Chromium Code Reviews| Index: reflectable/lib/src/transformer_implementation.dart |
| diff --git a/reflectable/lib/src/transformer_implementation.dart b/reflectable/lib/src/transformer_implementation.dart |
| index 8bb6decee619f24e8f7f1b4d11f491640db0e8f2..66ada78711fc6b21f905d494e7ac2f7ca02db9e7 100644 |
| --- a/reflectable/lib/src/transformer_implementation.dart |
| +++ b/reflectable/lib/src/transformer_implementation.dart |
| @@ -525,18 +525,32 @@ class _ReflectorDomain { |
| /// `_reflector` to behave correctly. |
| String _generateCode( |
| _ImportCollector importCollector, TransformLogger logger) { |
| - Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); |
| + // Library related collections. |
| + Enumerator<_LibraryDomain> libraries = new Enumerator<_LibraryDomain>(); |
| + Map<LibraryElement, _LibraryDomain> libraryMap = |
| + <LibraryElement, _LibraryDomain>{}; |
| + Enumerator<TopLevelVariableElement> topLevelVariables = |
| + new Enumerator<TopLevelVariableElement>(); |
| + |
| + // Class related collections. |
| Enumerator<FieldElement> fields = new Enumerator<FieldElement>(); |
| Enumerator<ParameterElement> parameters = |
| new Enumerator<ParameterElement>(); |
| - Enumerator<LibraryElement> libraries = new Enumerator<LibraryElement>(); |
| Set<String> instanceGetterNames = new Set<String>(); |
| Set<String> instanceSetterNames = new Set<String>(); |
| + // Library and class related collections. |
| + Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); |
| + |
| // Fill in [libraries], [members], [fields], [parameters], |
| // [instanceGetterNames], and [instanceSetterNames]. |
| for (LibraryElement library in _libraries) { |
| - libraries.add(library); |
| + _LibraryDomain libraryDomain = _createLibraryDomain(library, this); |
| + libraries.add(libraryDomain); |
| + libraryMap[library] = libraryDomain; |
| + libraryDomain._declarations.forEach(members.add); |
| + libraryDomain._declaredParameters.forEach(parameters.add); |
| + libraryDomain._declaredVariables.forEach(topLevelVariables.add); |
| } |
| for (_ClassDomain classDomain in classes.domains) { |
| // Gather the behavioral interface into [members]. Note that |
| @@ -588,13 +602,25 @@ class _ReflectorDomain { |
| }); |
| } |
| + // Find the offsets of fields and of methods and functions in members. |
| + int fieldsOffset = topLevelVariables.length; |
| + int methodsOffset = fieldsOffset + fields.length; |
| + |
| // Generate code for creation of class mirrors. |
| String classMirrorsCode = _formatAsList( |
| "m.ClassMirror", |
| _capabilities._impliesTypes |
| ? classes.domains.map((_ClassDomain classDomain) => |
| - _classMirrorCode(classDomain, fields, members, libraries, |
| - importCollector, logger)) |
| + _classMirrorCode( |
| + classDomain, |
| + fields, |
| + fieldsOffset, |
| + methodsOffset, |
| + members, |
| + libraries, |
| + libraryMap, |
| + importCollector, |
| + logger)) |
| : <String>[]); |
| // Generate code for creation of getter and setter closures. |
| @@ -630,8 +656,9 @@ class _ReflectorDomain { |
| librariesCode = "null"; |
| } else { |
| librariesCode = _formatAsList("m.LibraryMirror", |
| - libraries.items.map((LibraryElement library) { |
| - return _libraryMirrorCode(library, importCollector, logger); |
| + libraries.items.map((_LibraryDomain library) { |
| + return _libraryMirrorCode(library, members, topLevelVariables, |
| + fields.length, importCollector, logger); |
| })); |
| } |
| @@ -691,8 +718,7 @@ class _ReflectorDomain { |
| Iterable<Element> getters = <Iterable<Element>>[ |
| part.accessors |
| .where((PropertyAccessorElement accessor) => accessor.isGetter), |
| - part.functions, |
| - part.topLevelVariables |
| + part.functions |
| ].expand((Iterable<Element> elements) => elements); |
| return getters.where((Element getter) => |
| _capabilities.supportsTopLevelInvoke(getter.name, getter.metadata)); |
| @@ -703,9 +729,7 @@ class _ReflectorDomain { |
| return library.units.map((CompilationUnitElement part) { |
| Iterable setters = <Iterable<Element>>[ |
| part.accessors |
| - .where((PropertyAccessorElement accessor) => accessor.isSetter), |
| - part.topLevelVariables |
| - .where((TopLevelVariableElement variable) => !variable.isFinal) |
| + .where((PropertyAccessorElement accessor) => accessor.isSetter) |
| ].expand((Iterable<Element> elements) => elements); |
| return setters.where((Element setter) => |
| _capabilities.supportsTopLevelInvoke(setter.name, setter.metadata)); |
| @@ -715,15 +739,20 @@ class _ReflectorDomain { |
| String _classMirrorCode( |
| _ClassDomain classDomain, |
| Enumerator<FieldElement> fields, |
| + int fieldsOffset, |
| + int methodsOffset, |
| Enumerator<ExecutableElement> members, |
| - Enumerator<LibraryElement> libraries, |
| + Enumerator<_LibraryDomain> libraries, |
| + Map<LibraryElement, _LibraryDomain> libraryMap, |
| _ImportCollector importCollector, |
| TransformLogger logger) { |
| + int descriptor = _classDescriptor(classDomain._classElement); |
| + |
| // Fields go first in [memberMirrors], so they will get the |
| // same index as in [fields]. |
| Iterable<int> fieldsIndices = |
| classDomain._declaredFields.map((FieldElement element) { |
| - return fields.indexOf(element); |
| + return fields.indexOf(element) + fieldsOffset; |
| }); |
| // All the elements in the behavioral interface go after the |
| @@ -742,17 +771,17 @@ class _ReflectorDomain { |
| int index = members.indexOf(element); |
| return index == null |
| ? constants.NO_CAPABILITY_INDEX |
| - : index + fields.length; |
| + : index + methodsOffset; |
| }); |
| - String declarationsCode = "<int>[${constants |
| - .NO_CAPABILITY_INDEX}]"; |
| - if (_capabilities._impliesDeclarations) { |
| - List<int> declarationsIndices = <int>[] |
| - ..addAll(fieldsIndices) |
| - ..addAll(methodsIndices); |
| - declarationsCode = _formatAsList("int", declarationsIndices); |
| - } |
| + String declarationsCode = _capabilities._impliesDeclarations |
| + ? _formatAsList( |
| + "int", |
| + () sync* { |
| + yield* fieldsIndices; |
| + yield* methodsIndices; |
| + }()) |
| + : "<int>[${constants.NO_CAPABILITY_INDEX}]"; |
| // All instance members belong to the behavioral interface, so they |
| // also get an offset of `fields.length`. |
| @@ -764,7 +793,7 @@ class _ReflectorDomain { |
| int index = members.indexOf(element); |
| return index == null |
| ? constants.NO_CAPABILITY_INDEX |
| - : index + fields.length; |
| + : index + methodsOffset; |
| })); |
| // All static members belong to the behavioral interface, so they |
| @@ -774,7 +803,7 @@ class _ReflectorDomain { |
| int index = members.indexOf(element); |
| return index == null |
| ? constants.NO_CAPABILITY_INDEX |
| - : index + fields.length; |
| + : index + methodsOffset; |
| })); |
| ClassElement classElement = classDomain._classElement; |
| @@ -832,7 +861,7 @@ class _ReflectorDomain { |
| if (mixinIndex == null) mixinIndex = constants.NO_CAPABILITY_INDEX; |
| int ownerIndex = _capabilities.supportsLibraries |
| - ? libraries.indexOf(classElement.library) |
| + ? libraries.indexOf(libraryMap[classElement.library]) |
| : constants.NO_CAPABILITY_INDEX; |
| String superinterfaceIndices = _formatAsList( |
| @@ -853,7 +882,7 @@ class _ReflectorDomain { |
| int classIndex = classes.indexOf(classElement); |
| String result = 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", ' |
| - 'r"${_qualifiedName(classElement)}", $classIndex, ' |
| + 'r"${_qualifiedName(classElement)}", $descriptor, $classIndex, ' |
| '${_constConstructionCode(importCollector)}, ' |
| '$declarationsCode, $instanceMembersCode, $staticMembersCode, ' |
| '$superclassIndex, $staticGettersCode, $staticSettersCode, ' |
| @@ -950,15 +979,19 @@ class _ReflectorDomain { |
| if (classElement is MixinApplication && classElement.declaredName == null) { |
| return 'new r.FakeType(r"${_qualifiedName(classElement)}")'; |
| } |
| - if (classElement is! MixinApplication && classElement.type.isDynamic) { |
| - return "dynamic"; |
| - } |
| + if (classElement.type.isDynamic) return "dynamic"; |
| String prefix = importCollector._getPrefix(classElement.library); |
| return "$prefix.${classElement.name}"; |
| } |
| - String _libraryMirrorCode(LibraryElement library, |
| - _ImportCollector importCollector, TransformLogger logger) { |
| + String _libraryMirrorCode( |
| + _LibraryDomain libraryDomain, |
| + Enumerator<ExecutableElement> members, |
| + Enumerator<TopLevelVariableElement> variables, |
| + int fieldsLength, |
| + _ImportCollector importCollector, |
| + TransformLogger logger) { |
| + LibraryElement library = libraryDomain._libraryElement; |
| String gettersCode = _formatAsMap( |
| _gettersOfLibrary(library).map((PropertyAccessorElement getter) { |
| return _topLevelGettingClosure(importCollector, library, getter.name); |
| @@ -968,6 +1001,31 @@ class _ReflectorDomain { |
| return topLevelSettingClosure(importCollector, library, setter.name); |
| })); |
| + // Fields go first in [memberMirrors], so they will get the |
| + // same index as in [fields]. |
| + Iterable<int> variableIndices = |
| + libraryDomain._declaredVariables.map((TopLevelVariableElement element) { |
| + return variables.indexOf(element); |
| + }); |
| + |
| + // All the elements in the behavioral interface go after the |
| + // fields in [memberMirrors], so they must get an offset of |
| + // `fields.length` on the index. |
| + Iterable<int> methodsIndices = libraryDomain._declarations |
| + .where(_executableIsntImplicitGetterOrSetter) |
| + .map((ExecutableElement element) { |
| + int index = members.indexOf(element); |
| + return index + fieldsLength; |
| + }); |
| + |
| + String declarationsCode = "<int>[${constants.NO_CAPABILITY_INDEX}]"; |
| + if (_capabilities._impliesDeclarations) { |
| + List<int> declarationsIndices = <int>[] |
| + ..addAll(variableIndices) |
| + ..addAll(methodsIndices); |
| + declarationsCode = _formatAsList("int", declarationsIndices); |
| + } |
| + |
| // TODO(sigurdm) clarify: Find out how to get good uri's in a |
| // transformer. |
| // TODO(sigurdm) implement: Check for `uriCapability`. |
| @@ -982,7 +1040,8 @@ class _ReflectorDomain { |
| } |
| return 'new r.LibraryMirrorImpl(r"${library.name}", $uriCode, ' |
| - '$gettersCode, $settersCode, $metadataCode)'; |
| + '${_constConstructionCode(importCollector)}, ' |
| + '$declarationsCode, $gettersCode, $settersCode, $metadataCode)'; |
| } |
| String _parameterMirrorCode( |
| @@ -1304,10 +1363,9 @@ String _gettingClosure(String getterName) { |
| // Auxiliary function used by `_generateCode`. |
| String _settingClosure(String setterName) { |
| - assert(setterName.substring(setterName.length - 1) == "="); |
| - // The [setterName] includes the "=", remove it. |
| - String name = setterName.substring(0, setterName.length - 1); |
| - |
| + String name = setterName.substring(setterName.length - 1) == "=" |
|
sigurdm
2015/10/09 07:52:04
Can we now get a setterName not ending in '='? Whe
eernst
2015/10/09 10:09:05
I found `someName = value` in the generated code a
sigurdm
2015/10/09 10:47:20
I think we should track down where that happens. M
eernst
2015/10/09 11:24:14
Did that, and it doesn't fail now. I think this ma
|
| + ? setterName.substring(0, setterName.length - 1) |
| + : setterName; |
| return 'r"$setterName": (dynamic instance, value) => ' |
| 'instance.$name = value'; |
| } |
| @@ -1350,34 +1408,101 @@ String topLevelSettingClosure(_ImportCollector importCollector, |
| return 'r"$setterName": (value) => $prefix.$name = value'; |
| } |
| +/// Information about reflectability for a given library. |
| +class _LibraryDomain { |
| + /// Element describing the target library. |
| + final LibraryElement _libraryElement; |
| + |
| + /// Fields declared by [_libraryElement] and included for reflection support, |
| + /// according to the reflector described by the [_reflectorDomain]; |
| + /// obtained by filtering `_libraryElement.fields`. |
| + final Iterable<TopLevelVariableElement> _declaredVariables; |
| + |
| + /// Methods which are declared by [_libraryElement] and included for |
| + /// reflection support, according to the reflector described by |
| + /// [_reflectorDomain]; obtained by filtering `_libraryElement.functions`. |
| + final Iterable<FunctionElement> _declaredFunctions; |
| + |
| + /// Formal parameters declared by one of the [_declaredFunctions]. |
| + final Iterable<ParameterElement> _declaredParameters; |
| + |
| + /// Getters and setters possessed by [_libraryElement] and included for |
| + /// reflection support, according to the reflector described by |
| + /// [_reflectorDomain]; obtained by filtering `_libraryElement.accessors`. |
| + /// Note that it includes declared as well as synthetic accessors, |
| + /// implicitly created as getters/setters for fields. |
| + final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; |
| + |
| + /// The reflector domain that holds [this] object as one of its |
| + /// library domains. |
| + final _ReflectorDomain _reflectorDomain; |
| + |
| + _LibraryDomain( |
| + this._libraryElement, |
| + this._declaredVariables, |
| + this._declaredFunctions, |
| + this._declaredParameters, |
| + this._declaredAndImplicitAccessors, |
| + this._reflectorDomain); |
| + |
| + String get _simpleName { |
| + return _libraryElement.name; |
| + } |
| + |
| + /// Returns the declared methods, accessors and constructors in |
| + /// [_classElement]. Note that this includes synthetic getters and |
| + /// setters, and omits fields; in other words, it provides the |
| + /// behavioral point of view on the class. Also note that this is not |
| + /// the same semantics as that of `declarations` in [ClassMirror]. |
| + Iterable<ExecutableElement> get _declarations sync* { |
| + yield* _declaredFunctions; |
| + yield* _declaredAndImplicitAccessors; |
| + } |
| + |
| + String toString() { |
| + return "LibraryDomain($_libraryElement)"; |
| + } |
| + |
| + bool operator ==(Object other) { |
| + if (other is _LibraryDomain) { |
| + return _libraryElement == other._libraryElement && |
| + _reflectorDomain == other._reflectorDomain; |
| + } else { |
| + return false; |
| + } |
| + } |
| + |
| + int get hashCode => _libraryElement.hashCode ^ _reflectorDomain.hashCode; |
| +} |
| + |
| /// Information about reflectability for a given class. |
| class _ClassDomain { |
| /// Element describing the target class. |
| final ClassElement _classElement; |
| - /// Fields declared by [classElement] and included for reflection support, |
| - /// according to the reflector described by the [reflectorDomain]; |
| - /// obtained by filtering `classElement.fields`. |
| + /// Fields declared by [_classElement] and included for reflection support, |
| + /// according to the reflector described by the [_reflectorDomain]; |
| + /// obtained by filtering `_classElement.fields`. |
| final Iterable<FieldElement> _declaredFields; |
| - /// Methods which are declared by [classElement] and included for |
| + /// Methods which are declared by [_classElement] and included for |
| /// reflection support, according to the reflector described by |
| - /// [reflectorDomain]; obtained by filtering `classElement.methods`. |
| + /// [reflectorDomain]; obtained by filtering `_classElement.methods`. |
| final Iterable<MethodElement> _declaredMethods; |
| /// Formal parameters declared by one of the [_declaredMethods]. |
| final Iterable<ParameterElement> _declaredParameters; |
| - /// Getters and setters possessed by [classElement] and included for |
| + /// Getters and setters possessed by [_classElement] and included for |
| /// reflection support, according to the reflector described by |
| - /// [reflectorDomain]; obtained by filtering `classElement.accessors`. |
| + /// [reflectorDomain]; obtained by filtering `_classElement.accessors`. |
| /// Note that it includes declared as well as synthetic accessors, |
| /// implicitly created as getters/setters for fields. |
| final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; |
| - /// Constructors declared by [classElement] and included for reflection |
| - /// support, according to the reflector described by [reflectorDomain]; |
| - /// obtained by filtering `classElement.constructors`. |
| + /// Constructors declared by [_classElement] and included for reflection |
| + /// support, according to the reflector described by [_reflectorDomain]; |
| + /// obtained by filtering `_classElement.constructors`. |
| final Iterable<ConstructorElement> _constructors; |
| /// The reflector domain that holds [this] object as one of its |
| @@ -1641,7 +1766,7 @@ class _Capabilities { |
| return true; |
| } |
| // Quantifying capabilities do not influence the availability |
| - // of reflection support for top level invocation. |
| + // of reflection support for top-level invocation. |
| } |
| // All options exhausted, give up. |
| @@ -1942,7 +2067,7 @@ class TransformerImplementation { |
| bool isOk = checkInheritance(result.value.type, focusClass.type); |
| return isOk ? result.value.type.element : null; |
| } else { |
| - // Not a const top level variable, not relevant. |
| + // Not a const top-level variable, not relevant. |
| return null; |
| } |
| } |
| @@ -2133,7 +2258,9 @@ class TransformerImplementation { |
| for (InterfaceType mixin in type.mixins) { |
| ClassElement mixinElement = mixin.element; |
| ClassElement subClass = mixin == type.mixins.last ? type : null; |
| - String name = subClass == null ? null : type.name; |
| + String name = subClass == null |
|
sigurdm
2015/10/09 07:52:04
Could be
```
String name = subClass ?? (type.isMix
eernst
2015/10/09 10:09:04
It's a bit more tricky than that: If `subClass ==
sigurdm
2015/10/09 10:47:20
Oops - you're right!
|
| + ? null |
| + : (type.isMixinApplication ? type.name : null); |
| MixinApplication mixinApplication = new MixinApplication( |
| name, superclass, mixinElement, type.library, subClass); |
| domain._classes.add(mixinApplication); |
| @@ -2221,6 +2348,15 @@ class TransformerImplementation { |
| addClassDomain(type, reflector); |
| } |
| } |
| + for (FunctionElement function in unit.functions) { |
| + for (ClassElement reflector in getReflectors( |
| + _qualifiedFunctionName(function), function.metadata)) { |
| + // We just add the library here, the function itself will be |
| + // supported using `invoke` and `declarations` of that library |
| + // mirror. |
| + addLibrary(library, reflector); |
| + } |
| + } |
| } |
| } |
| @@ -2588,6 +2724,17 @@ bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) { |
| } |
| /// Returns an integer encoding of the kind and attributes of the given |
| +/// class. |
| +int _classDescriptor(ClassElement element) { |
| + int result = constants.clazz; |
| + if (element.isPrivate) result |= constants.privateAttribute; |
| + if (element.isSynthetic) result |= constants.syntheticAttribute; |
| + if (element.isAbstract) result |= constants.abstractAttribute; |
| + if (element.isEnum) result |= constants.enumAttribute; |
| + return result; |
| +} |
| + |
| +/// Returns an integer encoding of the kind and attributes of the given |
| /// field. |
| int _fieldDescriptor(FieldElement element) { |
| int result = constants.field; |
| @@ -2940,6 +3087,48 @@ String _extractMetadataCode(Element element, Resolver resolver, |
| return _formatAsList("Object", metadataParts); |
| } |
| +Iterable<TopLevelVariableElement> _extractDeclaredVariables( |
|
sigurdm
2015/10/09 07:52:04
Give these functions a (short) comment
eernst
2015/10/09 10:09:05
Done.
|
| + LibraryElement libraryElement, _Capabilities capabilities) sync* { |
| + for (CompilationUnitElement unit in libraryElement.units) { |
| + for (TopLevelVariableElement variable in unit.topLevelVariables) { |
| + if (variable.isPrivate || variable.isSynthetic) continue; |
| + // TODO(eernst) clarify: Do we want to subsume variables under invoke? |
| + if (capabilities.supportsTopLevelInvoke( |
| + variable.name, variable.metadata)) { |
| + yield variable; |
| + } |
| + } |
| + } |
| +} |
| + |
| +Iterable<FunctionElement> _extractDeclaredFunctions( |
| + LibraryElement libraryElement, _Capabilities capabilities) sync* { |
| + for (CompilationUnitElement unit in libraryElement.units) { |
| + for (FunctionElement function in unit.functions) { |
| + if (function.isPrivate) continue; |
| + if (capabilities.supportsTopLevelInvoke( |
| + function.name, function.metadata)) { |
| + yield function; |
| + } |
| + } |
| + } |
| +} |
| + |
| +Iterable<ParameterElement> _extractDeclaredFunctionParameters( |
| + Iterable<FunctionElement> declaredFunctions, |
| + Iterable<PropertyAccessorElement> accessors) { |
| + List<ParameterElement> result = <ParameterElement>[]; |
| + for (FunctionElement declaredFunction in declaredFunctions) { |
| + result.addAll(declaredFunction.parameters); |
| + } |
| + for (PropertyAccessorElement accessor in accessors) { |
| + if (accessor.isSetter) { |
| + result.addAll(accessor.parameters); |
| + } |
| + } |
| + return result; |
| +} |
| + |
| Iterable<FieldElement> _extractDeclaredFields( |
| ClassElement classElement, _Capabilities capabilities) { |
| return classElement.fields.where((FieldElement field) { |
| @@ -2981,6 +3170,19 @@ Iterable<ParameterElement> _extractDeclaredParameters( |
| return result; |
| } |
| +Iterable<PropertyAccessorElement> _declaredAndImplicitLibraryAccessors( |
| + LibraryElement libraryElement, _Capabilities capabilities) sync* { |
| + for (CompilationUnitElement unit in libraryElement.units) { |
| + for (PropertyAccessorElement accessor in unit.accessors) { |
| + if (accessor.isPrivate) continue; |
| + if (capabilities.supportsTopLevelInvoke( |
| + accessor.name, accessor.metadata)) { |
| + yield accessor; |
| + } |
| + } |
| + } |
| +} |
| + |
| /// Returns the [PropertyAccessorElement]s which are the accessors |
| /// of the given [classElement], including both the declared ones |
| /// and the implicitly generated ones corresponding to fields. This |
| @@ -3009,6 +3211,26 @@ Iterable<ConstructorElement> _declaredConstructors( |
| }); |
| } |
| +_LibraryDomain _createLibraryDomain( |
| + LibraryElement library, _ReflectorDomain domain) { |
| + List<TopLevelVariableElement> declaredVariablesOfLibrary = |
| + _extractDeclaredVariables(library, domain._capabilities).toList(); |
| + List<FunctionElement> declaredFunctionsOfLibrary = |
| + _extractDeclaredFunctions(library, domain._capabilities).toList(); |
| + List<PropertyAccessorElement> declaredAndImplicitAccessorsOfLibrary = |
| + _declaredAndImplicitLibraryAccessors(library, domain._capabilities); |
| + List<ParameterElement> declaredParametersOfLibrary = |
| + _extractDeclaredFunctionParameters( |
| + declaredFunctionsOfLibrary, declaredAndImplicitAccessorsOfLibrary); |
| + return new _LibraryDomain( |
| + library, |
| + declaredVariablesOfLibrary, |
| + declaredFunctionsOfLibrary, |
| + declaredParametersOfLibrary, |
| + declaredAndImplicitAccessorsOfLibrary, |
| + domain); |
| +} |
| + |
| _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) { |
| if (type is MixinApplication) { |
| List<FieldElement> declaredFieldsOfClass = |
| @@ -3116,13 +3338,16 @@ class MixinApplication implements ClassElement { |
| } |
| @override |
| + String get displayName => name; |
| + |
| + @override |
| List<InterfaceType> get interfaces => <InterfaceType>[]; |
| @override |
| List<ElementAnnotation> get metadata => <ElementAnnotation>[]; |
| @override |
| - bool get isSynthetic => declaredName != null; |
| + bool get isSynthetic => declaredName == null; |
| // Note that the `InterfaceTypeImpl` may well call methods on this |
| // `MixinApplication` whose body is `_unImplemented()`, but it still provides |
| @@ -3155,6 +3380,13 @@ class MixinApplication implements ClassElement { |
| bool get isMixinApplication => declaredName != null; |
| @override |
| + bool get isAbstract => !isMixinApplication || mixin.isAbstract; |
| + |
| + @override |
| + // TODO(eernst) clarify: Is this test correct? Are all cases possible? |
| + bool get isEnum => mixin.isEnum || superclass.isEnum; |
|
sigurdm
2015/10/09 07:52:04
As I understand it you cannot mix an enum in or su
eernst
2015/10/09 10:09:04
Yep, the spec confirms that. Removed the comment,
|
| + |
| + @override |
| NamedCompilationUnitMember computeNode() => |
| declaredName != null ? subclass.computeNode() : null; |
| @@ -3196,12 +3428,6 @@ class MixinApplication implements ClassElement { |
| bool get hasStaticMember => _unImplemented(); |
| @override |
| - bool get isAbstract => _unImplemented(); |
| - |
| - @override |
| - bool get isEnum => _unImplemented(); |
| - |
| - @override |
| bool get isOrInheritsProxy => _unImplemented(); |
| @override |
| @@ -3297,9 +3523,6 @@ class MixinApplication implements ClassElement { |
| get context => _unImplemented(); |
| @override |
| - String get displayName => _unImplemented(); |
| - |
| - @override |
| Element get enclosingElement => _unImplemented(); |
| @override |
| @@ -3356,3 +3579,9 @@ String _qualifiedName(ClassElement classElement) { |
| ? "null" |
| : "${classElement.library.name}.${classElement.name}"; |
| } |
| + |
| +String _qualifiedFunctionName(FunctionElement functionElement) { |
| + return functionElement == null |
| + ? "null" |
| + : "${functionElement.library.name}.${functionElement.name}"; |
| +} |