From 37003ee3be6a3a229c8dc9e0f4309fe8c4a226ca Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 4 Jul 2023 01:41:38 +0000 Subject: [PATCH] Add InterfaceElementImpl, move many methods into it. Change-Id: I7f77e318586b2c05874b3a0d25d2d940869b6a0d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/312240 Commit-Queue: Konstantin Shcheglov Reviewed-by: Samuel Rawlins --- .../lib/src/dart/element/element.dart | 1162 ++++++++--------- pkg/analyzer/lib/src/dart/element/type.dart | 6 +- .../dart/resolver/type_property_resolver.dart | 4 +- .../src/generated/element_type_provider.dart | 2 +- .../lib/src/summary2/bundle_reader.dart | 6 +- .../constructor_initializer_resolver.dart | 4 +- .../lib/src/summary2/element_builder.dart | 2 +- .../lib/src/summary2/types_builder.dart | 11 +- pkg/analyzer/lib/src/task/strong_mode.dart | 4 +- pkg/nnbd_migration/lib/src/fix_builder.dart | 2 +- 10 files changed, 551 insertions(+), 652 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index 9d7af95d77c..e800d1005c8 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -56,426 +56,6 @@ import 'package:analyzer/src/utilities/extensions/string.dart'; import 'package:collection/collection.dart'; import 'package:pub_semver/pub_semver.dart'; -/// A concrete implementation of a [ClassElement]. -abstract class AbstractClassElementImpl - extends NamedInstanceOrAugmentationElementImpl - with HasCompletionData, MacroTargetElement - implements InterfaceElement { - /// The superclass of the class, or `null` for [Object]. - @override - InterfaceType? supertype; - - /// 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 _mixins = const []; - - /// A list containing all of the interfaces that are implemented by this - /// class. - List _interfaces = const []; - - /// The type defined by the class. - InterfaceType? _thisType; - - /// A list containing all of the accessors (getters and setters) contained in - /// this class. - List _accessors = - _Sentinel.propertyAccessorElement; - - /// A list containing all of the fields contained in this class. - List _fields = _Sentinel.fieldElement; - - /// A list containing all of the methods contained in this class. - List _methods = _Sentinel.methodElement; - - /// A flag indicating whether the types associated with the instance members - /// of this class have been inferred. - bool hasBeenInferred = false; - - /// This callback is set during mixins inference to handle reentrant calls. - List? Function(AbstractClassElementImpl)? - mixinInferenceCallback; - - /// 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. - AbstractClassElementImpl(String super.name, super.offset); - - @override - List get accessors; - - /// Set the accessors contained in this class to the given [accessors]. - set accessors(List accessors) { - for (var accessor in accessors) { - accessor.enclosingElement = this; - } - _accessors = accessors; - } - - @override - List get allSupertypes { - return library.session.classHierarchy.implementedInterfaces(this); - } - - @override - List get children => [ - ...super.children, - ...accessors, - ...fields, - ...constructors, - ...methods, - ...typeParameters, - ]; - - @override - List get constructors; - - @override - String get displayName => name; - - @Deprecated('Use enclosingElement2 instead') - @override - CompilationUnitElementImpl get enclosingElement { - return _enclosingElement as CompilationUnitElementImpl; - } - - @override - CompilationUnitElementImpl get enclosingElement2 { - return _enclosingElement as CompilationUnitElementImpl; - } - - @override - List get fields; - - /// Set the fields contained in this class to the given [fields]. - set fields(List fields) { - for (var field in fields) { - field.enclosingElement = this; - } - _fields = fields; - } - - @override - List get interfaces => - ElementTypeProvider.current.getClassInterfaces(this); - - set interfaces(List interfaces) { - _interfaces = interfaces; - } - - List get interfacesInternal { - return _interfaces; - } - - /// Return `true` if this class represents the class '_Enum' defined in the - /// dart:core library. - bool get isDartCoreEnumImpl { - return name == '_Enum' && library.isDartCore; - } - - /// Return `true` if this class represents the class 'Function' defined in the - /// dart:core library. - bool get isDartCoreFunctionImpl { - return name == 'Function' && library.isDartCore; - } - - @override - List get mixins { - if (mixinInferenceCallback != null) { - var mixins = mixinInferenceCallback!(this); - if (mixins != null) { - return _mixins = mixins; - } - } - - return _mixins; - } - - set mixins(List mixins) { - _mixins = mixins; - } - - @override - InterfaceType get thisType { - if (_thisType == null) { - List typeArguments; - if (typeParameters.isNotEmpty) { - typeArguments = typeParameters.map((t) { - return t.instantiate(nullabilitySuffix: _noneOrStarSuffix); - }).toFixedList(); - } else { - typeArguments = const []; - } - return _thisType = instantiate( - typeArguments: typeArguments, - nullabilitySuffix: _noneOrStarSuffix, - ); - } - return _thisType!; - } - - set typeParameters(List typeParameters) { - for (TypeParameterElement typeParameter in typeParameters) { - (typeParameter as TypeParameterElementImpl).enclosingElement = this; - } - _typeParameterElements = typeParameters; - } - - @override - ConstructorElement? get unnamedConstructor { - return constructors.firstWhereOrNull((element) => element.name.isEmpty); - } - - @override - FieldElement? getField(String name) { - return fields.firstWhereOrNull((fieldElement) => name == fieldElement.name); - } - - @override - PropertyAccessorElement? getGetter(String getterName) { - return accessors.firstWhereOrNull( - (accessor) => accessor.isGetter && accessor.name == getterName); - } - - @override - MethodElement? getMethod(String methodName) { - return methods.firstWhereOrNull((method) => method.name == methodName); - } - - @override - ConstructorElement? getNamedConstructor(String name) { - if (name == 'new') { - // A constructor declared as `C.new` is unnamed, and is modeled as such. - name = ''; - } - return constructors.firstWhereOrNull((element) => element.name == name); - } - - @override - PropertyAccessorElement? getSetter(String setterName) { - return getSetterFromAccessors(setterName, accessors); - } - - @override - InterfaceType instantiate({ - required List typeArguments, - required NullabilitySuffix nullabilitySuffix, - }) { - return InterfaceTypeImpl( - element: this, - typeArguments: typeArguments, - nullabilitySuffix: nullabilitySuffix, - ); - } - - @override - MethodElement? lookUpConcreteMethod( - String methodName, LibraryElement library) { - return _implementationsOfMethod(methodName).firstWhereOrNull( - (method) => !method.isAbstract && method.isAccessibleIn(library)); - } - - @override - PropertyAccessorElement? lookUpGetter( - String getterName, LibraryElement library) { - return _implementationsOfGetter(getterName) - .firstWhereOrNull((getter) => getter.isAccessibleIn(library)); - } - - @override - PropertyAccessorElement? lookUpInheritedConcreteGetter( - String getterName, LibraryElement library) { - return _implementationsOfGetter(getterName).firstWhereOrNull((getter) => - !getter.isAbstract && - !getter.isStatic && - getter.isAccessibleIn(library) && - getter.enclosingElement2 != this); - } - - ExecutableElement? lookUpInheritedConcreteMember( - String name, LibraryElement library) { - if (name.endsWith('=')) { - return lookUpInheritedConcreteSetter(name, library); - } else { - return lookUpInheritedConcreteMethod(name, library) ?? - lookUpInheritedConcreteGetter(name, library); - } - } - - @override - MethodElement? lookUpInheritedConcreteMethod( - String methodName, LibraryElement library) { - return _implementationsOfMethod(methodName).firstWhereOrNull((method) => - !method.isAbstract && - !method.isStatic && - method.isAccessibleIn(library) && - method.enclosingElement2 != this); - } - - @override - PropertyAccessorElement? lookUpInheritedConcreteSetter( - String setterName, LibraryElement library) { - return _implementationsOfSetter(setterName).firstWhereOrNull((setter) => - !setter.isAbstract && - !setter.isStatic && - setter.isAccessibleIn(library) && - setter.enclosingElement2 != this); - } - - @override - MethodElement? lookUpInheritedMethod( - String methodName, LibraryElement library) { - return _implementationsOfMethod(methodName).firstWhereOrNull((method) => - !method.isStatic && - method.isAccessibleIn(library) && - method.enclosingElement2 != this); - } - - @override - MethodElement? lookUpMethod(String methodName, LibraryElement library) { - return _implementationsOfMethod(methodName).firstWhereOrNull( - (MethodElement method) => method.isAccessibleIn(library)); - } - - @override - PropertyAccessorElement? lookUpSetter( - String setterName, LibraryElement library) { - return _implementationsOfSetter(setterName).firstWhereOrNull( - (PropertyAccessorElement setter) => setter.isAccessibleIn(library)); - } - - /// Return the static getter with the [name], accessible to the [library]. - /// - /// This method should be used only for error recovery during analysis, - /// when instance access to a static class member, defined in this class, - /// or a superclass. - PropertyAccessorElement? lookupStaticGetter( - String name, LibraryElement library) { - return _implementationsOfGetter(name).firstWhereOrNull( - (element) => element.isStatic && element.isAccessibleIn(library)); - } - - /// Return the static method with the [name], accessible to the [library]. - /// - /// This method should be used only for error recovery during analysis, - /// when instance access to a static class member, defined in this class, - /// or a superclass. - MethodElement? lookupStaticMethod(String name, LibraryElement library) { - return _implementationsOfMethod(name).firstWhereOrNull( - (element) => element.isStatic && element.isAccessibleIn(library)); - } - - /// Return the static setter with the [name], accessible to the [library]. - /// - /// This method should be used only for error recovery during analysis, - /// when instance access to a static class member, defined in this class, - /// or a superclass. - PropertyAccessorElement? lookupStaticSetter( - String name, LibraryElement library) { - return _implementationsOfSetter(name).firstWhereOrNull( - (element) => element.isStatic && element.isAccessibleIn(library)); - } - - /// Return an iterable containing all of the implementations of a getter with - /// the given [getterName] that are defined in this class and any superclass - /// of this class (but not in interfaces). - /// - /// The getters that are returned are not filtered in any way. In particular, - /// they can include getters that are not visible in some context. Clients - /// must perform any necessary filtering. - /// - /// The getters are returned based on the depth of their defining class; if - /// this class contains a definition of the getter it will occur first, if - /// Object contains a definition of the getter it will occur last. - Iterable _implementationsOfGetter( - String getterName) sync* { - final visitedClasses = {}; - InterfaceElement? classElement = this; - while (classElement != null && visitedClasses.add(classElement)) { - var getter = classElement.getGetter(getterName); - if (getter != null) { - yield getter; - } - for (InterfaceType mixin in classElement.mixins.reversed) { - getter = mixin.element.getGetter(getterName); - if (getter != null) { - yield getter; - } - } - classElement = classElement.supertype?.element; - } - } - - /// Return an iterable containing all of the implementations of a method with - /// the given [methodName] that are defined in this class and any superclass - /// of this class (but not in interfaces). - /// - /// The methods that are returned are not filtered in any way. In particular, - /// they can include methods that are not visible in some context. Clients - /// must perform any necessary filtering. - /// - /// The methods are returned based on the depth of their defining class; if - /// this class contains a definition of the method it will occur first, if - /// Object contains a definition of the method it will occur last. - Iterable _implementationsOfMethod(String methodName) sync* { - final visitedClasses = {}; - InterfaceElement? classElement = this; - while (classElement != null && visitedClasses.add(classElement)) { - var method = classElement.getMethod(methodName); - if (method != null) { - yield method; - } - for (InterfaceType mixin in classElement.mixins.reversed) { - method = mixin.element.getMethod(methodName); - if (method != null) { - yield method; - } - } - classElement = classElement.supertype?.element; - } - } - - /// Return an iterable containing all of the implementations of a setter with - /// the given [setterName] that are defined in this class and any superclass - /// of this class (but not in interfaces). - /// - /// The setters that are returned are not filtered in any way. In particular, - /// they can include setters that are not visible in some context. Clients - /// must perform any necessary filtering. - /// - /// The setters are returned based on the depth of their defining class; if - /// this class contains a definition of the setter it will occur first, if - /// Object contains a definition of the setter it will occur last. - Iterable _implementationsOfSetter( - String setterName) sync* { - final visitedClasses = {}; - InterfaceElement? classElement = this; - while (classElement != null && visitedClasses.add(classElement)) { - var setter = classElement.getSetter(setterName); - if (setter != null) { - yield setter; - } - for (InterfaceType mixin in classElement.mixins.reversed) { - setter = mixin.element.getSetter(setterName); - if (setter != null) { - yield setter; - } - } - classElement = classElement.supertype?.element; - } - } - - static PropertyAccessorElement? getSetterFromAccessors( - String setterName, List accessors) { - // TODO (jwren) revisit- should we append '=' here or require clients to - // include it? - // Do we need the check for isSetter below? - if (!setterName.endsWith('=')) { - setterName += '='; - } - return accessors.firstWhereOrNull( - (accessor) => accessor.isSetter && accessor.name == setterName); - } -} - class AugmentationImportElementImpl extends _ExistingElementImpl implements AugmentationImportElement { @override @@ -528,12 +108,23 @@ class BindPatternVariableElementImpl extends PatternVariableElementImpl BindPatternVariableElementImpl(this.node, super.name, super.offset); } -/// An [AbstractClassElementImpl] which is a class. -class ClassElementImpl extends ClassOrMixinElementImpl implements ClassElement { +/// An [InterfaceElementImpl] which is a class. +class ClassElementImpl extends ClassOrMixinElementImpl + implements ClassElement { /// 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. ClassElementImpl(super.name, super.offset); + @override + List get accessors { + if (!identical(_accessors, _Sentinel.propertyAccessorElement)) { + return _accessors; + } + + linkedData?.readMembers(this); + return _accessors; + } + @override set accessors(List accessors) { assert(!isMixinApplication); @@ -604,8 +195,8 @@ class ClassElementImpl extends ClassOrMixinElementImpl implements ClassElement { return _constructors = _computeMixinAppConstructors(); } - var linkedData = this.linkedData; - if (linkedData is ClassElementLinkedData) { + final linkedData = this.linkedData; + if (linkedData != null) { linkedData.readMembers(this); return _constructors; } @@ -626,6 +217,16 @@ class ClassElementImpl extends ClassOrMixinElementImpl implements ClassElement { super.constructors = constructors; } + @override + List get fields { + if (!identical(_fields, _Sentinel.fieldElement)) { + return _fields; + } + + linkedData?.readMembers(this); + return _fields; + } + @override set fields(List fields) { assert(!isMixinApplication); @@ -822,15 +423,19 @@ class ClassElementImpl extends ClassOrMixinElementImpl implements ClassElement { } @override - set methods(List methods) { - assert(!isMixinApplication); - super.methods = methods; + List get methods { + if (!identical(_methods, _Sentinel.methodElement)) { + return _methods; + } + + linkedData?.readMembers(this); + return _methods; } @override - InterfaceType? get supertype { - linkedData?.read(this); - return super.supertype; + set methods(List methods) { + assert(!isMixinApplication); + super.methods = methods; } @override @@ -1019,68 +624,12 @@ class ClassElementImpl extends ClassOrMixinElementImpl implements ClassElement { } } -abstract class ClassOrMixinElementImpl extends AbstractClassElementImpl { - /// 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 _constructors = _Sentinel.constructorElement; - - ElementLinkedData? linkedData; - +abstract class ClassOrMixinElementImpl + extends InterfaceElementImpl { /// 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. ClassOrMixinElementImpl(super.name, super.offset); - @override - List get accessors { - if (!identical(_accessors, _Sentinel.propertyAccessorElement)) { - return _accessors; - } - - var linkedData = this.linkedData; - if (linkedData is ClassElementLinkedData) { - linkedData.readMembers(this); - return _accessors; - } - - return _accessors; - } - - /// Set the constructors contained in this class to the given [constructors]. - /// - /// Should only be used for class elements that are not mixin applications. - set constructors(List constructors) { - for (var constructor in constructors) { - constructor.enclosingElement = this; - } - _constructors = constructors; - } - - @override - List get fields { - if (!identical(_fields, _Sentinel.fieldElement)) { - return _fields; - } - - var linkedData = this.linkedData; - if (linkedData is ClassElementLinkedData) { - linkedData.readMembers(this); - return _fields; - } - - return _fields; - } - - @override - List get interfacesInternal { - linkedData?.read(this); - return _interfaces; - } - bool get isBase { return hasModifier(Modifier.BASE); } @@ -1089,66 +638,9 @@ abstract class ClassOrMixinElementImpl extends AbstractClassElementImpl { setModifier(Modifier.BASE, isBase); } - @override - bool get isSimplyBounded { - return hasModifier(Modifier.SIMPLY_BOUNDED); - } - - set isSimplyBounded(bool isSimplyBounded) { - setModifier(Modifier.SIMPLY_BOUNDED, isSimplyBounded); - } - /// TODO(scheglov) Do we need a separate kind for `MixinElement`? @override ElementKind get kind => ElementKind.CLASS; - - @override - List get metadata { - linkedData?.read(this); - return super.metadata; - } - - @override - List get methods { - if (!identical(_methods, _Sentinel.methodElement)) { - return _methods; - } - - var linkedData = this.linkedData; - if (linkedData is ClassElementLinkedData) { - linkedData.readMembers(this); - return _methods; - } - - return _methods; - } - - /// Set the methods contained in this class to the given [methods]. - set methods(List methods) { - for (var method in methods) { - method.enclosingElement = this; - } - _methods = methods; - } - - @override - List get mixins { - linkedData?.read(this); - return super.mixins; - } - - @override - List get typeParameters { - linkedData?.read(this); - return super.typeParameters; - } - - void setLinkedData(Reference reference, ElementLinkedData linkedData) { - this.reference = reference; - reference.element = this; - - this.linkedData = linkedData; - } } /// A concrete implementation of a [CompilationUnitElement]. @@ -1504,7 +996,7 @@ class ConstructorElementImpl extends ExecutableElementImpl @Deprecated('Use enclosingElement2 instead') @override InterfaceElement get enclosingElement => - super.enclosingElement2 as AbstractClassElementImpl; + super.enclosingElement2 as InterfaceElementImpl; @override NamedInstanceElement get enclosingElement2 => @@ -3048,20 +2540,13 @@ class ElementLocationImpl implements ElementLocation { } } -/// An [AbstractClassElementImpl] which is an enum. -class EnumElementImpl extends AbstractClassElementImpl implements EnumElement { - ElementLinkedData? linkedData; - List _constructors = _Sentinel.constructorElement; - +/// An [InterfaceElementImpl] which is an enum. +class EnumElementImpl extends InterfaceElementImpl + implements EnumElement { /// 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. EnumElementImpl(super.name, super.offset); - @override - List get accessors { - return _accessors; - } - @override Never get augmentation { // TODO(scheglov) implement @@ -3078,66 +2563,9 @@ class EnumElementImpl extends AbstractClassElementImpl implements EnumElement { return fields.where((field) => field.isEnumConstant).toList(); } - @override - List get constructors { - return _constructors; - } - - set constructors(List constructors) { - for (var constructor in constructors) { - constructor.enclosingElement = this; - } - _constructors = constructors; - } - - @override - List get fields { - return _fields; - } - - @override - bool get isSimplyBounded { - return hasModifier(Modifier.SIMPLY_BOUNDED); - } - - set isSimplyBounded(bool isSimplyBounded) { - setModifier(Modifier.SIMPLY_BOUNDED, isSimplyBounded); - } - @override ElementKind get kind => ElementKind.ENUM; - @override - List get metadata { - linkedData?.read(this); - return super.metadata; - } - - @override - List get methods { - return _methods; - } - - /// Set the methods contained in this class to the given [methods]. - set methods(List methods) { - for (var method in methods) { - method.enclosingElement = this; - } - _methods = methods; - } - - @override - InterfaceType? get supertype { - linkedData?.read(this); - return super.supertype; - } - - @override - List get typeParameters { - linkedData?.read(this); - return super.typeParameters; - } - ConstFieldElementImpl? get valuesField { for (var field in fields) { if (field is ConstFieldElementImpl && @@ -3158,13 +2586,6 @@ class EnumElementImpl extends AbstractClassElementImpl implements EnumElement { void appendTo(ElementDisplayStringBuilder builder) { builder.writeEnumElement(this); } - - void setLinkedData(Reference reference, ElementLinkedData linkedData) { - this.reference = reference; - reference.element = this; - - this.linkedData = linkedData; - } } /// A base class for concrete implementations of an [ExecutableElement]. @@ -3567,8 +2988,7 @@ class ExtensionElementImpl extends _ExistingElementImpl @override PropertyAccessorElement? getSetter(String setterName) { - return AbstractClassElementImpl.getSetterFromAccessors( - setterName, accessors); + return InterfaceElementImpl.getSetterFromAccessors(setterName, accessors); } void setLinkedData(Reference reference, ElementLinkedData linkedData) { @@ -3992,6 +3412,489 @@ abstract class InstanceOrAugmentationElementImpl extends _ExistingElementImpl } } +abstract class InterfaceElementImpl + extends NamedInstanceOrAugmentationElementImpl + with HasCompletionData, MacroTargetElement + implements InterfaceElement { + LinkedData? linkedData; + InterfaceType? _supertype; + + /// 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 _mixins = const []; + + /// A list containing all of the interfaces that are implemented by this + /// class. + List _interfaces = const []; + + /// The type defined by the class. + InterfaceType? _thisType; + + /// A list containing all of the accessors (getters and setters) contained in + /// this class. + List _accessors = + _Sentinel.propertyAccessorElement; + + /// A list containing all of the fields contained in this class. + List _fields = _Sentinel.fieldElement; + + List _constructors = _Sentinel.constructorElement; + + /// A list containing all of the methods contained in this class. + List _methods = _Sentinel.methodElement; + + /// A flag indicating whether the types associated with the instance members + /// of this class have been inferred. + bool hasBeenInferred = false; + + /// This callback is set during mixins inference to handle reentrant calls. + List? Function(InterfaceElementImpl)? mixinInferenceCallback; + + /// 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. + InterfaceElementImpl(String super.name, super.offset); + + @override + List get accessors { + return _accessors; + } + + /// Set the accessors contained in this class to the given [accessors]. + set accessors(List accessors) { + for (var accessor in accessors) { + accessor.enclosingElement = this; + } + _accessors = accessors; + } + + @override + List get allSupertypes { + return library.session.classHierarchy.implementedInterfaces(this); + } + + @override + List get children => [ + ...super.children, + ...accessors, + ...fields, + ...constructors, + ...methods, + ...typeParameters, + ]; + + @override + List get constructors { + return _constructors; + } + + set constructors(List constructors) { + for (var constructor in constructors) { + constructor.enclosingElement = this; + } + _constructors = constructors; + } + + @override + String get displayName => name; + + @Deprecated('Use enclosingElement2 instead') + @override + CompilationUnitElementImpl get enclosingElement { + return _enclosingElement as CompilationUnitElementImpl; + } + + @override + CompilationUnitElementImpl get enclosingElement2 { + return _enclosingElement as CompilationUnitElementImpl; + } + + @override + List get fields => _fields; + + /// Set the fields contained in this class to the given [fields]. + set fields(List fields) { + for (var field in fields) { + field.enclosingElement = this; + } + _fields = fields; + } + + @override + List get interfaces => + ElementTypeProvider.current.getClassInterfaces(this); + + set interfaces(List interfaces) { + _interfaces = interfaces; + } + + List get interfacesInternal { + linkedData?.read(this); + return _interfaces; + } + + /// Return `true` if this class represents the class '_Enum' defined in the + /// dart:core library. + bool get isDartCoreEnumImpl { + return name == '_Enum' && library.isDartCore; + } + + /// Return `true` if this class represents the class 'Function' defined in the + /// dart:core library. + bool get isDartCoreFunctionImpl { + return name == 'Function' && library.isDartCore; + } + + @override + bool get isSimplyBounded { + return hasModifier(Modifier.SIMPLY_BOUNDED); + } + + set isSimplyBounded(bool isSimplyBounded) { + setModifier(Modifier.SIMPLY_BOUNDED, isSimplyBounded); + } + + @override + List get metadata { + linkedData?.read(this); + return super.metadata; + } + + @override + List get methods { + return _methods; + } + + /// Set the methods contained in this class to the given [methods]. + set methods(List methods) { + for (var method in methods) { + method.enclosingElement = this; + } + _methods = methods; + } + + @override + List get mixins { + if (mixinInferenceCallback != null) { + var mixins = mixinInferenceCallback!(this); + if (mixins != null) { + return _mixins = mixins; + } + } + + linkedData?.read(this); + return _mixins; + } + + set mixins(List mixins) { + _mixins = mixins; + } + + @override + InterfaceType? get supertype { + linkedData?.read(this); + return _supertype; + } + + set supertype(InterfaceType? value) { + _supertype = value; + } + + @override + InterfaceType get thisType { + if (_thisType == null) { + List typeArguments; + if (typeParameters.isNotEmpty) { + typeArguments = typeParameters.map((t) { + return t.instantiate(nullabilitySuffix: _noneOrStarSuffix); + }).toFixedList(); + } else { + typeArguments = const []; + } + return _thisType = instantiate( + typeArguments: typeArguments, + nullabilitySuffix: _noneOrStarSuffix, + ); + } + return _thisType!; + } + + @override + List get typeParameters { + linkedData?.read(this); + return super.typeParameters; + } + + set typeParameters(List typeParameters) { + for (TypeParameterElement typeParameter in typeParameters) { + (typeParameter as TypeParameterElementImpl).enclosingElement = this; + } + _typeParameterElements = typeParameters; + } + + @override + ConstructorElement? get unnamedConstructor { + return constructors.firstWhereOrNull((element) => element.name.isEmpty); + } + + @override + FieldElement? getField(String name) { + return fields.firstWhereOrNull((fieldElement) => name == fieldElement.name); + } + + @override + PropertyAccessorElement? getGetter(String getterName) { + return accessors.firstWhereOrNull( + (accessor) => accessor.isGetter && accessor.name == getterName); + } + + @override + MethodElement? getMethod(String methodName) { + return methods.firstWhereOrNull((method) => method.name == methodName); + } + + @override + ConstructorElement? getNamedConstructor(String name) { + if (name == 'new') { + // A constructor declared as `C.new` is unnamed, and is modeled as such. + name = ''; + } + return constructors.firstWhereOrNull((element) => element.name == name); + } + + @override + PropertyAccessorElement? getSetter(String setterName) { + return getSetterFromAccessors(setterName, accessors); + } + + @override + InterfaceType instantiate({ + required List typeArguments, + required NullabilitySuffix nullabilitySuffix, + }) { + return InterfaceTypeImpl( + element: this, + typeArguments: typeArguments, + nullabilitySuffix: nullabilitySuffix, + ); + } + + @override + MethodElement? lookUpConcreteMethod( + String methodName, LibraryElement library) { + return _implementationsOfMethod(methodName).firstWhereOrNull( + (method) => !method.isAbstract && method.isAccessibleIn(library)); + } + + @override + PropertyAccessorElement? lookUpGetter( + String getterName, LibraryElement library) { + return _implementationsOfGetter(getterName) + .firstWhereOrNull((getter) => getter.isAccessibleIn(library)); + } + + @override + PropertyAccessorElement? lookUpInheritedConcreteGetter( + String getterName, LibraryElement library) { + return _implementationsOfGetter(getterName).firstWhereOrNull((getter) => + !getter.isAbstract && + !getter.isStatic && + getter.isAccessibleIn(library) && + getter.enclosingElement2 != this); + } + + ExecutableElement? lookUpInheritedConcreteMember( + String name, LibraryElement library) { + if (name.endsWith('=')) { + return lookUpInheritedConcreteSetter(name, library); + } else { + return lookUpInheritedConcreteMethod(name, library) ?? + lookUpInheritedConcreteGetter(name, library); + } + } + + @override + MethodElement? lookUpInheritedConcreteMethod( + String methodName, LibraryElement library) { + return _implementationsOfMethod(methodName).firstWhereOrNull((method) => + !method.isAbstract && + !method.isStatic && + method.isAccessibleIn(library) && + method.enclosingElement2 != this); + } + + @override + PropertyAccessorElement? lookUpInheritedConcreteSetter( + String setterName, LibraryElement library) { + return _implementationsOfSetter(setterName).firstWhereOrNull((setter) => + !setter.isAbstract && + !setter.isStatic && + setter.isAccessibleIn(library) && + setter.enclosingElement2 != this); + } + + @override + MethodElement? lookUpInheritedMethod( + String methodName, LibraryElement library) { + return _implementationsOfMethod(methodName).firstWhereOrNull((method) => + !method.isStatic && + method.isAccessibleIn(library) && + method.enclosingElement2 != this); + } + + @override + MethodElement? lookUpMethod(String methodName, LibraryElement library) { + return _implementationsOfMethod(methodName).firstWhereOrNull( + (MethodElement method) => method.isAccessibleIn(library)); + } + + @override + PropertyAccessorElement? lookUpSetter( + String setterName, LibraryElement library) { + return _implementationsOfSetter(setterName).firstWhereOrNull( + (PropertyAccessorElement setter) => setter.isAccessibleIn(library)); + } + + /// Return the static getter with the [name], accessible to the [library]. + /// + /// This method should be used only for error recovery during analysis, + /// when instance access to a static class member, defined in this class, + /// or a superclass. + PropertyAccessorElement? lookupStaticGetter( + String name, LibraryElement library) { + return _implementationsOfGetter(name).firstWhereOrNull( + (element) => element.isStatic && element.isAccessibleIn(library)); + } + + /// Return the static method with the [name], accessible to the [library]. + /// + /// This method should be used only for error recovery during analysis, + /// when instance access to a static class member, defined in this class, + /// or a superclass. + MethodElement? lookupStaticMethod(String name, LibraryElement library) { + return _implementationsOfMethod(name).firstWhereOrNull( + (element) => element.isStatic && element.isAccessibleIn(library)); + } + + /// Return the static setter with the [name], accessible to the [library]. + /// + /// This method should be used only for error recovery during analysis, + /// when instance access to a static class member, defined in this class, + /// or a superclass. + PropertyAccessorElement? lookupStaticSetter( + String name, LibraryElement library) { + return _implementationsOfSetter(name).firstWhereOrNull( + (element) => element.isStatic && element.isAccessibleIn(library)); + } + + void setLinkedData(Reference reference, LinkedData linkedData) { + this.reference = reference; + reference.element = this; + + this.linkedData = linkedData; + } + + /// Return an iterable containing all of the implementations of a getter with + /// the given [getterName] that are defined in this class and any superclass + /// of this class (but not in interfaces). + /// + /// The getters that are returned are not filtered in any way. In particular, + /// they can include getters that are not visible in some context. Clients + /// must perform any necessary filtering. + /// + /// The getters are returned based on the depth of their defining class; if + /// this class contains a definition of the getter it will occur first, if + /// Object contains a definition of the getter it will occur last. + Iterable _implementationsOfGetter( + String getterName) sync* { + final visitedClasses = {}; + InterfaceElement? classElement = this; + while (classElement != null && visitedClasses.add(classElement)) { + var getter = classElement.getGetter(getterName); + if (getter != null) { + yield getter; + } + for (InterfaceType mixin in classElement.mixins.reversed) { + getter = mixin.element.getGetter(getterName); + if (getter != null) { + yield getter; + } + } + classElement = classElement.supertype?.element; + } + } + + /// Return an iterable containing all of the implementations of a method with + /// the given [methodName] that are defined in this class and any superclass + /// of this class (but not in interfaces). + /// + /// The methods that are returned are not filtered in any way. In particular, + /// they can include methods that are not visible in some context. Clients + /// must perform any necessary filtering. + /// + /// The methods are returned based on the depth of their defining class; if + /// this class contains a definition of the method it will occur first, if + /// Object contains a definition of the method it will occur last. + Iterable _implementationsOfMethod(String methodName) sync* { + final visitedClasses = {}; + InterfaceElement? classElement = this; + while (classElement != null && visitedClasses.add(classElement)) { + var method = classElement.getMethod(methodName); + if (method != null) { + yield method; + } + for (InterfaceType mixin in classElement.mixins.reversed) { + method = mixin.element.getMethod(methodName); + if (method != null) { + yield method; + } + } + classElement = classElement.supertype?.element; + } + } + + /// Return an iterable containing all of the implementations of a setter with + /// the given [setterName] that are defined in this class and any superclass + /// of this class (but not in interfaces). + /// + /// The setters that are returned are not filtered in any way. In particular, + /// they can include setters that are not visible in some context. Clients + /// must perform any necessary filtering. + /// + /// The setters are returned based on the depth of their defining class; if + /// this class contains a definition of the setter it will occur first, if + /// Object contains a definition of the setter it will occur last. + Iterable _implementationsOfSetter( + String setterName) sync* { + final visitedClasses = {}; + InterfaceElement? classElement = this; + while (classElement != null && visitedClasses.add(classElement)) { + var setter = classElement.getSetter(setterName); + if (setter != null) { + yield setter; + } + for (InterfaceType mixin in classElement.mixins.reversed) { + setter = mixin.element.getSetter(setterName); + if (setter != null) { + yield setter; + } + } + classElement = classElement.supertype?.element; + } + } + + static PropertyAccessorElement? getSetterFromAccessors( + String setterName, List accessors) { + // TODO (jwren) revisit- should we append '=' here or require clients to + // include it? + // Do we need the check for isSetter below? + if (!setterName.endsWith('=')) { + setterName += '='; + } + return accessors.firstWhereOrNull( + (accessor) => accessor.isSetter && accessor.name == setterName); + } +} + class JoinPatternVariableElementImpl extends PatternVariableElementImpl implements JoinPatternVariableElement { @override @@ -5026,11 +4929,8 @@ class MethodElementImpl extends ExecutableElementImpl implements MethodElement { } /// A [ClassElementImpl] representing a mixin declaration. -class MixinElementImpl extends ClassOrMixinElementImpl implements MixinElement { - // TODO(brianwilkerson) Consider creating an abstract superclass of - // ClassElementImpl that contains the portions of the API that this class - // needs, and make this class extend the new class. - +class MixinElementImpl extends ClassOrMixinElementImpl + implements MixinElement { /// A list containing all of the superclass constraints that are defined for /// the mixin. List _superclassConstraints = const []; @@ -5057,12 +4957,12 @@ class MixinElementImpl extends ClassOrMixinElementImpl implements MixinElement { } @override - List get constructors { - return _constructors; - } + List get mixins => const []; @override - List get mixins => const []; + set mixins(List mixins) { + throw StateError('Attempt to set mixins for a mixin declaration.'); + } @override List get superclassConstraints { diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index a08bf341eb8..ca126bad0d2 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart @@ -789,7 +789,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { } if (recoveryStatic) { - final element = this.element as AbstractClassElementImpl; + final element = this.element as InterfaceElementImpl; return element.lookupStaticGetter(name, library); } @@ -828,7 +828,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { } if (recoveryStatic) { - final element = this.element as AbstractClassElementImpl; + final element = this.element as InterfaceElementImpl; return element.lookupStaticMethod(name, library); } @@ -867,7 +867,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { } if (recoveryStatic) { - final element = this.element as AbstractClassElementImpl; + final element = this.element as InterfaceElementImpl; return element.lookupStaticSetter(name, library); } diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart index c32c7b5003c..fc638df4fce 100644 --- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart @@ -258,7 +258,7 @@ class TypePropertyResolver { _needsGetterError = _getterRequested == null; if (_getterRequested == null && recoverWithStatic) { - var classElement = type.element as AbstractClassElementImpl; + var classElement = type.element as InterfaceElementImpl; _getterRecovery ??= classElement.lookupStaticGetter(_name, _definingLibrary) ?? classElement.lookupStaticMethod(_name, _definingLibrary); @@ -271,7 +271,7 @@ class TypePropertyResolver { _needsSetterError = _setterRequested == null; if (_setterRequested == null && recoverWithStatic) { - var classElement = type.element as AbstractClassElementImpl; + var classElement = type.element as InterfaceElementImpl; _setterRecovery ??= classElement.lookupStaticSetter(_name, _definingLibrary); _needsSetterError = _setterRecovery == null; diff --git a/pkg/analyzer/lib/src/generated/element_type_provider.dart b/pkg/analyzer/lib/src/generated/element_type_provider.dart index c089385a6f7..e2f076c0e6e 100644 --- a/pkg/analyzer/lib/src/generated/element_type_provider.dart +++ b/pkg/analyzer/lib/src/generated/element_type_provider.dart @@ -32,7 +32,7 @@ class ElementTypeProvider { void freshTypeParameterCreated(TypeParameterElement newTypeParameter, TypeParameterElement oldTypeParameter) {} - List getClassInterfaces(AbstractClassElementImpl element) => + List getClassInterfaces(InterfaceElementImpl element) => element.interfacesInternal; /// Queries the parameters of an executable element's signature. diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart index e43349ae8f1..068f9e1bc1a 100644 --- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart +++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart @@ -101,8 +101,8 @@ class ClassElementLinkedData extends ElementLinkedData { /// as well access them through their [Reference]s. For a class declaration /// this means reading them, for a named mixin application this means /// computing constructors. - void readMembers(ClassOrMixinElementImpl element) { - if (element is ClassElementImpl && element.isMixinApplication) { + void readMembers(ClassElementImpl element) { + if (element.isMixinApplication) { element.constructors; } else { _readMembers?.call(); @@ -668,7 +668,7 @@ class LibraryReader { List _readConstructors( CompilationUnitElementImpl unitElement, - AbstractClassElementImpl classElement, + InterfaceElementImpl classElement, Reference classReference, ) { var containerRef = classReference.getChild('@constructor'); diff --git a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart index 5ada31b9d8c..0fbb16543b1 100644 --- a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart +++ b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart @@ -17,7 +17,7 @@ class ConstructorInitializerResolver { void resolve() { for (var unitElement in _libraryElement.units) { - var interfaceElements = [ + var interfaceElements = [ ...unitElement.classes, ...unitElement.enums, ...unitElement.mixins, @@ -36,7 +36,7 @@ class ConstructorInitializerResolver { void _constructor( CompilationUnitElementImpl unitElement, - AbstractClassElementImpl classElement, + InterfaceElementImpl classElement, ConstructorElementImpl element, ) { if (element.isSynthetic) return; diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart index d16cf83cc4d..c6ef92593bf 100644 --- a/pkg/analyzer/lib/src/summary2/element_builder.dart +++ b/pkg/analyzer/lib/src/summary2/element_builder.dart @@ -1241,7 +1241,7 @@ class ElementBuilder extends ThrowingAstVisitor { node?.accept(this); } - void _resolveConstructorFieldFormals(AbstractClassElementImpl element) { + void _resolveConstructorFieldFormals(InterfaceElementImpl element) { for (var constructor in element.constructors) { for (var parameter in constructor.parameters) { if (parameter is FieldFormalParameterElementImpl) { diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart index 52b5f9a13bf..45626ead0c8 100644 --- a/pkg/analyzer/lib/src/summary2/types_builder.dart +++ b/pkg/analyzer/lib/src/summary2/types_builder.dart @@ -362,14 +362,14 @@ class TypesBuilder { ); } - static InterfaceType _objectType(AbstractClassElementImpl element) { + static InterfaceType _objectType(InterfaceElementImpl element) { return element.library.typeProvider.objectType; } } /// Performs mixins inference in a [ClassDeclaration]. class _MixinInference { - final AbstractClassElementImpl element; + final InterfaceElementImpl element; final TypeSystemImpl typeSystem; final FeatureSet featureSet; final InterfaceType classType; @@ -534,15 +534,14 @@ class _MixinsInference { /// we are inferring the [element] now, i.e. there is a loop. /// /// This is an error. So, we return the empty list, and break the loop. - List _callbackWhenLoop(AbstractClassElementImpl element) { + List _callbackWhenLoop(InterfaceElementImpl element) { element.mixinInferenceCallback = null; return []; } /// This method is invoked when mixins are asked from the [element], and /// we are not inferring the [element] now, i.e. there is no loop. - List? _callbackWhenRecursion( - AbstractClassElementImpl element) { + List? _callbackWhenRecursion(InterfaceElementImpl element) { var node = _linker.getLinkingNode(element); if (node != null) { _inferDeclaration(node); @@ -551,7 +550,7 @@ class _MixinsInference { return null; } - void _infer(AbstractClassElementImpl element, WithClause? withClause) { + void _infer(InterfaceElementImpl element, WithClause? withClause) { if (withClause != null) { element.mixinInferenceCallback = _callbackWhenLoop; try { diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart index 963299a32ba..0b031acd17f 100644 --- a/pkg/analyzer/lib/src/task/strong_mode.dart +++ b/pkg/analyzer/lib/src/task/strong_mode.dart @@ -303,7 +303,7 @@ class InstanceMemberInferrer { /// [classElement]. void _inferClass(InterfaceElement classElement) { _setInducedModifier(classElement); - if (classElement is AbstractClassElementImpl) { + if (classElement is InterfaceElementImpl) { if (classElement.hasBeenInferred) { return; } @@ -338,7 +338,7 @@ class InstanceMemberInferrer { ); } for (var method in classElement.methods) { - _inferExecutable(method as MethodElementImpl); + _inferExecutable(method); } // // Infer initializing formal parameter types. This must happen after diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart index b98d1cda67a..2cbad61ca3f 100644 --- a/pkg/nnbd_migration/lib/src/fix_builder.dart +++ b/pkg/nnbd_migration/lib/src/fix_builder.dart @@ -374,7 +374,7 @@ class MigrationResolutionHooksImpl } @override - List getClassInterfaces(AbstractClassElementImpl element) { + List getClassInterfaces(InterfaceElementImpl element) { return _wrapExceptions( _fixBuilder.unit, () => element.interfacesInternal,