diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart index 9559ff32ad85..d23b9fd58bc5 100644 --- a/pkg/analyzer/lib/dart/element/element.dart +++ b/pkg/analyzer/lib/dart/element/element.dart @@ -349,9 +349,8 @@ abstract class ClassElement /// /// Clients may not extend, implement or mix-in this class. abstract class ClassMemberElement implements Element { - @override - ClassElement get enclosingElement; - + // TODO(brianwilkerson) Either remove this class or rename it to something + // more correct, such as PotentiallyStaticElement. /// Return `true` if this element is a static element. A static element is an /// element that is not associated with a particular instance, but rather with /// an entire library or class. @@ -425,6 +424,9 @@ abstract class CompilationUnitElement implements Element, UriReferencedElement { /// Clients may not extend, implement or mix-in this class. abstract class ConstructorElement implements ClassMemberElement, ExecutableElement, ConstantEvaluationTarget { + @override + ClassElement get enclosingElement; + /// Return `true` if this constructor is a const constructor. bool get isConst; @@ -1058,7 +1060,7 @@ abstract class ExportElement implements Element, UriReferencedElement { /// An element that represents an extension. /// /// Clients may not extend, implement or mix-in this class. -abstract class ExtensionElement implements Element { +abstract class ExtensionElement implements TypeParameterizedElement { /// Return a list containing all of the accessors (getters and setters) /// declared in this extension. List get accessors; @@ -1069,10 +1071,6 @@ abstract class ExtensionElement implements Element { /// Return a list containing all of the methods declared in this extension. List get methods; - /// Return a list containing all of the type parameters declared by this - /// extension. - List get typeParameters; - /// Return the element representing the getter with the given [name] that is /// declared in this extension, or `null` if this extension does not declare a /// getter with the given name. @@ -1100,6 +1098,11 @@ abstract class FieldElement /// Return `true` if this element is an enum constant. bool get isEnumConstant; + /// Return `true` if this element is a static element. A static element is an + /// element that is not associated with a particular instance, but rather with + /// an entire library or class. + bool get isStatic; + /// Returns `true` if this field can be overridden in strong mode. @deprecated bool get isVirtual; @@ -1191,7 +1194,7 @@ abstract class FunctionTypedElement implements TypeParameterizedElement { /// return type was explicitly specified. DartType get returnType; - @override + /// Return the type defined by this element. FunctionType get type; } @@ -1674,9 +1677,6 @@ abstract class TypeParameterizedElement implements Element { /// If the element does not define a type, returns `true`. bool get isSimplyBounded; - /// The type of this element, which will be a parameterized type. - ParameterizedType get type; - /// Return a list containing all of the type parameters declared by this /// element directly. This does not include type parameters that are declared /// by any enclosing elements. diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart index 26fc896c739d..62c604add9d4 100644 --- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart +++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart @@ -348,7 +348,8 @@ class ConstantVerifier extends RecursiveAstVisitor { // lookup for == MethodElement method = element.lookUpConcreteMethod("==", _currentLibrary); - if (method == null || method.enclosingElement.type.isObject) { + if (method == null || + (method.enclosingElement as ClassElement).type.isObject) { return false; } // there is == that we don't like diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index 1f9d8c39f55a..ada4f062c63f 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -4926,12 +4926,11 @@ class ExportElementImpl extends UriReferencedElementImpl } /// A concrete implementation of an [ExtensionElement]. -class ExtensionElementImpl extends ElementImpl implements ExtensionElement { +class ExtensionElementImpl extends ElementImpl + with TypeParameterizedElementMixin + implements ExtensionElement { /// The unlinked representation of the extension in the summary. - final /* UnlinkedExtension */ _unlinkedExtension; - - /// A list containing all of the type parameters declared by this extension. - List _typeParameters; + final UnlinkedExtension _unlinkedExtension; /// The type being extended. DartType _extendedType; @@ -4991,6 +4990,9 @@ class ExtensionElementImpl extends ElementImpl implements ExtensionElement { _accessors = accessors; } + @override + TypeParameterizedElementMixin get enclosingTypeParameterContext => null; + @override DartType get extendedType { if (_extendedType != null) { @@ -5014,6 +5016,9 @@ class ExtensionElementImpl extends ElementImpl implements ExtensionElement { _extendedType = extendedType; } + @override + bool get isSimplyBounded => true; + @override ElementKind get kind => ElementKind.EXTENSION; @@ -5024,49 +5029,47 @@ class ExtensionElementImpl extends ElementImpl implements ExtensionElement { } if (linkedNode != null) { - // TODO(brianwilkerson) Implement this. -// var context = enclosingUnit.linkedContext; -// var containerRef = reference.getChild('@method'); -// return _methods = context -// .getMethods(linkedNode) -// .where((node) => node.propertyKeyword == null) -// .map((node) { -// var name = node.name.name; -// var reference = containerRef.getChild(name); -// if (reference.hasElementFor(node)) { -// return reference.element as MethodElement; -// } -// return MethodElementImpl.forLinkedNode(this, reference, node); -// }).toList(); + var context = enclosingUnit.linkedContext; + var containerRef = reference.getChild('@method'); + return _methods = context + .getMethods(linkedNode) + .where((node) => node.propertyKeyword == null) + .map((node) { + var name = node.name.name; + var reference = containerRef.getChild(name); + if (reference.hasElementFor(node)) { + return reference.element as MethodElement; + } + return MethodElementImpl.forLinkedNode(this, reference, node); + }).toList(); } else if (_unlinkedExtension != null) { - // TODO(brianwilkerson) Implement this. -// var unlinkedExecutables = _unlinkedExtension.executables; -// -// var length = unlinkedExecutables.length; -// if (length == 0) { -// return _methods = const []; -// } -// -// var count = 0; -// for (var i = 0; i < length; i++) { -// var e = unlinkedExecutables[i]; -// if (e.kind == UnlinkedExecutableKind.functionOrMethod) { -// count++; -// } -// } -// if (count == 0) { -// return _methods = const []; -// } -// -// var methods = new List(count); -// var index = 0; -// for (var i = 0; i < length; i++) { -// var e = unlinkedExecutables[i]; -// if (e.kind == UnlinkedExecutableKind.functionOrMethod) { -// methods[index++] = new MethodElementImpl.forSerialized(e, this); -// } -// } -// return _methods = methods; + var unlinkedExecutables = _unlinkedExtension.executables; + + var length = unlinkedExecutables.length; + if (length == 0) { + return _methods = const []; + } + + var count = 0; + for (var i = 0; i < length; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.functionOrMethod) { + count++; + } + } + if (count == 0) { + return _methods = const []; + } + + var methods = new List(count); + var index = 0; + for (var i = 0; i < length; i++) { + var e = unlinkedExecutables[i]; + if (e.kind == UnlinkedExecutableKind.functionOrMethod) { + methods[index++] = new MethodElementImpl.forSerialized(e, this); + } + } + return _methods = methods; } return _methods = const []; } @@ -5104,42 +5107,6 @@ class ExtensionElementImpl extends ElementImpl implements ExtensionElement { return offset; } - @override - List get typeParameters { - if (_typeParameters != null) { - return _typeParameters; - } - - if (linkedNode != null) { - var typeParameters = linkedContext.getTypeParameters2(linkedNode); - if (typeParameters == null) { - return _typeParameters = const []; - } - var containerRef = reference.getChild('@typeParameter'); - return _typeParameters = - typeParameters.typeParameters.map((node) { - var reference = containerRef.getChild(node.name.name); - if (reference.hasElementFor(node)) { - return reference.element as TypeParameterElement; - } - return TypeParameterElementImpl.forLinkedNode(this, reference, node); - }).toList(); - } else if (_unlinkedExtension != null) { - List unlinkedParams = - _unlinkedExtension?.typeParameters; - if (unlinkedParams != null) { - int numTypeParameters = unlinkedParams.length; - _typeParameters = new List(numTypeParameters); - for (int i = 0; i < numTypeParameters; i++) { - _typeParameters[i] = new TypeParameterElementImpl.forSerialized( - unlinkedParams[i], this); - } - } - } - - return _typeParameters ?? const []; - } - /// Set the type parameters defined by this extension to the given /// [typeParameters]. void set typeParameters(List typeParameters) { @@ -5147,9 +5114,13 @@ class ExtensionElementImpl extends ElementImpl implements ExtensionElement { for (TypeParameterElement typeParameter in typeParameters) { (typeParameter as TypeParameterElementImpl).enclosingElement = this; } - this._typeParameters = typeParameters; + this._typeParameterElements = typeParameters; } + @override + List get unlinkedTypeParams => + _unlinkedExtension?.typeParameters; + @override T accept(ElementVisitor visitor) { return visitor.visitExtensionElement(this); @@ -7499,7 +7470,7 @@ class MethodElementImpl extends ExecutableElementImpl implements MethodElement { /// given [offset]. MethodElementImpl(String name, int offset) : super(name, offset); - MethodElementImpl.forLinkedNode(ClassElementImpl enclosingClass, + MethodElementImpl.forLinkedNode(TypeParameterizedElementMixin enclosingClass, Reference reference, MethodDeclaration linkedNode) : super.forLinkedNode(enclosingClass, reference, linkedNode); @@ -7507,8 +7478,8 @@ class MethodElementImpl extends ExecutableElementImpl implements MethodElement { MethodElementImpl.forNode(Identifier name) : super.forNode(name); /// Initialize using the given serialized information. - MethodElementImpl.forSerialized( - UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass) + MethodElementImpl.forSerialized(UnlinkedExecutable serializedExecutable, + TypeParameterizedElementMixin enclosingClass) : super.forSerialized(serializedExecutable, enclosingClass); @override @@ -7520,12 +7491,9 @@ class MethodElementImpl extends ExecutableElementImpl implements MethodElement { return displayName; } - @override - ClassElement get enclosingElement => super.enclosingElement as ClassElement; - @override TypeParameterizedElementMixin get enclosingTypeParameterContext => - super.enclosingElement as ClassElementImpl; + super.enclosingElement as TypeParameterizedElementMixin; /// Set whether this class is abstract. void set isAbstract(bool isAbstract) { diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart index 15cbd7b5a475..2adb345ec7e9 100644 --- a/pkg/analyzer/lib/src/dart/element/member.dart +++ b/pkg/analyzer/lib/src/dart/element/member.dart @@ -215,7 +215,7 @@ class FieldFormalParameterMember extends ParameterMember FieldElement field = (baseElement as FieldFormalParameterElement).field; if (field is FieldElement) { return FieldMember.from( - field, substituteFor(field.enclosingElement.type)); + field, substituteFor((field.enclosingElement as ClassElement).type)); } return field; } diff --git a/pkg/analyzer/test/util/element_type_matchers.dart b/pkg/analyzer/test/util/element_type_matchers.dart index c1414145d0f0..93f7e7a1f2ff 100644 --- a/pkg/analyzer/test/util/element_type_matchers.dart +++ b/pkg/analyzer/test/util/element_type_matchers.dart @@ -7,8 +7,6 @@ import 'package:test/test.dart'; const isClassElement = const TypeMatcher(); -const isClassMemberElement = const TypeMatcher(); - const isCompilationUnitElement = const TypeMatcher(); const isConstructorElement = const TypeMatcher(); diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart index e415e3963791..9fd489dca14e 100644 --- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart +++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart @@ -3105,7 +3105,7 @@ class CodeGenerator extends Object js_ast.Expression _emitClassMemberElement( ClassMemberElement element, Element accessor, Expression node) { bool isStatic = element.isStatic; - var classElem = element.enclosingElement; + var classElem = element.enclosingElement as ClassElement; var type = classElem.type; var member = _emitMemberName(element.name, isStatic: isStatic, type: type, element: accessor); @@ -3300,7 +3300,7 @@ class CodeGenerator extends Object /// [_emitTopLevelName] on the class, but if the member is external, then the /// native class name will be used, for direct access to the native member. js_ast.Expression _emitStaticClassName(ClassMemberElement member) { - var c = member.enclosingElement; + var c = member.enclosingElement as ClassElement; _declareBeforeUse(c); // A static native element should just forward directly to the JS type's @@ -3593,7 +3593,7 @@ class CodeGenerator extends Object /// Emits assignment to a static field element or property. js_ast.Expression _emitSetField(Expression right, FieldElement field, js_ast.Expression jsTarget, SimpleIdentifier id) { - var classElem = field.enclosingElement; + var classElem = field.enclosingElement as ClassElement; var isStatic = field.isStatic; var member = _emitMemberName(field.name, isStatic: isStatic, type: classElem.type, element: field.setter); @@ -4577,7 +4577,10 @@ class CodeGenerator extends Object DartType getType(TypeAnnotation typeNode) { if (typeNode is NamedType && typeNode.typeArguments != null) { var e = typeNode.name.staticElement; - if (e is TypeParameterizedElement) { + if (e is ClassElement) { + return e.type.instantiate( + typeNode.typeArguments.arguments.map(getType).toList()); + } else if (e is FunctionTypedElement) { return e.type.instantiate( typeNode.typeArguments.arguments.map(getType).toList()); } diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart index e8fe0f09f864..98c7b54eec2c 100644 --- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart +++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart @@ -57,7 +57,14 @@ DartType instantiateElementTypeToBounds( // Futhermore, the second line is represented by a GenericTypeAliasElement, // and its type getter does not even include its own type formals ``. // That has to be worked around using `.function.type`. - var type = e is GenericTypeAliasElement ? e.function.type : e.type; + DartType type; + if (e is GenericTypeAliasElement) { + type = e.function.type; + } else if (e is FunctionTypedElement) { + type = e.type; + } else if (e is ClassElement) { + type = e.type; + } var bounds = rules.instantiateTypeFormalsToBounds(e.typeParameters); if (bounds == null) return type; return type.substitute2( @@ -220,7 +227,7 @@ bool hasNoSuchMethod(ClassElement classElement) { var method = classElement.lookUpMethod( FunctionElement.NO_SUCH_METHOD_METHOD_NAME, classElement.library); var definingClass = method?.enclosingElement; - return definingClass != null && !definingClass.type.isObject; + return definingClass is ClassElement && !definingClass.type.isObject; } /// Returns true if this class is of the form: diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart index caa8b8310f3b..d90fa57eafcc 100644 --- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart +++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart @@ -436,7 +436,7 @@ class AnalyzerToKernel { fileUri: e.source.uri, reference: _reference(e)); if (!e.isFinal && !e.isConst) { - var class_ = e.enclosingElement; + var class_ = e.enclosingElement as a.ClassElement; if (class_.typeParameters.isNotEmpty) { result.isGenericCovariantImpl = _isGenericCovariant(class_, e.type); } @@ -598,7 +598,7 @@ class AnalyzerToKernel { var enclosingElement = e.enclosingElement; if (hasBound && enclosingElement is a.ClassMemberElement) { var class_ = enclosingElement.enclosingElement; - if (class_ != null && class_.typeParameters.isNotEmpty) { + if (class_ is a.ClassElement && class_.typeParameters.isNotEmpty) { t.isGenericCovariantImpl = _isGenericCovariant(class_, e.bound); } } diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart index 08c3f805bcc9..7aeabde3cdf6 100644 --- a/pkg/nnbd_migration/lib/src/edge_builder.dart +++ b/pkg/nnbd_migration/lib/src/edge_builder.dart @@ -108,7 +108,7 @@ class EdgeBuilder extends GeneralizingAstVisitor { var targetTypeType = targetType.type; if (targetTypeType is InterfaceType && baseElement is ClassMemberElement) { - var enclosingClass = baseElement.enclosingElement; + var enclosingClass = baseElement.enclosingElement as ClassElement; assert(targetTypeType.element == enclosingClass); // TODO(paulberry) substitution = {}; assert(enclosingClass.typeParameters.length == @@ -250,8 +250,9 @@ class EdgeBuilder extends GeneralizingAstVisitor { _handleAssignment(node.leftOperand, _notNullType); var callee = node.staticElement; assert(!(callee is ClassMemberElement && - callee - .enclosingElement.typeParameters.isNotEmpty)); // TODO(paulberry) + (callee.enclosingElement as ClassElement) + .typeParameters + .isNotEmpty)); // TODO(paulberry) assert(callee != null); // TODO(paulberry) var calleeType = getOrComputeElementType(callee); // TODO(paulberry): substitute if necessary @@ -649,7 +650,7 @@ $stackTrace'''); _handleAssignment(node.operand, _notNullType); var callee = node.staticElement; if (callee is ClassMemberElement && - callee.enclosingElement.typeParameters.isNotEmpty) { + (callee.enclosingElement as ClassElement).typeParameters.isNotEmpty) { // TODO(paulberry) _unimplemented(node, 'Operator ${operatorType.lexeme} defined on a class with type parameters'); @@ -686,7 +687,7 @@ $stackTrace'''); operatorType == TokenType.MINUS_MINUS) { var callee = node.staticElement; if (callee is ClassMemberElement && - callee.enclosingElement.typeParameters.isNotEmpty) { + (callee.enclosingElement as ClassElement).typeParameters.isNotEmpty) { // TODO(paulberry) _unimplemented(node, 'Operator ${operatorType.lexeme} defined on a class with type parameters');