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}"; |
+} |