Chromium Code Reviews| Index: pkg/analyzer/lib/src/dart/element/element.dart |
| diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart |
| index 6ce99401ebb2bfe458052ae9b0d6260aaff4bfa6..cfd009f1ff4921dc698c68cce95b7a789d4ac490 100644 |
| --- a/pkg/analyzer/lib/src/dart/element/element.dart |
| +++ b/pkg/analyzer/lib/src/dart/element/element.dart |
| @@ -44,38 +44,11 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; |
| /** |
| - * For classes which are not mixin applications, a list containing all of the |
| - * constructors contained in this class, or `null` if the list of |
| - * constructors has not yet been built. |
| - * |
| - * For classes which are mixin applications, the list of constructors is |
| - * computed on the fly by the [constructors] getter, and this field is |
| - * `null`. |
| - */ |
| - List<ConstructorElement> _constructors; |
| - |
| - /** |
| * A list containing all of the fields contained in this class. |
| */ |
| List<FieldElement> _fields = FieldElement.EMPTY_LIST; |
| /** |
| - * A list containing all of the mixins that are applied to the class being |
| - * extended in order to derive the superclass of this class. |
| - */ |
| - List<InterfaceType> _mixins; |
| - |
| - /** |
| - * A list containing all of the interfaces that are implemented by this class. |
| - */ |
| - List<InterfaceType> _interfaces; |
| - |
| - /** |
| - * A list containing all of the methods contained in this class. |
| - */ |
| - List<MethodElement> _methods = MethodElement.EMPTY_LIST; |
| - |
| - /** |
| * The superclass of the class, or `null` if the class does not have an |
| * explicit superclass. |
| */ |
| @@ -89,17 +62,6 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| InterfaceType type; |
| /** |
| - * A list containing all of the type parameters defined for this class. |
| - */ |
| - List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; |
| - |
| - /** |
| - * A flag indicating whether the types associated with the instance members of |
| - * this class have been inferred. |
| - */ |
| - bool hasBeenInferred = false; |
| - |
| - /** |
| * Initialize a newly created class element to have the given [name] at the |
| * given [offset] in the file that contains the declaration of this element. |
| */ |
| @@ -117,13 +79,6 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| CompilationUnitElementImpl enclosingUnit) |
| : super.forSerialized(enclosingUnit); |
| - /** |
| - * Set whether this class is abstract. |
| - */ |
| - void set abstract(bool isAbstract) { |
| - setModifier(Modifier.ABSTRACT, isAbstract); |
| - } |
| - |
| @override |
| List<PropertyAccessorElement> get accessors => _accessors; |
| @@ -138,81 +93,8 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| } |
| @override |
| - List<InterfaceType> get allSupertypes { |
| - List<InterfaceType> list = new List<InterfaceType>(); |
| - _collectAllSupertypes(list); |
| - return list; |
| - } |
| - |
| - @override |
| - List<ConstructorElement> get constructors { |
| - if (!isMixinApplication) { |
| - assert(_constructors != null); |
| - return _constructors ?? ConstructorElement.EMPTY_LIST; |
| - } |
| - return _computeMixinAppConstructors(); |
| - } |
| - |
| - /** |
| - * Set the constructors contained in this class to the given [constructors]. |
| - * |
| - * Should only be used for class elements that are not mixin applications. |
| - */ |
| - void set constructors(List<ConstructorElement> constructors) { |
| - assert(!isMixinApplication); |
| - for (ConstructorElement constructor in constructors) { |
| - (constructor as ConstructorElementImpl).enclosingElement = this; |
| - } |
| - this._constructors = constructors; |
| - } |
| - |
| - @override |
| String get displayName => name; |
| - /** |
| - * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should |
| - * be reported for this class. |
| - */ |
| - bool get doesMixinLackConstructors { |
| - if (!isMixinApplication && mixins.isEmpty) { |
| - // This class is not a mixin application and it doesn't have a "with" |
| - // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is |
| - // inapplicable. |
| - return false; |
| - } |
| - if (supertype == null) { |
| - // Should never happen, since Object is the only class that has no |
| - // supertype, and it should have been caught by the test above. |
| - assert(false); |
| - return false; |
| - } |
| - // Find the nearest class in the supertype chain that is not a mixin |
| - // application. |
| - ClassElement nearestNonMixinClass = supertype.element; |
| - if (nearestNonMixinClass.isMixinApplication) { |
| - // Use a list to keep track of the classes we've seen, so that we won't |
| - // go into an infinite loop in the event of a non-trivial loop in the |
| - // class hierarchy. |
| - List<ClassElement> classesSeen = <ClassElement>[this]; |
| - while (nearestNonMixinClass.isMixinApplication) { |
| - if (classesSeen.contains(nearestNonMixinClass)) { |
| - // Loop in the class hierarchy (which is reported elsewhere). Don't |
| - // confuse the user with further errors. |
| - return false; |
| - } |
| - classesSeen.add(nearestNonMixinClass); |
| - if (nearestNonMixinClass.supertype == null) { |
| - // Should never happen, since Object is the only class that has no |
| - // supertype, and it is not a mixin application. |
| - assert(false); |
| - return false; |
| - } |
| - nearestNonMixinClass = nearestNonMixinClass.supertype.element; |
| - } |
| - } |
| - return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); |
| - } |
| - |
| @override |
| TypeParameterizedElementMixin get enclosingTypeParameterContext => null; |
| @@ -230,330 +112,80 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| } |
| @override |
| - bool get hasNonFinalField { |
| - List<ClassElement> classesToVisit = new List<ClassElement>(); |
| - HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| - classesToVisit.add(this); |
| - while (!classesToVisit.isEmpty) { |
| - ClassElement currentElement = classesToVisit.removeAt(0); |
| - if (visitedClasses.add(currentElement)) { |
| - // check fields |
| - for (FieldElement field in currentElement.fields) { |
| - if (!field.isFinal && |
| - !field.isConst && |
| - !field.isStatic && |
| - !field.isSynthetic) { |
| - return true; |
| - } |
| - } |
| - // check mixins |
| - for (InterfaceType mixinType in currentElement.mixins) { |
| - ClassElement mixinElement = mixinType.element; |
| - classesToVisit.add(mixinElement); |
| - } |
| - // check super |
| - InterfaceType supertype = currentElement.supertype; |
| - if (supertype != null) { |
| - ClassElement superElement = supertype.element; |
| - if (superElement != null) { |
| - classesToVisit.add(superElement); |
| - } |
| - } |
| - } |
| - } |
| - // not found |
| - return false; |
| - } |
| + bool get isEnum; |
| @override |
| - bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER); |
| + ElementKind get kind => ElementKind.CLASS; |
| /** |
| - * Set whether this class references 'super'. |
| + * Return resynthesized type parameter elements. |
| */ |
| - void set hasReferenceToSuper(bool isReferencedSuper) { |
| - setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); |
| - } |
| - |
| - @override |
| - bool get hasStaticMember { |
| - for (MethodElement method in _methods) { |
| - if (method.isStatic) { |
| - return true; |
| - } |
| - } |
| - for (PropertyAccessorElement accessor in _accessors) { |
| - if (accessor.isStatic) { |
| - return true; |
| - } |
| - } |
| - return false; |
| + List<TypeParameterElement> get resynthesizedTypeParameters { |
| + return super.typeParameters; |
| } |
| @override |
| - List<InterfaceType> get interfaces { |
| - return _interfaces ?? const <InterfaceType>[]; |
| - } |
| - |
| - void set interfaces(List<InterfaceType> interfaces) { |
| - _interfaces = interfaces; |
| - } |
| + TypeParameterizedElementMixin get typeParameterContext => this; |
| @override |
| - bool get isAbstract { |
| - return hasModifier(Modifier.ABSTRACT); |
| - } |
| + List<UnlinkedTypeParam> get unlinkedTypeParams => const <UnlinkedTypeParam>[]; |
| @override |
| - bool get isEnum; |
| + accept(ElementVisitor visitor) => visitor.visitClassElement(this); |
| @override |
| - bool get isMixinApplication { |
| - return hasModifier(Modifier.MIXIN_APPLICATION); |
| + NamedCompilationUnitMember computeNode() { |
| + if (isEnum) { |
| + return getNodeMatching((node) => node is EnumDeclaration); |
| + } else { |
| + return getNodeMatching( |
| + (node) => node is ClassDeclaration || node is ClassTypeAlias); |
| + } |
| } |
| @override |
| - bool get isOrInheritsProxy => |
| - _safeIsOrInheritsProxy(this, new HashSet<ClassElement>()); |
| - |
| - @override |
| - bool get isProxy { |
| - for (ElementAnnotation annotation in metadata) { |
| - if (annotation.isProxy) { |
| - return true; |
| + ElementImpl getChild(String identifier) { |
| + // |
| + // The casts in this method are safe because the set methods would have |
| + // thrown a CCE if any of the elements in the arrays were not of the |
| + // expected types. |
| + // |
| + for (PropertyAccessorElement accessor in _accessors) { |
| + PropertyAccessorElementImpl accessorImpl = accessor; |
| + if (accessorImpl.identifier == identifier) { |
| + return accessorImpl; |
| } |
| } |
| - return false; |
| + for (FieldElement field in _fields) { |
| + FieldElementImpl fieldImpl = field; |
| + if (fieldImpl.identifier == identifier) { |
| + return fieldImpl; |
| + } |
| + } |
| + return null; |
| } |
| @override |
| - bool get isValidMixin { |
| - if (!context.analysisOptions.enableSuperMixins) { |
| - if (hasReferenceToSuper) { |
| - return false; |
| - } |
| - if (!supertype.isObject) { |
| - return false; |
| - } |
| - } |
| - for (ConstructorElement constructor in constructors) { |
| - if (!constructor.isSynthetic && !constructor.isFactory) { |
| - return false; |
| + FieldElement getField(String name) { |
| + for (FieldElement fieldElement in _fields) { |
| + if (name == fieldElement.name) { |
| + return fieldElement; |
| } |
| } |
| - return true; |
| + return null; |
| } |
| @override |
| - ElementKind get kind => ElementKind.CLASS; |
| - |
| - @override |
| - List<MethodElement> get methods => _methods; |
| - |
| - /** |
| - * Set the methods contained in this class to the given [methods]. |
| - */ |
| - void set methods(List<MethodElement> methods) { |
| - for (MethodElement method in methods) { |
| - (method as MethodElementImpl).enclosingElement = this; |
| - } |
| - this._methods = methods; |
| - } |
| - |
| - /** |
| - * Set whether this class is a mixin application. |
| - */ |
| - void set mixinApplication(bool isMixinApplication) { |
| - setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); |
| - } |
| - |
| - @override |
| - List<InterfaceType> get mixins { |
| - return _mixins ?? const <InterfaceType>[]; |
| - } |
| - |
| - void set mixins(List<InterfaceType> mixins) { |
| - _mixins = mixins; |
| - } |
| - |
| - /** |
| - * Return resynthesized type parameter elements. |
| - */ |
| - List<TypeParameterElement> get resynthesizedTypeParameters { |
| - return super.typeParameters; |
| - } |
| - |
| - @override |
| - TypeParameterizedElementMixin get typeParameterContext => this; |
| - |
| - @override |
| - List<TypeParameterElement> get typeParameters { |
| - return _typeParameters; |
| - } |
| - |
| - /** |
| - * Set the type parameters defined for this class to the given |
| - * [typeParameters]. |
| - */ |
| - void set typeParameters(List<TypeParameterElement> typeParameters) { |
| - for (TypeParameterElement typeParameter in typeParameters) { |
| - (typeParameter as TypeParameterElementImpl).enclosingElement = this; |
| - } |
| - this._typeParameters = typeParameters; |
| - } |
| - |
| - @override |
| - List<UnlinkedTypeParam> get unlinkedTypeParams => const <UnlinkedTypeParam>[]; |
| - |
| - @override |
| - ConstructorElement get unnamedConstructor { |
| - for (ConstructorElement element in constructors) { |
| - String name = element.displayName; |
| - if (name == null || name.isEmpty) { |
| - return element; |
| - } |
| - } |
| - return null; |
| - } |
| - |
| - @override |
| - accept(ElementVisitor visitor) => visitor.visitClassElement(this); |
| - |
| - @override |
| - void appendTo(StringBuffer buffer) { |
| - if (isAbstract) { |
| - buffer.write('abstract '); |
| - } |
| - if (isEnum) { |
| - buffer.write('enum '); |
| - } else { |
| - buffer.write('class '); |
| - } |
| - String name = displayName; |
| - if (name == null) { |
| - buffer.write("{unnamed class}"); |
| - } else { |
| - buffer.write(name); |
| - } |
| - int variableCount = typeParameters.length; |
| - if (variableCount > 0) { |
| - buffer.write("<"); |
| - for (int i = 0; i < variableCount; i++) { |
| - if (i > 0) { |
| - buffer.write(", "); |
| - } |
| - (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); |
| - } |
| - buffer.write(">"); |
| - } |
| - if (supertype != null && !supertype.isObject) { |
| - buffer.write(' extends '); |
| - buffer.write(supertype.displayName); |
| - } |
| - if (mixins.isNotEmpty) { |
| - buffer.write(' with '); |
| - buffer.write(mixins.map((t) => t.displayName).join(', ')); |
| - } |
| - if (interfaces.isNotEmpty) { |
| - buffer.write(' implements '); |
| - buffer.write(interfaces.map((t) => t.displayName).join(', ')); |
| - } |
| - } |
| - |
| - @override |
| - NamedCompilationUnitMember computeNode() { |
| - if (isEnum) { |
| - return getNodeMatching((node) => node is EnumDeclaration); |
| - } else { |
| - return getNodeMatching( |
| - (node) => node is ClassDeclaration || node is ClassTypeAlias); |
| - } |
| - } |
| - |
| - @override |
| - ElementImpl getChild(String identifier) { |
| - // |
| - // The casts in this method are safe because the set methods would have |
| - // thrown a CCE if any of the elements in the arrays were not of the |
| - // expected types. |
| - // |
| - for (PropertyAccessorElement accessor in _accessors) { |
| - PropertyAccessorElementImpl accessorImpl = accessor; |
| - if (accessorImpl.identifier == identifier) { |
| - return accessorImpl; |
| - } |
| - } |
| - for (ConstructorElement constructor in _constructors) { |
| - ConstructorElementImpl constructorImpl = constructor; |
| - if (constructorImpl.identifier == identifier) { |
| - return constructorImpl; |
| - } |
| - } |
| - for (FieldElement field in _fields) { |
| - FieldElementImpl fieldImpl = field; |
| - if (fieldImpl.identifier == identifier) { |
| - return fieldImpl; |
| - } |
| - } |
| - for (MethodElement method in _methods) { |
| - MethodElementImpl methodImpl = method; |
| - if (methodImpl.identifier == identifier) { |
| - return methodImpl; |
| - } |
| - } |
| - for (TypeParameterElement typeParameter in typeParameters) { |
| - TypeParameterElementImpl typeParameterImpl = typeParameter; |
| - if (typeParameterImpl.identifier == identifier) { |
| - return typeParameterImpl; |
| - } |
| - } |
| - return null; |
| - } |
| - |
| - @override |
| - FieldElement getField(String name) { |
| - for (FieldElement fieldElement in _fields) { |
| - if (name == fieldElement.name) { |
| - return fieldElement; |
| - } |
| - } |
| - return null; |
| - } |
| - |
| - @override |
| - PropertyAccessorElement getGetter(String getterName) { |
| - int length = _accessors.length; |
| - for (int i = 0; i < length; i++) { |
| - PropertyAccessorElement accessor = _accessors[i]; |
| - if (accessor.isGetter && accessor.name == getterName) { |
| - return accessor; |
| - } |
| - } |
| - return null; |
| - } |
| - |
| - @override |
| - MethodElement getMethod(String methodName) { |
| - int length = _methods.length; |
| - for (int i = 0; i < length; i++) { |
| - MethodElement method = _methods[i]; |
| - if (method.name == methodName) { |
| - return method; |
| - } |
| - } |
| - return null; |
| - } |
| - |
| - @override |
| - ConstructorElement getNamedConstructor(String name) { |
| - for (ConstructorElement element in constructors) { |
| - String elementName = element.name; |
| - if (elementName != null && elementName == name) { |
| - return element; |
| - } |
| - } |
| - return null; |
| - } |
| + PropertyAccessorElement getGetter(String getterName) { |
| + int length = _accessors.length; |
| + for (int i = 0; i < length; i++) { |
| + PropertyAccessorElement accessor = _accessors[i]; |
| + if (accessor.isGetter && accessor.name == getterName) { |
| + return accessor; |
| + } |
| + } |
| + return null; |
| + } |
| @override |
| PropertyAccessorElement getSetter(String setterName) { |
| @@ -572,23 +204,6 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| } |
| @override |
| - bool isSuperConstructorAccessible(ConstructorElement constructor) { |
| - // If this class has no mixins, then all superclass constructors are |
| - // accessible. |
| - if (mixins.isEmpty) { |
| - return true; |
| - } |
| - // Otherwise only constructors that lack optional parameters are |
| - // accessible (see dartbug.com/19576). |
| - for (ParameterElement parameter in constructor.parameters) { |
| - if (parameter.parameterKind != ParameterKind.REQUIRED) { |
| - return false; |
| - } |
| - } |
| - return true; |
| - } |
| - |
| - @override |
| MethodElement lookUpConcreteMethod( |
| String methodName, LibraryElement library) => |
| _internalLookUpConcreteMethod( |
| @@ -635,131 +250,7 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| void visitChildren(ElementVisitor visitor) { |
| super.visitChildren(visitor); |
| safelyVisitChildren(_accessors, visitor); |
| - safelyVisitChildren(_constructors, visitor); |
| safelyVisitChildren(_fields, visitor); |
| - safelyVisitChildren(_methods, visitor); |
| - safelyVisitChildren(_typeParameters, visitor); |
| - } |
| - |
| - void _collectAllSupertypes(List<InterfaceType> supertypes) { |
| - List<InterfaceType> typesToVisit = new List<InterfaceType>(); |
| - List<ClassElement> visitedClasses = new List<ClassElement>(); |
| - typesToVisit.add(this.type); |
| - while (!typesToVisit.isEmpty) { |
| - InterfaceType currentType = typesToVisit.removeAt(0); |
| - ClassElement currentElement = currentType.element; |
| - if (!visitedClasses.contains(currentElement)) { |
| - visitedClasses.add(currentElement); |
| - if (!identical(currentType, this.type)) { |
| - supertypes.add(currentType); |
| - } |
| - InterfaceType supertype = currentType.superclass; |
| - if (supertype != null) { |
| - typesToVisit.add(supertype); |
| - } |
| - for (InterfaceType type in currentElement.interfaces) { |
| - typesToVisit.add(type); |
| - } |
| - for (InterfaceType type in currentElement.mixins) { |
| - ClassElement element = type.element; |
| - if (!visitedClasses.contains(element)) { |
| - supertypes.add(type); |
| - } |
| - } |
| - } |
| - } |
| - } |
| - |
| - /** |
| - * Compute a list of constructors for this class, which is a mixin |
| - * application. If specified, [visitedClasses] is a list of the other mixin |
| - * application classes which have been visited on the way to reaching this |
| - * one (this is used to detect circularities). |
| - */ |
| - List<ConstructorElement> _computeMixinAppConstructors( |
| - [List<ClassElementImpl> visitedClasses = null]) { |
| - // First get the list of constructors of the superclass which need to be |
| - // forwarded to this class. |
| - Iterable<ConstructorElement> constructorsToForward; |
| - if (supertype == null) { |
| - // Shouldn't ever happen, since the only class with no supertype is |
| - // Object, and it isn't a mixin application. But for safety's sake just |
| - // assume an empty list. |
| - assert(false); |
| - constructorsToForward = <ConstructorElement>[]; |
| - } else if (!supertype.element.isMixinApplication) { |
| - List<ConstructorElement> superclassConstructors = |
| - supertype.element.constructors; |
| - // Filter out any constructors with optional parameters (see |
| - // dartbug.com/15101). |
| - constructorsToForward = |
| - superclassConstructors.where(isSuperConstructorAccessible); |
| - } else { |
| - if (visitedClasses == null) { |
| - visitedClasses = <ClassElementImpl>[this]; |
| - } else { |
| - if (visitedClasses.contains(this)) { |
| - // Loop in the class hierarchy. Don't try to forward any |
| - // constructors. |
| - return <ConstructorElement>[]; |
| - } |
| - visitedClasses.add(this); |
| - } |
| - try { |
| - constructorsToForward = getImpl(supertype.element) |
| - ._computeMixinAppConstructors(visitedClasses); |
| - } finally { |
| - visitedClasses.removeLast(); |
| - } |
| - } |
| - |
| - // Figure out the type parameter substitution we need to perform in order |
| - // to produce constructors for this class. We want to be robust in the |
| - // face of errors, so drop any extra type arguments and fill in any missing |
| - // ones with `dynamic`. |
| - List<DartType> parameterTypes = |
| - TypeParameterTypeImpl.getTypes(supertype.typeParameters); |
| - List<DartType> argumentTypes = new List<DartType>.filled( |
| - parameterTypes.length, DynamicTypeImpl.instance); |
| - for (int i = 0; i < supertype.typeArguments.length; i++) { |
| - if (i >= argumentTypes.length) { |
| - break; |
| - } |
| - argumentTypes[i] = supertype.typeArguments[i]; |
| - } |
| - |
| - // Now create an implicit constructor for every constructor found above, |
| - // substituting type parameters as appropriate. |
| - return constructorsToForward |
| - .map((ConstructorElement superclassConstructor) { |
| - ConstructorElementImpl implicitConstructor = |
| - new ConstructorElementImpl(superclassConstructor.name, -1); |
| - implicitConstructor.synthetic = true; |
| - implicitConstructor.redirectedConstructor = superclassConstructor; |
| - implicitConstructor.returnType = type; |
| - List<ParameterElement> superParameters = superclassConstructor.parameters; |
| - int count = superParameters.length; |
| - if (count > 0) { |
| - List<ParameterElement> implicitParameters = |
| - new List<ParameterElement>(count); |
| - for (int i = 0; i < count; i++) { |
| - ParameterElement superParameter = superParameters[i]; |
| - ParameterElementImpl implicitParameter = |
| - new ParameterElementImpl(superParameter.name, -1); |
| - implicitParameter.const3 = superParameter.isConst; |
| - implicitParameter.final2 = superParameter.isFinal; |
| - implicitParameter.parameterKind = superParameter.parameterKind; |
| - implicitParameter.synthetic = true; |
| - implicitParameter.type = |
| - superParameter.type.substitute2(argumentTypes, parameterTypes); |
| - implicitParameters[i] = implicitParameter; |
| - } |
| - implicitConstructor.parameters = implicitParameters; |
| - } |
| - implicitConstructor.enclosingElement = this; |
| - implicitConstructor.type = new FunctionTypeImpl(implicitConstructor); |
| - return implicitConstructor; |
| - }).toList(growable: false); |
| } |
| PropertyAccessorElement _internalLookUpConcreteGetter( |
| @@ -909,33 +400,6 @@ abstract class AbstractClassElementImpl extends ElementImpl |
| return null; |
| } |
| - bool _safeIsOrInheritsProxy( |
| - ClassElement classElt, HashSet<ClassElement> visitedClassElts) { |
| - if (visitedClassElts.contains(classElt)) { |
| - return false; |
| - } |
| - visitedClassElts.add(classElt); |
| - if (classElt.isProxy) { |
| - return true; |
| - } else if (classElt.supertype != null && |
| - _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) { |
| - return true; |
| - } |
| - List<InterfaceType> supertypes = classElt.interfaces; |
| - for (int i = 0; i < supertypes.length; i++) { |
| - if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| - return true; |
| - } |
| - } |
| - supertypes = classElt.mixins; |
| - for (int i = 0; i < supertypes.length; i++) { |
| - if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| - return true; |
| - } |
| - } |
| - return false; |
| - } |
| - |
| /** |
| * Return the [AbstractClassElementImpl] of the given [classElement]. May |
| * throw an exception if the [AbstractClassElementImpl] cannot be provided |
| @@ -988,6 +452,44 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| final UnlinkedClass _unlinkedClass; |
| /** |
| + * A list containing all of the type parameters defined for this class. |
| + */ |
| + List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; |
| + |
| + /** |
| + * A list containing all of the mixins that are applied to the class being |
| + * extended in order to derive the superclass of this class. |
| + */ |
| + List<InterfaceType> _mixins; |
| + |
| + /** |
| + * A list containing all of the interfaces that are implemented by this class. |
| + */ |
| + List<InterfaceType> _interfaces; |
| + |
| + /** |
| + * For classes which are not mixin applications, a list containing all of the |
| + * constructors contained in this class, or `null` if the list of |
| + * constructors has not yet been built. |
| + * |
| + * For classes which are mixin applications, the list of constructors is |
| + * computed on the fly by the [constructors] getter, and this field is |
| + * `null`. |
| + */ |
| + List<ConstructorElement> _constructors; |
| + |
| + /** |
| + * A list containing all of the methods contained in this class. |
| + */ |
| + List<MethodElement> _methods = MethodElement.EMPTY_LIST; |
| + |
| + /** |
| + * A flag indicating whether the types associated with the instance members of |
| + * this class have been inferred. |
| + */ |
| + bool hasBeenInferred = false; |
| + |
| + /** |
| * Initialize a newly created class element to have the given [name] at the |
| * given [offset] in the file that contains the declaration of this element. |
| */ |
| @@ -1014,7 +516,14 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| */ |
| void set abstract(bool isAbstract) { |
| assert(_unlinkedClass == null); |
| - super.abstract = isAbstract; |
| + setModifier(Modifier.ABSTRACT, isAbstract); |
| + } |
| + |
| + @override |
| + List<InterfaceType> get allSupertypes { |
| + List<InterfaceType> list = new List<InterfaceType>(); |
| + _collectAllSupertypes(list); |
| + return list; |
| } |
| @override |
| @@ -1034,6 +543,28 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| } |
| @override |
| + List<ConstructorElement> get constructors { |
| + if (!isMixinApplication) { |
| + assert(_constructors != null); |
| + return _constructors ?? ConstructorElement.EMPTY_LIST; |
| + } |
| + return _computeMixinAppConstructors(); |
| + } |
| + |
| + /** |
| + * Set the constructors contained in this class to the given [constructors]. |
| + * |
| + * Should only be used for class elements that are not mixin applications. |
| + */ |
| + void set constructors(List<ConstructorElement> constructors) { |
| + assert(!isMixinApplication); |
| + for (ConstructorElement constructor in constructors) { |
| + (constructor as ConstructorElementImpl).enclosingElement = this; |
| + } |
| + this._constructors = constructors; |
| + } |
| + |
| + @override |
| SourceRange get docRange { |
| if (_unlinkedClass != null) { |
| UnlinkedDocumentationComment comment = |
| @@ -1053,6 +584,111 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| return super.documentationComment; |
| } |
| + /** |
| + * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should |
| + * be reported for this class. |
| + */ |
| + bool get doesMixinLackConstructors { |
| + if (!isMixinApplication && mixins.isEmpty) { |
| + // This class is not a mixin application and it doesn't have a "with" |
| + // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is |
| + // inapplicable. |
| + return false; |
| + } |
| + if (supertype == null) { |
| + // Should never happen, since Object is the only class that has no |
| + // supertype, and it should have been caught by the test above. |
| + assert(false); |
| + return false; |
| + } |
| + // Find the nearest class in the supertype chain that is not a mixin |
| + // application. |
| + ClassElement nearestNonMixinClass = supertype.element; |
| + if (nearestNonMixinClass.isMixinApplication) { |
| + // Use a list to keep track of the classes we've seen, so that we won't |
| + // go into an infinite loop in the event of a non-trivial loop in the |
| + // class hierarchy. |
| + List<ClassElement> classesSeen = <ClassElement>[this]; |
| + while (nearestNonMixinClass.isMixinApplication) { |
| + if (classesSeen.contains(nearestNonMixinClass)) { |
| + // Loop in the class hierarchy (which is reported elsewhere). Don't |
| + // confuse the user with further errors. |
| + return false; |
| + } |
| + classesSeen.add(nearestNonMixinClass); |
| + if (nearestNonMixinClass.supertype == null) { |
| + // Should never happen, since Object is the only class that has no |
| + // supertype, and it is not a mixin application. |
| + assert(false); |
| + return false; |
| + } |
| + nearestNonMixinClass = nearestNonMixinClass.supertype.element; |
| + } |
| + } |
| + return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); |
| + } |
| + |
| + @override |
| + bool get hasNonFinalField { |
| + List<ClassElement> classesToVisit = new List<ClassElement>(); |
| + HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| + classesToVisit.add(this); |
| + while (!classesToVisit.isEmpty) { |
| + ClassElement currentElement = classesToVisit.removeAt(0); |
| + if (visitedClasses.add(currentElement)) { |
| + // check fields |
| + for (FieldElement field in currentElement.fields) { |
| + if (!field.isFinal && |
| + !field.isConst && |
| + !field.isStatic && |
| + !field.isSynthetic) { |
| + return true; |
| + } |
| + } |
| + // check mixins |
| + for (InterfaceType mixinType in currentElement.mixins) { |
| + ClassElement mixinElement = mixinType.element; |
| + classesToVisit.add(mixinElement); |
| + } |
| + // check super |
| + InterfaceType supertype = currentElement.supertype; |
| + if (supertype != null) { |
| + ClassElement superElement = supertype.element; |
| + if (superElement != null) { |
| + classesToVisit.add(superElement); |
| + } |
| + } |
| + } |
| + } |
| + // not found |
| + return false; |
| + } |
| + |
| + @override |
| + bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER); |
| + |
| + /** |
| + * Set whether this class references 'super'. |
| + */ |
| + void set hasReferenceToSuper(bool isReferencedSuper) { |
| + setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); |
| + } |
| + |
| + @override |
| + bool get hasStaticMember { |
| + for (MethodElement method in _methods) { |
| + if (method.isStatic) { |
| + return true; |
| + } |
| + } |
| + for (PropertyAccessorElement accessor in _accessors) { |
| + if (accessor.isStatic) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| @override |
| List<InterfaceType> get interfaces { |
| if (_unlinkedClass != null && _interfaces == null) { |
| @@ -1061,12 +697,12 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| .map((EntityRef t) => context.resolveTypeRef(t, this)) |
| .toList(growable: false); |
| } |
| - return super.interfaces; |
| + return _interfaces ?? const <InterfaceType>[]; |
| } |
| void set interfaces(List<InterfaceType> interfaces) { |
| assert(_unlinkedClass == null); |
| - super.interfaces = interfaces; |
| + _interfaces = interfaces; |
| } |
| @override |
| @@ -1074,7 +710,7 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| if (_unlinkedClass != null) { |
| return _unlinkedClass.isAbstract; |
| } |
| - return super.isAbstract; |
| + return hasModifier(Modifier.ABSTRACT); |
| } |
| @override |
| @@ -1085,7 +721,39 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| if (_unlinkedClass != null) { |
| return _unlinkedClass.isMixinApplication; |
| } |
| - return super.isMixinApplication; |
| + return hasModifier(Modifier.MIXIN_APPLICATION); |
| + } |
| + |
| + @override |
| + bool get isOrInheritsProxy => |
| + _safeIsOrInheritsProxy(this, new HashSet<ClassElement>()); |
| + |
| + @override |
| + bool get isProxy { |
| + for (ElementAnnotation annotation in metadata) { |
| + if (annotation.isProxy) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + @override |
| + bool get isValidMixin { |
| + if (!context.analysisOptions.enableSuperMixins) { |
| + if (hasReferenceToSuper) { |
| + return false; |
| + } |
| + if (!supertype.isObject) { |
| + return false; |
| + } |
| + } |
| + for (ConstructorElement constructor in constructors) { |
| + if (!constructor.isSynthetic && !constructor.isFactory) { |
| + return false; |
| + } |
| + } |
| + return true; |
| } |
| @override |
| @@ -1097,66 +765,360 @@ class ClassElementImpl extends AbstractClassElementImpl { |
| return super.metadata; |
| } |
| + @override |
| + List<MethodElement> get methods => _methods; |
| + |
| + /** |
| + * Set the methods contained in this class to the given [methods]. |
| + */ |
| + void set methods(List<MethodElement> methods) { |
| + for (MethodElement method in methods) { |
| + (method as MethodElementImpl).enclosingElement = this; |
| + } |
| + this._methods = methods; |
| + } |
| + |
| /** |
| * Set whether this class is a mixin application. |
| */ |
| void set mixinApplication(bool isMixinApplication) { |
| assert(_unlinkedClass == null); |
| - super.mixinApplication = isMixinApplication; |
| + setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); |
| + } |
| + |
| + @override |
| + List<InterfaceType> get mixins { |
| + if (_unlinkedClass != null && _mixins == null) { |
| + ResynthesizerContext context = enclosingUnit.resynthesizerContext; |
| + _mixins = _unlinkedClass.mixins |
| + .map((EntityRef t) => context.resolveTypeRef(t, this)) |
| + .toList(growable: false); |
| + } |
| + return _mixins ?? const <InterfaceType>[]; |
| + } |
| + |
| + void set mixins(List<InterfaceType> mixins) { |
| + assert(_unlinkedClass == null); |
| + _mixins = mixins; |
| + } |
| + |
| + @override |
| + String get name { |
| + if (_unlinkedClass != null) { |
| + return _unlinkedClass.name; |
| + } |
| + return super.name; |
| + } |
| + |
| + @override |
| + int get nameOffset { |
| + if (_unlinkedClass != null) { |
| + return _unlinkedClass.nameOffset; |
| + } |
| + return super.nameOffset; |
| + } |
| + |
| + @override |
| + List<TypeParameterElement> get typeParameters { |
| + if (_unlinkedClass != null) { |
| + return resynthesizedTypeParameters; |
| + } |
| + return _typeParameters; |
| + } |
| + |
| + /** |
| + * Set the type parameters defined for this class to the given |
| + * [typeParameters]. |
| + */ |
| + void set typeParameters(List<TypeParameterElement> typeParameters) { |
| + assert(_unlinkedClass == null); |
| + for (TypeParameterElement typeParameter in typeParameters) { |
| + (typeParameter as TypeParameterElementImpl).enclosingElement = this; |
| + } |
| + this._typeParameters = typeParameters; |
| + } |
| + |
| + @override |
| + List<UnlinkedTypeParam> get unlinkedTypeParams => |
| + _unlinkedClass.typeParameters; |
| + |
| + @override |
| + ConstructorElement get unnamedConstructor { |
| + for (ConstructorElement element in constructors) { |
| + String name = element.displayName; |
| + if (name == null || name.isEmpty) { |
| + return element; |
| + } |
| + } |
| + return null; |
| + } |
| + |
| + @override |
| + void appendTo(StringBuffer buffer) { |
| + if (isAbstract) { |
| + buffer.write('abstract '); |
| + } |
| + buffer.write('class '); |
| + String name = displayName; |
| + if (name == null) { |
| + buffer.write("{unnamed class}"); |
| + } else { |
| + buffer.write(name); |
| + } |
| + int variableCount = typeParameters.length; |
| + if (variableCount > 0) { |
| + buffer.write("<"); |
| + for (int i = 0; i < variableCount; i++) { |
| + if (i > 0) { |
| + buffer.write(", "); |
| + } |
| + (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); |
| + } |
| + buffer.write(">"); |
| + } |
| + if (supertype != null && !supertype.isObject) { |
| + buffer.write(' extends '); |
| + buffer.write(supertype.displayName); |
| + } |
| + if (mixins.isNotEmpty) { |
| + buffer.write(' with '); |
| + buffer.write(mixins.map((t) => t.displayName).join(', ')); |
| + } |
| + if (interfaces.isNotEmpty) { |
| + buffer.write(' implements '); |
| + buffer.write(interfaces.map((t) => t.displayName).join(', ')); |
| + } |
| + } |
| + |
| + @override |
| + ElementImpl getChild(String identifier) { |
| + ElementImpl child = super.getChild(identifier); |
| + if (child != null) { |
| + return child; |
| + } |
| + // |
| + // The casts in this method are safe because the set methods would have |
| + // thrown a CCE if any of the elements in the arrays were not of the |
| + // expected types. |
| + // |
| + for (ConstructorElement constructor in _constructors) { |
| + ConstructorElementImpl constructorImpl = constructor; |
| + if (constructorImpl.identifier == identifier) { |
| + return constructorImpl; |
| + } |
| + } |
| + for (MethodElement method in _methods) { |
| + MethodElementImpl methodImpl = method; |
| + if (methodImpl.identifier == identifier) { |
| + return methodImpl; |
| + } |
| + } |
| + for (TypeParameterElement typeParameter in typeParameters) { |
| + TypeParameterElementImpl typeParameterImpl = typeParameter; |
| + if (typeParameterImpl.identifier == identifier) { |
| + return typeParameterImpl; |
| + } |
| + } |
| + return null; |
| } |
| @override |
| - List<InterfaceType> get mixins { |
| - if (_unlinkedClass != null && _mixins == null) { |
| - ResynthesizerContext context = enclosingUnit.resynthesizerContext; |
| - _mixins = _unlinkedClass.mixins |
| - .map((EntityRef t) => context.resolveTypeRef(t, this)) |
| - .toList(growable: false); |
| + MethodElement getMethod(String methodName) { |
| + int length = _methods.length; |
| + for (int i = 0; i < length; i++) { |
| + MethodElement method = _methods[i]; |
| + if (method.name == methodName) { |
| + return method; |
| + } |
| } |
| - return super.mixins; |
| - } |
| - |
| - void set mixins(List<InterfaceType> mixins) { |
| - assert(_unlinkedClass == null); |
| - super.mixins = mixins; |
| + return null; |
| } |
| @override |
| - String get name { |
| - if (_unlinkedClass != null) { |
| - return _unlinkedClass.name; |
| + ConstructorElement getNamedConstructor(String name) { |
| + for (ConstructorElement element in constructors) { |
| + String elementName = element.name; |
| + if (elementName != null && elementName == name) { |
| + return element; |
| + } |
| } |
| - return super.name; |
| + return null; |
| } |
| @override |
| - int get nameOffset { |
| - if (_unlinkedClass != null) { |
| - return _unlinkedClass.nameOffset; |
| + bool isSuperConstructorAccessible(ConstructorElement constructor) { |
| + // If this class has no mixins, then all superclass constructors are |
| + // accessible. |
| + if (mixins.isEmpty) { |
| + return true; |
| } |
| - return super.nameOffset; |
| + // Otherwise only constructors that lack optional parameters are |
| + // accessible (see dartbug.com/19576). |
| + for (ParameterElement parameter in constructor.parameters) { |
| + if (parameter.parameterKind != ParameterKind.REQUIRED) { |
| + return false; |
| + } |
| + } |
| + return true; |
| } |
| @override |
| - List<TypeParameterElement> get typeParameters { |
| - if (_unlinkedClass != null) { |
| - return resynthesizedTypeParameters; |
| + void visitChildren(ElementVisitor visitor) { |
| + super.visitChildren(visitor); |
| + safelyVisitChildren(_constructors, visitor); |
| + safelyVisitChildren(_methods, visitor); |
| + safelyVisitChildren(_typeParameters, visitor); |
| + } |
| + |
| + void _collectAllSupertypes(List<InterfaceType> supertypes) { |
| + List<InterfaceType> typesToVisit = new List<InterfaceType>(); |
| + List<ClassElement> visitedClasses = new List<ClassElement>(); |
| + typesToVisit.add(this.type); |
| + while (!typesToVisit.isEmpty) { |
| + InterfaceType currentType = typesToVisit.removeAt(0); |
| + ClassElement currentElement = currentType.element; |
| + if (!visitedClasses.contains(currentElement)) { |
| + visitedClasses.add(currentElement); |
| + if (!identical(currentType, this.type)) { |
| + supertypes.add(currentType); |
| + } |
| + InterfaceType supertype = currentType.superclass; |
| + if (supertype != null) { |
| + typesToVisit.add(supertype); |
| + } |
| + for (InterfaceType type in currentElement.interfaces) { |
| + typesToVisit.add(type); |
| + } |
| + for (InterfaceType type in currentElement.mixins) { |
| + ClassElement element = type.element; |
| + if (!visitedClasses.contains(element)) { |
| + supertypes.add(type); |
| + } |
| + } |
| + } |
| } |
| - return super.typeParameters; |
| } |
| /** |
| - * Set the type parameters defined for this class to the given |
| - * [typeParameters]. |
| + * Compute a list of constructors for this class, which is a mixin |
| + * application. If specified, [visitedClasses] is a list of the other mixin |
| + * application classes which have been visited on the way to reaching this |
| + * one (this is used to detect circularities). |
| */ |
| - void set typeParameters(List<TypeParameterElement> typeParameters) { |
| - assert(_unlinkedClass == null); |
| - super.typeParameters = typeParameters; |
| + List<ConstructorElement> _computeMixinAppConstructors( |
| + [List<ClassElementImpl> visitedClasses = null]) { |
| + // First get the list of constructors of the superclass which need to be |
| + // forwarded to this class. |
| + Iterable<ConstructorElement> constructorsToForward; |
| + if (supertype == null) { |
| + // Shouldn't ever happen, since the only class with no supertype is |
| + // Object, and it isn't a mixin application. But for safety's sake just |
| + // assume an empty list. |
| + assert(false); |
| + constructorsToForward = <ConstructorElement>[]; |
| + } else if (!supertype.element.isMixinApplication) { |
| + List<ConstructorElement> superclassConstructors = |
| + supertype.element.constructors; |
| + // Filter out any constructors with optional parameters (see |
| + // dartbug.com/15101). |
| + constructorsToForward = |
| + superclassConstructors.where(isSuperConstructorAccessible); |
| + } else { |
| + if (visitedClasses == null) { |
| + visitedClasses = <ClassElementImpl>[this]; |
| + } else { |
| + if (visitedClasses.contains(this)) { |
| + // Loop in the class hierarchy. Don't try to forward any |
| + // constructors. |
| + return <ConstructorElement>[]; |
| + } |
| + visitedClasses.add(this); |
| + } |
| + try { |
| + ClassElementImpl superElement = AbstractClassElementImpl |
| + .getImpl(supertype.element) as ClassElementImpl; |
| + constructorsToForward = |
| + superElement._computeMixinAppConstructors(visitedClasses); |
| + } finally { |
| + visitedClasses.removeLast(); |
| + } |
| + } |
| + |
| + // Figure out the type parameter substitution we need to perform in order |
| + // to produce constructors for this class. We want to be robust in the |
| + // face of errors, so drop any extra type arguments and fill in any missing |
| + // ones with `dynamic`. |
| + List<DartType> parameterTypes = |
| + TypeParameterTypeImpl.getTypes(supertype.typeParameters); |
| + List<DartType> argumentTypes = new List<DartType>.filled( |
| + parameterTypes.length, DynamicTypeImpl.instance); |
| + for (int i = 0; i < supertype.typeArguments.length; i++) { |
| + if (i >= argumentTypes.length) { |
| + break; |
| + } |
| + argumentTypes[i] = supertype.typeArguments[i]; |
| + } |
| + |
| + // Now create an implicit constructor for every constructor found above, |
| + // substituting type parameters as appropriate. |
| + return constructorsToForward |
| + .map((ConstructorElement superclassConstructor) { |
| + ConstructorElementImpl implicitConstructor = |
| + new ConstructorElementImpl(superclassConstructor.name, -1); |
| + implicitConstructor.synthetic = true; |
| + implicitConstructor.redirectedConstructor = superclassConstructor; |
| + implicitConstructor.returnType = type; |
| + List<ParameterElement> superParameters = superclassConstructor.parameters; |
| + int count = superParameters.length; |
| + if (count > 0) { |
| + List<ParameterElement> implicitParameters = |
| + new List<ParameterElement>(count); |
| + for (int i = 0; i < count; i++) { |
| + ParameterElement superParameter = superParameters[i]; |
| + ParameterElementImpl implicitParameter = |
| + new ParameterElementImpl(superParameter.name, -1); |
| + implicitParameter.const3 = superParameter.isConst; |
| + implicitParameter.final2 = superParameter.isFinal; |
| + implicitParameter.parameterKind = superParameter.parameterKind; |
| + implicitParameter.synthetic = true; |
| + implicitParameter.type = |
| + superParameter.type.substitute2(argumentTypes, parameterTypes); |
| + implicitParameters[i] = implicitParameter; |
| + } |
| + implicitConstructor.parameters = implicitParameters; |
| + } |
| + implicitConstructor.enclosingElement = this; |
| + implicitConstructor.type = new FunctionTypeImpl(implicitConstructor); |
| + return implicitConstructor; |
| + }).toList(growable: false); |
| } |
| - @override |
| - List<UnlinkedTypeParam> get unlinkedTypeParams => |
| - _unlinkedClass.typeParameters; |
| + bool _safeIsOrInheritsProxy( |
| + ClassElement classElt, HashSet<ClassElement> visitedClassElts) { |
| + if (visitedClassElts.contains(classElt)) { |
| + return false; |
| + } |
| + visitedClassElts.add(classElt); |
| + if (classElt.isProxy) { |
| + return true; |
| + } else if (classElt.supertype != null && |
| + _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) { |
| + return true; |
| + } |
| + List<InterfaceType> supertypes = classElt.interfaces; |
| + for (int i = 0; i < supertypes.length; i++) { |
| + if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| + return true; |
| + } |
| + } |
| + supertypes = classElt.mixins; |
| + for (int i = 0; i < supertypes.length; i++) { |
| + if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| } |
| /** |
| @@ -3022,6 +2984,9 @@ class EnumElementImpl extends AbstractClassElementImpl { |
| } |
| @override |
| + List<InterfaceType> get allSupertypes => <InterfaceType>[supertype]; |
| + |
| + @override |
| int get codeLength { |
| if (_unlinkedEnum != null) { |
| return _unlinkedEnum.codeRange?.length; |
| @@ -3038,6 +3003,9 @@ class EnumElementImpl extends AbstractClassElementImpl { |
| } |
| @override |
| + List<ConstructorElement> get constructors => const <ConstructorElement>[]; |
|
Paul Berry
2016/06/01 21:47:02
Can we replicate the comment you've removed from p
scheglov
2016/06/02 00:13:24
Done.
|
| + |
| + @override |
| SourceRange get docRange { |
| if (_unlinkedEnum != null) { |
| UnlinkedDocumentationComment comment = _unlinkedEnum.documentationComment; |
| @@ -3057,11 +3025,16 @@ class EnumElementImpl extends AbstractClassElementImpl { |
| } |
| @override |
| - List<InterfaceType> get interfaces => const <InterfaceType>[]; |
| + bool get hasNonFinalField => false; |
| - void set interfaces(List<InterfaceType> interfaces) { |
| - assert(false); |
| - } |
| + @override |
| + bool get hasReferenceToSuper => false; |
| + |
| + @override |
| + bool get hasStaticMember => true; |
| + |
| + @override |
| + List<InterfaceType> get interfaces => const <InterfaceType>[]; |
| @override |
| bool get isAbstract => false; |
| @@ -3073,6 +3046,15 @@ class EnumElementImpl extends AbstractClassElementImpl { |
| bool get isMixinApplication => false; |
| @override |
| + bool get isOrInheritsProxy => false; |
| + |
| + @override |
| + bool get isProxy => false; |
| + |
| + @override |
| + bool get isValidMixin => false; |
| + |
| + @override |
| List<ElementAnnotation> get metadata { |
| if (_unlinkedEnum != null) { |
| return _metadata ??= |
| @@ -3081,20 +3063,12 @@ class EnumElementImpl extends AbstractClassElementImpl { |
| return super.metadata; |
| } |
| - /** |
| - * Set whether this class is a mixin application. |
| - */ |
| - void set mixinApplication(bool isMixinApplication) { |
| - assert(false); |
| - } |
| + @override |
| + List<MethodElement> get methods => const <MethodElement>[]; |
| @override |
| List<InterfaceType> get mixins => const <InterfaceType>[]; |
| - void set mixins(List<InterfaceType> mixins) { |
| - assert(false); |
| - } |
| - |
| @override |
| String get name { |
| if (_unlinkedEnum != null) { |
| @@ -3115,13 +3089,28 @@ class EnumElementImpl extends AbstractClassElementImpl { |
| List<TypeParameterElement> get typeParameters => |
| const <TypeParameterElement>[]; |
| - /** |
| - * Set the type parameters defined for this class to the given |
| - * [typeParameters]. |
| - */ |
| - void set typeParameters(List<TypeParameterElement> typeParameters) { |
| - assert(false); |
| + @override |
| + ConstructorElement get unnamedConstructor => null; |
| + |
| + @override |
| + void appendTo(StringBuffer buffer) { |
| + buffer.write('enum '); |
| + String name = displayName; |
| + if (name == null) { |
| + buffer.write("{unnamed enum}"); |
| + } else { |
| + buffer.write(name); |
| + } |
| } |
| + |
| + @override |
| + MethodElement getMethod(String name) => null; |
| + |
| + @override |
| + ConstructorElement getNamedConstructor(String name) => null; |
| + |
| + @override |
| + bool isSuperConstructorAccessible(ConstructorElement constructor) => false; |
| } |
| /** |