| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:collection'; |
| import 'dart:typed_data'; |
| |
| import 'package:_fe_analyzer_shared/src/scanner/string_canonicalizer.dart'; |
| import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart' |
| as shared; |
| import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart' |
| as shared; |
| import 'package:analyzer/dart/analysis/features.dart'; |
| import 'package:analyzer/dart/analysis/session.dart'; |
| import 'package:analyzer/dart/ast/token.dart'; |
| import 'package:analyzer/dart/constant/value.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| import 'package:analyzer/dart/element/element2.dart'; |
| import 'package:analyzer/dart/element/nullability_suffix.dart'; |
| import 'package:analyzer/dart/element/scope.dart'; |
| import 'package:analyzer/dart/element/type.dart'; |
| import 'package:analyzer/dart/element/type_provider.dart'; |
| import 'package:analyzer/dart/element/type_system.dart'; |
| import 'package:analyzer/error/error.dart'; |
| import 'package:analyzer/source/line_info.dart'; |
| import 'package:analyzer/source/source.dart'; |
| import 'package:analyzer/src/dart/analysis/experiments.dart'; |
| import 'package:analyzer/src/dart/analysis/session.dart'; |
| import 'package:analyzer/src/dart/ast/ast.dart'; |
| import 'package:analyzer/src/dart/ast/token.dart'; |
| import 'package:analyzer/src/dart/constant/compute.dart'; |
| import 'package:analyzer/src/dart/constant/evaluation.dart'; |
| import 'package:analyzer/src/dart/constant/value.dart'; |
| import 'package:analyzer/src/dart/element/display_string_builder.dart'; |
| import 'package:analyzer/src/dart/element/field_name_non_promotability_info.dart'; |
| import 'package:analyzer/src/dart/element/member.dart'; |
| import 'package:analyzer/src/dart/element/name_union.dart'; |
| import 'package:analyzer/src/dart/element/scope.dart'; |
| import 'package:analyzer/src/dart/element/since_sdk_version.dart'; |
| import 'package:analyzer/src/dart/element/type.dart'; |
| import 'package:analyzer/src/dart/element/type_algebra.dart'; |
| import 'package:analyzer/src/dart/element/type_provider.dart'; |
| import 'package:analyzer/src/dart/element/type_system.dart'; |
| import 'package:analyzer/src/dart/resolver/scope.dart' |
| show Namespace, NamespaceBuilder; |
| import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
| import 'package:analyzer/src/generated/sdk.dart' show DartSdk; |
| import 'package:analyzer/src/generated/source.dart' show DartUriResolver; |
| import 'package:analyzer/src/generated/utilities_collection.dart'; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| import 'package:analyzer/src/summary2/ast_binary_tokens.dart'; |
| import 'package:analyzer/src/summary2/bundle_reader.dart'; |
| import 'package:analyzer/src/summary2/export.dart'; |
| import 'package:analyzer/src/summary2/macro.dart'; |
| import 'package:analyzer/src/summary2/macro_application_error.dart'; |
| import 'package:analyzer/src/summary2/reference.dart'; |
| import 'package:analyzer/src/task/inference_error.dart'; |
| import 'package:analyzer/src/util/file_paths.dart' as file_paths; |
| import 'package:analyzer/src/utilities/extensions/collection.dart'; |
| import 'package:analyzer/src/utilities/extensions/object.dart'; |
| import 'package:analyzer/src/utilities/extensions/string.dart'; |
| import 'package:collection/collection.dart'; |
| import 'package:pub_semver/pub_semver.dart'; |
| |
| /// Shared implementation of `augmentation` and `augmentationTarget`. |
| mixin AugmentableElement<T extends ElementImpl> on ElementImpl { |
| T? _augmentation; |
| ElementImpl? _augmentationTargetAny; |
| |
| T? get augmentation { |
| linkedData?.read(this); |
| return _augmentation; |
| } |
| |
| set augmentation(T? value) { |
| _augmentation = value; |
| } |
| |
| T? get augmentationTarget { |
| return augmentationTargetAny.ifTypeOrNull(); |
| } |
| |
| ElementImpl? get augmentationTargetAny { |
| linkedData?.read(this); |
| return _augmentationTargetAny; |
| } |
| |
| set augmentationTargetAny(ElementImpl? value) { |
| _augmentationTargetAny = value; |
| } |
| |
| bool get isAugmentation { |
| return hasModifier(Modifier.AUGMENTATION); |
| } |
| |
| set isAugmentation(bool value) { |
| setModifier(Modifier.AUGMENTATION, value); |
| } |
| |
| bool get isAugmentationChainStart { |
| return hasModifier(Modifier.AUGMENTATION_CHAIN_START); |
| } |
| |
| set isAugmentationChainStart(bool value) { |
| setModifier(Modifier.AUGMENTATION_CHAIN_START, value); |
| } |
| |
| ElementLinkedData? get linkedData; |
| } |
| |
| class AugmentationImportElementImpl extends _ExistingElementImpl |
| implements AugmentationImportElement { |
| @override |
| final int importKeywordOffset; |
| |
| @override |
| final DirectiveUri uri; |
| |
| AugmentationImportElementImpl({ |
| required this.importKeywordOffset, |
| required this.uri, |
| }) : super(null, importKeywordOffset); |
| |
| @override |
| LibraryOrAugmentationElementImpl get enclosingElement { |
| return super.enclosingElement as LibraryOrAugmentationElementImpl; |
| } |
| |
| @override |
| LibraryAugmentationElementImpl? get importedAugmentation { |
| var uri = this.uri; |
| if (uri is DirectiveUriWithAugmentationImpl) { |
| return uri.augmentation; |
| } |
| return null; |
| } |
| |
| @override |
| ElementKind get kind => ElementKind.AUGMENTATION_IMPORT; |
| |
| @override |
| T? accept<T>(ElementVisitor<T> visitor) => |
| visitor.visitAugmentationImportElement(this); |
| } |
| |
| class AugmentedClassElementImpl extends AugmentedInterfaceElementImpl |
| with MaybeAugmentedClassElementMixin { |
| @override |
| final ClassElementImpl declaration; |
| |
| AugmentedClassElementImpl(this.declaration); |
| } |
| |
| class AugmentedEnumElementImpl extends AugmentedInterfaceElementImpl |
| with MaybeAugmentedEnumElementMixin { |
| @override |
| final EnumElementImpl declaration; |
| |
| AugmentedEnumElementImpl(this.declaration); |
| } |
| |
| class AugmentedExtensionElementImpl extends AugmentedInstanceElementImpl |
| with MaybeAugmentedExtensionElementMixin { |
| @override |
| final ExtensionElementImpl declaration; |
| |
| AugmentedExtensionElementImpl(this.declaration); |
| } |
| |
| class AugmentedExtensionTypeElementImpl extends AugmentedInterfaceElementImpl |
| with MaybeAugmentedExtensionTypeElementMixin { |
| @override |
| final ExtensionTypeElementImpl declaration; |
| |
| AugmentedExtensionTypeElementImpl(this.declaration); |
| } |
| |
| abstract class AugmentedInstanceElementImpl |
| with MaybeAugmentedInstanceElementMixin { |
| @override |
| List<FieldElement> fields = []; |
| |
| @override |
| List<PropertyAccessorElement> accessors = []; |
| |
| @override |
| List<MethodElement> methods = []; |
| |
| @override |
| // TODO(scheglov): implement metadata |
| List<ElementAnnotationImpl> get metadata => throw UnimplementedError(); |
| } |
| |
| abstract class AugmentedInterfaceElementImpl |
| extends AugmentedInstanceElementImpl |
| with MaybeAugmentedInterfaceElementMixin { |
| @override |
| List<InterfaceType> interfaces = []; |
| |
| @override |
| List<InterfaceType> mixins = []; |
| |
| @override |
| List<ConstructorElement> constructors = []; |
| } |
| |
| class AugmentedMixinElementImpl extends AugmentedInterfaceElementImpl |
| with MaybeAugmentedMixinElementMixin { |
| @override |
| final MixinElementImpl declaration; |
| |
| @override |
| List<InterfaceType> superclassConstraints = []; |
| |
| AugmentedMixinElementImpl(this.declaration); |
| } |
| |
| class BindPatternVariableElementImpl extends PatternVariableElementImpl |
| implements BindPatternVariableElement { |
| final DeclaredVariablePatternImpl node; |
| |
| /// This flag is set to `true` if this variable clashes with another |
| /// pattern variable with the same name within the same pattern. |
| bool isDuplicate = false; |
| |
| BindPatternVariableElementImpl(this.node, super.name, super.offset); |
| } |
| |
| /// An [InterfaceElementImpl] which is a class. |
| class ClassElementImpl extends ClassOrMixinElementImpl |
| with AugmentableElement<ClassElementImpl> |
| implements ClassElement { |
| late MaybeAugmentedClassElementMixin augmentedInternal = |
| NotAugmentedClassElementImpl(this); |
| |
| /// 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 |
| set accessors(List<PropertyAccessorElementImpl> accessors) { |
| assert(!isMixinApplication); |
| super.accessors = accessors; |
| } |
| |
| /// If we can find all possible subtypes of this class, return them. |
| /// |
| /// If the class is final, all its subtypes are declared in this library. |
| /// |
| /// If the class is sealed, and all its subtypes are either final or sealed, |
| /// then these subtypes are all subtypes that are possible. |
| List<InterfaceType>? get allSubtypes { |
| if (isFinal) { |
| var result = <InterfaceType>[]; |
| for (var element in library.topLevelElements) { |
| if (element is InterfaceElement && element != this) { |
| var elementThis = element.thisType; |
| if (elementThis.asInstanceOf(this) != null) { |
| result.add(elementThis); |
| } |
| } |
| } |
| return result; |
| } |
| |
| if (isSealed) { |
| var result = <InterfaceType>[]; |
| for (var element in library.topLevelElements) { |
| if (element is! InterfaceElement || identical(element, this)) { |
| continue; |
| } |
| |
| var elementThis = element.thisType; |
| if (elementThis.asInstanceOf(this) == null) { |
| continue; |
| } |
| |
| switch (element) { |
| case ClassElement _: |
| if (element.isFinal || element.isSealed) { |
| result.add(elementThis); |
| } else { |
| return null; |
| } |
| case EnumElement _: |
| result.add(elementThis); |
| case MixinElement _: |
| return null; |
| } |
| } |
| return result; |
| } |
| |
| return null; |
| } |
| |
| @override |
| MaybeAugmentedClassElementMixin get augmented { |
| if (isAugmentation) { |
| if (augmentationTarget case var augmentationTarget?) { |
| return augmentationTarget.augmented; |
| } |
| } |
| |
| linkedData?.read(this); |
| return augmentedInternal; |
| } |
| |
| AugmentedClassElementImpl? get augmentedIfReally { |
| if (augmentationTarget != null) { |
| if (augmented case AugmentedClassElementImpl augmented) { |
| return augmented; |
| } |
| } |
| return null; |
| } |
| |
| @override |
| set constructors(List<ConstructorElementImpl> constructors) { |
| assert(!isMixinApplication); |
| super.constructors = constructors; |
| } |
| |
| @override |
| set fields(List<FieldElementImpl> fields) { |
| assert(!isMixinApplication); |
| super.fields = fields; |
| } |
| |
| bool get hasExtendsClause { |
| return hasModifier(Modifier.HAS_EXTENDS_CLAUSE); |
| } |
| |
| set hasExtendsClause(bool value) { |
| setModifier(Modifier.HAS_EXTENDS_CLAUSE, value); |
| } |
| |
| bool get hasGenerativeConstConstructor { |
| return constructors.any((c) => !c.isFactory && c.isConst); |
| } |
| |
| @override |
| bool get hasNonFinalField { |
| var classesToVisit = <InterfaceElement>[]; |
| var visitedClasses = <InterfaceElement>{}; |
| classesToVisit.add(this); |
| while (classesToVisit.isNotEmpty) { |
| var 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) { |
| classesToVisit.add(mixinType.element); |
| } |
| // check super |
| var supertype = currentElement.supertype; |
| if (supertype != null) { |
| classesToVisit.add(supertype.element); |
| } |
| } |
| } |
| // not found |
| return false; |
| } |
| |
| /// Return `true` if the class has a concrete `noSuchMethod()` method distinct |
| /// from the one declared in class `Object`, as per the Dart Language |
| /// Specification (section 10.4). |
| bool get hasNoSuchMethod { |
| MethodElement? method = lookUpConcreteMethod( |
| FunctionElement.NO_SUCH_METHOD_METHOD_NAME, library); |
| var definingClass = method?.enclosingElement as ClassElement?; |
| return definingClass != null && !definingClass.isDartCoreObject; |
| } |
| |
| @override |
| bool get isAbstract { |
| return hasModifier(Modifier.ABSTRACT); |
| } |
| |
| set isAbstract(bool isAbstract) { |
| setModifier(Modifier.ABSTRACT, isAbstract); |
| } |
| |
| @override |
| bool get isBase { |
| return hasModifier(Modifier.BASE); |
| } |
| |
| @override |
| bool get isConstructable => !isSealed && !isAbstract; |
| |
| @override |
| bool get isDartCoreEnum { |
| return name == 'Enum' && library.isDartCore; |
| } |
| |
| @override |
| bool get isDartCoreObject { |
| return name == 'Object' && library.isDartCore; |
| } |
| |
| bool get isDartCoreRecord { |
| return name == 'Record' && library.isDartCore; |
| } |
| |
| bool get isEnumLike { |
| // Must be a concrete class. |
| if (isAbstract) { |
| return false; |
| } |
| |
| // With only private non-factory constructors. |
| for (var constructor in constructors) { |
| if (constructor.isPublic || constructor.isFactory) { |
| return false; |
| } |
| } |
| |
| // With 2+ static const fields with the type of this class. |
| var numberOfElements = 0; |
| for (var field in fields) { |
| if (field.isStatic && field.isConst && field.type == thisType) { |
| numberOfElements++; |
| } |
| } |
| if (numberOfElements < 2) { |
| return false; |
| } |
| |
| // No subclasses in the library. |
| for (var unit in library.units) { |
| for (var class_ in unit.classes) { |
| if (class_.supertype?.element == this) { |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| @override |
| bool get isExhaustive => isSealed; |
| |
| @override |
| bool get isFinal { |
| return hasModifier(Modifier.FINAL); |
| } |
| |
| set isFinal(bool isFinal) { |
| setModifier(Modifier.FINAL, isFinal); |
| } |
| |
| @override |
| bool get isInterface { |
| return hasModifier(Modifier.INTERFACE); |
| } |
| |
| set isInterface(bool isInterface) { |
| setModifier(Modifier.INTERFACE, isInterface); |
| } |
| |
| bool get isMacro { |
| return hasModifier(Modifier.MACRO); |
| } |
| |
| set isMacro(bool isMacro) { |
| setModifier(Modifier.MACRO, isMacro); |
| } |
| |
| @override |
| bool get isMixinApplication { |
| return hasModifier(Modifier.MIXIN_APPLICATION); |
| } |
| |
| /// Set whether this class is a mixin application. |
| set isMixinApplication(bool isMixinApplication) { |
| setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); |
| } |
| |
| @override |
| bool get isMixinClass { |
| return hasModifier(Modifier.MIXIN_CLASS); |
| } |
| |
| set isMixinClass(bool isMixinClass) { |
| setModifier(Modifier.MIXIN_CLASS, isMixinClass); |
| } |
| |
| @override |
| bool get isSealed { |
| return hasModifier(Modifier.SEALED); |
| } |
| |
| set isSealed(bool isSealed) { |
| setModifier(Modifier.SEALED, isSealed); |
| } |
| |
| @override |
| bool get isValidMixin { |
| var supertype = this.supertype; |
| if (supertype != null && !supertype.isDartCoreObject) { |
| return false; |
| } |
| for (ConstructorElement constructor in constructors) { |
| if (!constructor.isSynthetic && !constructor.isFactory) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @override |
| ElementKind get kind => ElementKind.CLASS; |
| |
| @override |
| set methods(List<MethodElementImpl> methods) { |
| assert(!isMixinApplication); |
| super.methods = methods; |
| } |
| |
| @override |
| T? accept<T>(ElementVisitor<T> visitor) { |
| return visitor.visitClassElement(this); |
| } |
| |
| @override |
| void appendTo(ElementDisplayStringBuilder builder) { |
| builder.writeClassElement(this); |
| } |
| |
| @override |
| bool isExtendableIn(LibraryElement library) { |
| if (library == this.library) { |
| return true; |
| } |
| return !isInterface && !isFinal && !isSealed; |
| } |
| |
| @override |
| bool isImplementableIn(LibraryElement library) { |
| if (library == this.library) { |
| return true; |
| } |
| return !isBase && !isFinal && !isSealed; |
| } |
| |
| @override |
| bool isMixableIn(LibraryElement library) { |
| if (library == this.library) { |
| return true; |
| } else if (this.library.featureSet.isEnabled(Feature.class_modifiers)) { |
| return isMixinClass && !isInterface && !isFinal && !isSealed; |
| } |
| return true; |
| } |
| |
| @override |
| void _buildMixinAppConstructors() { |
| // Do nothing if not a mixin application. |
| if (!isMixinApplication) { |
| return; |
| } |
| |
| // Assign to break a possible infinite recursion during computing. |
| _constructors = const <ConstructorElementImpl>[]; |
| |
| var superType = supertype; |
| if (superType == null) { |
| // Shouldn't ever happen, since the only classes with no supertype are |
| // Object and mixins, and they aren't a mixin application. But for |
| // safety's sake just assume an empty list. |
| assert(false); |
| _constructors = <ConstructorElementImpl>[]; |
| return; |
| } |
| |
| var superElement = superType.element as ClassElementImpl; |
| |
| var constructorsToForward = superElement.constructors |
| .where((constructor) => constructor.isAccessibleIn(library)) |
| .where((constructor) => !constructor.isFactory); |
| |
| // 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`. |
| var superClassParameters = superElement.typeParameters; |
| List<DartType> argumentTypes = List<DartType>.filled( |
| superClassParameters.length, DynamicTypeImpl.instance); |
| for (int i = 0; i < superType.typeArguments.length; i++) { |
| if (i >= argumentTypes.length) { |
| break; |
| } |
| argumentTypes[i] = superType.typeArguments[i]; |
| } |
| var substitution = |
| Substitution.fromPairs(superClassParameters, argumentTypes); |
| |
| bool typeHasInstanceVariables(InterfaceType type) => |
| type.element.fields.any((e) => !e.isSynthetic); |
| |
| // Now create an implicit constructor for every constructor found above, |
| // substituting type parameters as appropriate. |
| _constructors = constructorsToForward.map((superclassConstructor) { |
| var name = superclassConstructor.name; |
| var implicitConstructor = ConstructorElementImpl(name, -1); |
| implicitConstructor.isSynthetic = true; |
| implicitConstructor.name = name; |
| implicitConstructor.nameOffset = -1; |
| |
| var containerRef = reference!.getChild('@constructor'); |
| var referenceName = name.ifNotEmptyOrElse('new'); |
| var implicitReference = containerRef.getChild(referenceName); |
| implicitConstructor.reference = implicitReference; |
| implicitReference.element = implicitConstructor; |
| |
| var hasMixinWithInstanceVariables = mixins.any(typeHasInstanceVariables); |
| implicitConstructor.isConst = |
| superclassConstructor.isConst && !hasMixinWithInstanceVariables; |
| List<ParameterElement> superParameters = superclassConstructor.parameters; |
| int count = superParameters.length; |
| var argumentsForSuperInvocation = <ExpressionImpl>[]; |
| if (count > 0) { |
| var implicitParameters = <ParameterElement>[]; |
| for (int i = 0; i < count; i++) { |
| ParameterElement superParameter = superParameters[i]; |
| ParameterElementImpl implicitParameter; |
| if (superParameter is ConstVariableElement) { |
| var constVariable = superParameter as ConstVariableElement; |
| implicitParameter = DefaultParameterElementImpl( |
| name: superParameter.name, |
| nameOffset: -1, |
| // ignore: deprecated_member_use_from_same_package |
| parameterKind: superParameter.parameterKind, |
| )..constantInitializer = constVariable.constantInitializer; |
| if (superParameter.isNamed) { |
| var reference = implicitReference |
| .getChild('@parameter') |
| .getChild(implicitParameter.name); |
| implicitParameter.reference = reference; |
| reference.element = implicitParameter; |
| } |
| } else { |
| implicitParameter = ParameterElementImpl( |
| name: superParameter.name, |
| nameOffset: -1, |
| // ignore: deprecated_member_use_from_same_package |
| parameterKind: superParameter.parameterKind, |
| ); |
| } |
| implicitParameter.isConst = superParameter.isConst; |
| implicitParameter.isFinal = superParameter.isFinal; |
| implicitParameter.isSynthetic = true; |
| implicitParameter.type = |
| substitution.substituteType(superParameter.type); |
| implicitParameters.add(implicitParameter); |
| argumentsForSuperInvocation.add( |
| SimpleIdentifierImpl( |
| StringToken(TokenType.STRING, implicitParameter.name, -1), |
| ) |
| ..staticElement = implicitParameter |
| ..setPseudoExpressionStaticType(implicitParameter.type), |
| ); |
| } |
| implicitConstructor.parameters = implicitParameters.toFixedList(); |
| } |
| implicitConstructor.enclosingElement3 = this; |
| implicitConstructor.enclosingElement = this; |
| // TODO(scheglov): Why do we manually map parameters types above? |
| implicitConstructor.superConstructor = |
| ConstructorMember.from(superclassConstructor, superType); |
| |
| var isNamed = superclassConstructor.name.isNotEmpty; |
| implicitConstructor.constantInitializers = [ |
| SuperConstructorInvocationImpl( |
| superKeyword: Tokens.super_(), |
| period: isNamed ? Tokens.period() : null, |
| constructorName: isNamed |
| ? (SimpleIdentifierImpl( |
| StringToken(TokenType.STRING, superclassConstructor.name, -1), |
| )..staticElement = superclassConstructor) |
| : null, |
| argumentList: ArgumentListImpl( |
| leftParenthesis: Tokens.openParenthesis(), |
| arguments: argumentsForSuperInvocation, |
| rightParenthesis: Tokens.closeParenthesis(), |
| ), |
| )..staticElement = superclassConstructor, |
| ]; |
| |
| return implicitConstructor; |
| }).toList(growable: false); |
| } |
| } |
| |
| 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); |
| |
| bool get isBase { |
| return hasModifier(Modifier.BASE); |
| } |
| |
| set isBase(bool isBase) { |
| setModifier(Modifier.BASE, isBase); |
| } |
| } |
| |
| /// A concrete implementation of a [CompilationUnitElement] or |
| /// [LibraryFragment]. |
| class CompilationUnitElementImpl extends UriReferencedElementImpl |
| implements CompilationUnitElement, LibraryFragment { |
| /// The source that corresponds to this compilation unit. |
| @override |
| final Source source; |
| |
| @override |
| LineInfo lineInfo; |
| |
| @override |
| final LibraryElementImpl library; |
| |
| // TODO(scheglov): Remove after removing [LibraryAugmentationElementImpl]. |
| late final LibraryOrAugmentationElementImpl libraryOrAugmentationElement; |
| |
| /// The libraries exported by this unit. |
| List<LibraryExportElementImpl> _libraryExports = |
| _Sentinel.libraryExportElement; |
| |
| /// The libraries imported by this unit. |
| List<LibraryImportElementImpl> _libraryImports = |
| _Sentinel.libraryImportElement; |
| |
| /// The cached list of prefixes from [libraryImports]. |
| List<PrefixElementImpl>? _libraryImportPrefixes; |
| |
| /// The parts included by this unit. |
| List<PartElementImpl> _parts = const <PartElementImpl>[]; |
| |
| /// A list containing all of the top-level accessors (getters and setters) |
| /// contained in this compilation unit. |
| List<PropertyAccessorElementImpl> _accessors = const []; |
| |
| List<ClassElementImpl> _classes = const []; |
| |
| /// A list containing all of the enums contained in this compilation unit. |
| List<EnumElementImpl> _enums = const []; |
| |
| /// A list containing all of the extensions contained in this compilation |
| /// unit. |
| List<ExtensionElementImpl> _extensions = const []; |
| |
| List<ExtensionTypeElementImpl> _extensionTypes = const []; |
| |
| /// A list containing all of the top-level functions contained in this |
| /// compilation unit. |
| List<FunctionElementImpl> _functions = const []; |
| |
| List<MixinElementImpl> _mixins = const []; |
| |
| /// A list containing all of the type aliases contained in this compilation |
| /// unit. |
| List<TypeAliasElementImpl> _typeAliases = const []; |
| |
| /// A list containing all of the variables contained in this compilation unit. |
| List<TopLevelVariableElementImpl> _variables = const []; |
| |
| ElementLinkedData? linkedData; |
| |
| /// Initialize a newly created compilation unit element to have the given |
| /// [name]. |
| CompilationUnitElementImpl({ |
| required this.library, |
| required this.source, |
| required this.lineInfo, |
| }) : super(null, -1); |
| |
| @override |
| List<PropertyAccessorElementImpl> get accessors { |
| return _accessors; |
| } |
| |
| /// Set the top-level accessors (getters and setters) contained in this |
| /// compilation unit to the given [accessors]. |
| set accessors(List<PropertyAccessorElementImpl> accessors) { |
| for (var accessor in accessors) { |
| accessor.enclosingElement3 = this; |
| accessor.enclosingElement = this; |
| } |
| _accessors = accessors; |
| } |
| |
| @override |
| List<Element> get children => [ |
| ...super.children, |
| ...accessors, |
| ...classes, |
| ...enums, |
| ...extensions, |
| ...extensionTypes, |
| ...functions, |
| ...mixins, |
| ...typeAliases, |
| ...topLevelVariables, |
| ]; |
| |
| @override |
| List<Fragment> get children3 => children.cast<Fragment>(); |
| |
| @override |
| List<ClassElementImpl> get classes { |
| return _classes; |
| } |
| |
| /// Set the classes contained in this compilation unit to [classes]. |
| set classes(List<ClassElementImpl> classes) { |
| for (var class_ in classes) { |
| class_.enclosingElement3 = this; |
| class_.enclosingElement = this; |
| } |
| _classes = classes; |
| } |
| |
| @override |
| List<ClassFragment> get classes2 => classes.cast<ClassFragment>(); |
| |
| @override |
| LibraryElement2 get element => enclosingElement as LibraryElement2; |
| |
| @override |
| LibraryOrAugmentationElement get enclosingElement => |
| libraryOrAugmentationElement; |
| |
| @override |
| CompilationUnitElementImpl? get enclosingElement3 { |
| switch (libraryOrAugmentationElement) { |
| case LibraryElementImpl library: |
| if (identical(library.definingCompilationUnit, this)) { |
| return null; |
| } |
| return library.definingCompilationUnit; |
| default: |
| return (libraryOrAugmentationElement.enclosingElement3 |
| as LibraryOrAugmentationElementImpl) |
| .definingCompilationUnit; |
| } |
| } |
| |
| @override |
| LibraryFragment? get enclosingFragment => null; |
| |
| @override |
| CompilationUnitElementImpl get enclosingUnit { |
| return this; |
| } |
| |
| @override |
| List<EnumElementImpl> get enums { |
| return _enums; |
| } |
| |
| /// Set the enums contained in this compilation unit to the given [enums]. |
| set enums(List<EnumElementImpl> enums) { |
| for (var element in enums) { |
| element.enclosingElement3 = this; |
| element.enclosingElement = this; |
| } |
| _enums = enums; |
| } |
| |
| @override |
| List<EnumFragment> get enums2 => enums.cast<EnumFragment>(); |
| |
| @override |
| List<ExtensionElementImpl> get extensions { |
| return _extensions; |
| } |
| |
| /// Set the extensions contained in this compilation unit to the given |
| /// [extensions]. |
| set extensions(List<ExtensionElementImpl> extensions) { |
| for (var extension in extensions) { |
| extension.enclosingElement3 = this; |
| extension.enclosingElement = this; |
| } |
| _extensions = extensions; |
| } |
| |
| @override |
| List<ExtensionFragment> get extensions2 => |
| extensions.cast<ExtensionFragment>(); |
| |
| @override |
| List<ExtensionTypeElementImpl> get extensionTypes { |
| return _extensionTypes; |
| } |
| |
| set extensionTypes(List<ExtensionTypeElementImpl> elements) { |
| for (var element in elements) { |
| element.enclosingElement3 = this; |
| element.enclosingElement = this; |
| } |
| _extensionTypes = elements; |
| } |
| |
| @override |
| List<ExtensionTypeFragment> get extensionTypes2 => |
| extensionTypes.cast<ExtensionTypeFragment>(); |
| |
| @override |
| List<FunctionElementImpl> get functions { |
| return _functions; |
| } |
| |
| /// Set the top-level functions contained in this compilation unit to the |
| /// given[functions]. |
| set functions(List<FunctionElementImpl> functions) { |
| for (var function in functions) { |
| function.enclosingElement3 = this; |
| function.enclosingElement = this; |
| } |
| _functions = functions; |
| } |
| |
| @override |
| List<TopLevelFunctionFragment> get functions2 => |
| functions.cast<TopLevelFunctionFragment>(); |
| |
| @override |
| List<GetterFragment> get getters => accessors |
| .where((element) => element.isGetter) |
| .cast<GetterFragment>() |
| .toList(); |
| |
| @override |
| int get hashCode => source.hashCode; |
| |
| @override |
| String get identifier => '${source.uri}'; |
| |
| @override |
| ElementKind get kind => ElementKind.COMPILATION_UNIT; |
| |
| @override |
| List<LibraryExportElementImpl> get libraryExports { |
| linkedData?.read(this); |
| return _libraryExports; |
| } |
| |
| set libraryExports(List<LibraryExportElementImpl> exports) { |
| for (var exportElement in exports) { |
| exportElement.enclosingElement3 = this; |
| exportElement.enclosingElement = library; |
| } |
| _libraryExports = exports; |
| } |
| |
| @override |
| List<LibraryExport> get libraryExports2 => |
| libraryExports.cast<LibraryExport>(); |
| |
| List<LibraryExportElementImpl> get libraryExports_unresolved { |
| return _libraryExports; |
| } |
| |
| @override |
| LibraryFragment get libraryFragment => this; |
| |
| @override |
| List<PrefixElementImpl> get libraryImportPrefixes { |
| return _libraryImportPrefixes ??= _buildLibraryImportPrefixes(); |
| } |
| |
| @override |
| List<LibraryImportElementImpl> get libraryImports { |
| linkedData?.read(this); |
| return _libraryImports; |
| } |
| |
| set libraryImports(List<LibraryImportElementImpl> imports) { |
| for (var importElement in imports) { |
| importElement.enclosingElement3 = this; |
| importElement.enclosingElement = library; |
| } |
| _libraryImports = imports; |
| _libraryImportPrefixes = null; |
| } |
| |
| @override |
| List<LibraryImport> get libraryImports2 => |
| libraryImports.cast<LibraryImport>(); |
| |
| List<LibraryImportElementImpl> get libraryImports_unresolved { |
| return _libraryImports; |
| } |
| |
| @override |
| Source get librarySource => library.source; |
| |
| @override |
| List<ElementAnnotationImpl> get metadata { |
| linkedData?.read(this); |
| return super.metadata; |
| } |
| |
| @override |
| List<MixinElementImpl> get mixins { |
| return _mixins; |
| } |
| |
| /// Set the mixins contained in this compilation unit to the given [mixins]. |
| set mixins(List<MixinElementImpl> mixins) { |
| for (var mixin_ in mixins) { |
| mixin_.enclosingElement3 = this; |
| mixin_.enclosingElement = this; |
| } |
| _mixins = mixins; |
| } |
| |
| @override |
| List<MixinFragment> get mixins2 => mixins.cast<MixinFragment>(); |
| |
| @override |
| Fragment? get nextFragment => throw UnsupportedError('Not yet implemented'); |
| |
| @override |
| List<PartInclude> get partIncludes => |
| libraryImportPrefixes.cast<PartInclude>(); |
| |
| @override |
| List<PartElementImpl> get parts => _parts; |
| |
| set parts(List<PartElementImpl> parts) { |
| for (var part in parts) { |
| part.enclosingElement3 = this; |
| part.enclosingElement = library; |
| var uri = part.uri; |
| if (uri is DirectiveUriWithUnitImpl) { |
| uri.unit.libraryOrAugmentationElement = library; |
| uri.unit.enclosingElement3 = this; |
| uri.unit.enclosingElement = library; |
| } |
| } |
| _parts = parts; |
| } |
| |
| @override |
| List<PrefixElement2> get prefixes => |
| libraryImportPrefixes.cast<PrefixElement2>(); |
| |
| @override |
| Fragment? get previousFragment => |
| throw UnsupportedError('Not yet implemented'); |
| |
| @override |
| Scope get scope => enclosingElement.scope; |
| |
| @override |
| AnalysisSession get session => enclosingElement.session; |
| |
| @override |
| List<SetterFragment> get setters => accessors |
| .where((element) => element.isSetter) |
| .cast<SetterFragment>() |
| .toList(); |
| |
| @override |
| List<TopLevelVariableElementImpl> get topLevelVariables { |
| return _variables; |
| } |
| |
| /// Set the top-level variables contained in this compilation unit to the |
| /// given[variables]. |
| set topLevelVariables(List<TopLevelVariableElementImpl> variables) { |
| for (var variable in variables) { |
| variable.enclosingElement3 = this; |
| variable.enclosingElement = this; |
| } |
| _variables = variables; |
| } |
| |
| @override |
| List<TopLevelVariableFragment> get topLevelVariables2 => |
| topLevelVariables.cast<TopLevelVariableFragment>(); |
| |
| @override |
| List<TypeAliasElementImpl> get typeAliases { |
| return _typeAliases; |
| } |
| |
| /// Set the type aliases contained in this compilation unit to [typeAliases]. |
| set typeAliases(List<TypeAliasElementImpl> typeAliases) { |
| for (var typeAlias in typeAliases) { |
| typeAlias.enclosingElement3 = this; |
| typeAlias.enclosingElement = this; |
| } |
| _typeAliases = typeAliases; |
| } |
| |
| @override |
| List<TypeAliasFragment> get typeAliases2 => |
| typeAliases.cast<TypeAliasFragment>(); |
| |
| @override |
| bool operator ==(Object other) => |
| other is CompilationUnitElementImpl && source == other.source; |
| |
| @override |
| T? accept<T>(ElementVisitor<T> visitor) => |
| visitor.visitCompilationUnitElement(this); |
| |
| @override |
| void appendTo(ElementDisplayStringBuilder builder) { |
| builder.writeCompilationUnitElement(this); |
| } |
| |
| @override |
| ClassElement? getClass(String className) { |
| for (var class_ in classes) { |
| if (class_.name == className) { |
| return class_; |
| } |
| } |
| return null; |
| } |
| |
| @override |
| EnumElement? getEnum(String name) { |
| for (var element in enums) { |
| if (element.name == name) { |
| return element; |
| } |
| } |
| return null; |
| } |
| |
| /// Returns the mixin defined in this compilation unit that has the given |
| /// [name], or `null` if this compilation unit does not define a mixin with |
| /// the given name. |
| MixinElement? getMixin(String name) { |
| for (var mixin in mixins) { |
| if (mixin.name == name) { |
| return mixin; |
| } |
| } |
| return null; |
| } |
| |
| void setLinkedData(Reference reference, ElementLinkedData linkedData) { |
| this.reference = reference; |
| reference.element = this; |
| |
| this.linkedData = linkedData; |
| } |
| |
| List<PrefixElementImpl> _buildLibraryImportPrefixes() { |
| var prefixes = <PrefixElementImpl>{}; |
| for (var import in libraryImports) { |
| var prefix = import.prefix?.element; |
| if (prefix != null) { |
| prefixes.add(prefix); |
| } |
| } |
| return prefixes.toFixedList(); |
| } |
| } |
| |
| /// A [FieldElement] for a 'const' or 'final' field that has an initializer. |
| /// |
| // TODO(paulberry): we should rename this class to reflect the fact that it's |
| // used for both const and final fields. However, we shouldn't do so until |
| // we've created an API for reading the values of constants; until that API is |
| // available, clients are likely to read constant values by casting to |
| // ConstFieldElementImpl, so it would be a breaking change to rename this |
| // class. |
| class ConstFieldElementImpl extends FieldElementImpl with ConstVariableElement { |
| /// Initialize a newly created synthetic field element to have the given |
| /// [name] and [offset]. |
| ConstFieldElementImpl(super.name, super.offset); |
| |
| @override |
| ExpressionImpl? get constantInitializer { |
| linkedData?.read(this); |
| return super.constantInitializer; |
| } |
| } |
| |
| /// A [LocalVariableElement] for a local 'const' variable that has an |
| /// initializer. |
| class ConstLocalVariableElementImpl extends LocalVariableElementImpl |
| with ConstVariableElement { |
| /// Initialize a newly created local variable element to have the given [name] |
| /// and [offset]. |
| ConstLocalVariableElementImpl(super.name, super.offset); |
| } |
| |
| /// A concrete implementation of a [ConstructorElement]. |
| class ConstructorElementImpl extends ExecutableElementImpl |
| with AugmentableElement<ConstructorElementImpl>, ConstructorElementMixin |
| implements ConstructorElement { |
| /// The super-constructor which this constructor is invoking, or `null` if |
| /// this constructor is not generative, or is redirecting, or the |
| /// super-constructor is not resolved, or the enclosing class is `Object`. |
| /// |
| // TODO(scheglov): We cannot have both super and redirecting constructors. |
| // So, ideally we should have some kind of "either" or "variant" here. |
| ConstructorElement? _superConstructor; |
| |
| /// The constructor to which this constructor is redirecting. |
| ConstructorElement? _redirectedConstructor; |
| |
| /// The initializers for this constructor (used for evaluating constant |
| /// instance creation expressions). |
| List<ConstructorInitializer> _constantInitializers = const []; |
| |
| @override |
| int? periodOffset; |
| |
| @override |
| int? nameEnd; |
| |
| /// For every constructor we initially set this flag to `true`, and then |
| /// set it to `false` during computing constant values if we detect that it |
| /// is a part of a cycle. |
| bool isCycleFree = true; |
| |
| @override |
| bool isConstantEvaluated = false; |
| |
| /// Initialize a newly created constructor element to have the given [name] |
| /// and [offset]. |
| ConstructorElementImpl(super.name, super.offset); |
| |
| ConstructorElementImpl? get augmentedDeclaration { |
| if (isAugmentation) { |
| return augmentationTarget?.augmentedDeclaration; |
| } else { |
| return this; |
| } |
| } |
| |
| /// Return the constant initializers for this element, which will be empty if |
| /// there are no initializers, or `null` if there was an error in the source. |
| List<ConstructorInitializer> get constantInitializers { |
| linkedData?.read(this); |
| return _constantInitializers; |
| } |
| |
| set constantInitializers(List<ConstructorInitializer> constantInitializers) { |
| _constantInitializers = constantInitializers; |
| } |
| |
| @override |
| ConstructorElement get declaration => this; |
| |
| @override |
| String get displayName { |
| var className = enclosingElement.name; |
| var name = this.name; |
| if (name.isNotEmpty) { |
| return '$className.$name'; |
| } else { |
| return className; |
| } |
| } |
| |
| @override |
| InterfaceElement get enclosingElement => |
| super.enclosingElement as InterfaceElementImpl; |
| |
| @override |
| bool get hasLiteral { |
| if (super.hasLiteral) return true; |
| var enclosingElement = this.enclosingElement; |
| if (enclosingElement is! ExtensionTypeElement) return false; |
| return this == enclosingElement.primaryConstructor && |
| enclosingElement.hasLiteral; |
| } |
| |
| @override |
| bool get isConst { |
| return hasModifier(Modifier.CONST); |
| } |
| |
| /// Set whether this constructor represents a 'const' constructor. |
| set isConst(bool isConst) { |
| setModifier(Modifier.CONST, isConst); |
| } |
| |
| @override |
| bool get isFactory { |
| return hasModifier(Modifier.FACTORY); |
| } |
| |
| /// Set whether this constructor represents a factory method. |
| set isFactory(bool isFactory) { |
| setModifier(Modifier.FACTORY, isFactory); |
| } |
| |
| @override |
| ElementKind get kind => ElementKind.CONSTRUCTOR; |
| |
| @override |
| int get nameLength { |
| var nameEnd = this.nameEnd; |
| if (nameEnd == null) { |
| return 0; |
| } else { |
| return nameEnd - nameOffset; |
| } |
| } |
| |
| @override |
| Element get nonSynthetic { |
| return isSynthetic ? enclosingElement : this; |
| } |
| |
| @override |
| ConstructorElement? get redirectedConstructor { |
| linkedData?.read(this); |
| return _redirectedConstructor; |
| } |
| |
| set redirectedConstructor(ConstructorElement? redirectedConstructor) { |
| _redirectedConstructor = redirectedConstructor; |
| } |
| |
| @override |
| InterfaceType get returnType { |
| var result = _returnType; |
| if (result != null) { |
| return result as InterfaceType; |
| } |
| |
| var augmentedDeclaration = enclosingElement.augmented.declaration; |
| result = augmentedDeclaration.thisType; |
| return _returnType = result as InterfaceType; |
| } |
| |
| @override |
| set returnType(DartType returnType) { |
| assert(false); |
| } |
| |
| @override |
| ConstructorElement? get superConstructor { |
| linkedData?.read(this); |
| return _superConstructor; |
| } |
| |
| set superConstructor(ConstructorElement? superConstructor) { |
| _superConstructor = superConstructor; |
| } |
| |
| @override |
| FunctionType get type { |
| // TODO(scheglov): Remove "element" in the breaking changes branch. |
| return _type ??= FunctionTypeImpl( |
| typeFormals: typeParameters, |
| parameters: parameters, |
| returnType: returnType, |
| nullabilitySuffix: NullabilitySuffix.none, |
| ); |
| } |
| |
| @override |
| set type(FunctionType type) { |
| assert(false); |
| } |
| |
| @override |
| T? accept<T>(ElementVisitor<T> visitor) => |
| visitor.visitConstructorElement(this); |
| |
| @override |
| void appendTo(ElementDisplayStringBuilder builder) { |
| builder.writeConstructorElement(this); |
| } |
| |
| /// Ensures that dependencies of this constructor, such as default values |
| /// of formal parameters, are evaluated. |
| void computeConstantDependencies() { |
| if (!isConstantEvaluated) { |
| computeConstants( |
| declaredVariables: context.declaredVariables, |
| constants: [this], |
| featureSet: library.featureSet, |
| configuration: ConstantEvaluationConfiguration(), |
| ); |
| } |
| } |
| } |
| |
| /// Common implementation for methods defined in [ConstructorElement]. |
| mixin ConstructorElementMixin implements ConstructorElement { |
| @override |
| bool get isDefaultConstructor { |
| // unnamed |
| if (name.isNotEmpty) { |
| return false; |
| } |
| // no required parameters |
| for (ParameterElement parameter in parameters) { |
| if (parameter.isRequired) { |
| return false; |
| } |
| } |
| // OK, can be used as default constructor |
| return true; |
| } |
| |
| @override |
| bool get isGenerative { |
| return !isFactory; |
| } |
| } |
| |
| /// A [TopLevelVariableElement] for a top-level 'const' variable that has an |
| /// initializer. |
| class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl |
| with ConstVariableElement { |
| /// Initialize a newly created synthetic top-level variable element to have |
| /// the given [name] and [offset]. |
| ConstTopLevelVariableElementImpl(super.name, super.offset); |
| |
| @override |
| ExpressionImpl? get constantInitializer { |
| linkedData?.read(this); |
| return super.constantInitializer; |
| } |
| } |
| |
| /// Mixin used by elements that represent constant variables and have |
| /// initializers. |
| /// |
| /// Note that in correct Dart code, all constant variables must have |
| /// initializers. However, analyzer also needs to handle incorrect Dart code, |
| /// in which case there might be some constant variables that lack initializers. |
| /// This interface is only used for constant variables that have initializers. |
| /// |
| /// This class is not intended to be part of the public API for analyzer. |
| mixin ConstVariableElement implements ElementImpl, ConstantEvaluationTarget { |
| /// If this element represents a constant variable, and it has an initializer, |
| /// a copy of the initializer for the constant. Otherwise `null`. |
| /// |
| /// Note that in correct Dart code, all constant variables must have |
| /// initializers. However, analyzer also needs to handle incorrect Dart code, |
| /// in which case there might be some constant variables that lack |
| /// initializers. |
| ExpressionImpl? constantInitializer; |
| |
| Constant? _evaluationResult; |
| |
| Constant? get evaluationResult => _evaluationResult; |
| |
| set evaluationResult(Constant? evaluationResult) { |
| _evaluationResult = evaluationResult; |
| } |
| |
| @override |
| bool get isConstantEvaluated => _evaluationResult != null; |
| |
| /// Return a representation of the value of this variable, forcing the value |
| /// to be computed if it had not previously been computed, or `null` if either |
| /// this variable was not declared with the 'const' modifier or if the value |
| /// of this variable could not be computed because of errors. |
| DartObject? computeConstantValue() { |
| if (evaluationResult == null) { |
| var library = this.library; |
| // TODO(scheglov): https://github.com/dart-lang/sdk/issues/47915 |
| if (library == null) { |
| throw StateError( |
| '[library: null][this: ($runtimeType) $this]' |
| '[enclosingElement: $enclosingElement]' |
| '[reference: $reference]', |
| ); |
| } |
| computeConstants( |
| declaredVariables: context.declaredVariables, |
| constants: [this], |
| featureSet: library.featureSet, |
| configuration: ConstantEvaluationConfiguration(), |
| ); |
| } |
| |
| if (evaluationResult case DartObjectImpl result) { |
| return result; |
| } |
| return null; |
| } |
| } |
| |
| /// A [FieldFormalParameterElementImpl] for parameters that have an initializer. |
| class DefaultFieldFormalParameterElementImpl |
| extends FieldFormalParameterElementImpl with ConstVariableElement { |
| /// Initialize a newly created parameter element to have the given [name] and |
| /// [nameOffset]. |
| DefaultFieldFormalParameterElementImpl({ |
| required super.name, |
| required super.nameOffset, |
| required super.parameterKind, |
| }); |
| |
| @override |
| String? get defaultValueCode { |
| return constantInitializer?.toSource(); |
| } |
| } |
| |
| /// A [ParameterElement] for parameters that have an initializer. |
| class DefaultParameterElementImpl extends ParameterElementImpl |
| with ConstVariableElement { |
| /// Initialize a newly created parameter element to have the given [name] and |
| /// [nameOffset]. |
| DefaultParameterElementImpl({ |
| required super.name, |
| required super.nameOffset, |
| required super.parameterKind, |
| }); |
| |
| @override |
| String? get defaultValueCode { |
| return constantInitializer?.toSource(); |
| } |
| } |
| |
| class DefaultSuperFormalParameterElementImpl |
| extends SuperFormalParameterElementImpl with ConstVariableElement { |
| /// Initialize a newly created parameter element to have the given [name] and |
| /// [nameOffset]. |
| DefaultSuperFormalParameterElementImpl({ |
| required super.name, |
| required super.nameOffset, |
| required super.parameterKind, |
| }); |
| |
| @override |
| String? get defaultValueCode { |
| if (isRequired) { |
| return null; |
| } |
| |
| var constantInitializer = this.constantInitializer; |
| if (constantInitializer != null) { |
| return constantInitializer.toSource(); |
| } |
| |
| if (_superConstructorParameterDefaultValue != null) { |
| return superConstructorParameter?.defaultValueCode; |
| } |
| |
| return null; |
| } |
| |
| @override |
| Constant? get evaluationResult { |
| if (constantInitializer != null) { |
| return super.evaluationResult; |
| } |
| |
| var superConstructorParameter = this.superConstructorParameter?.declaration; |
| if (superConstructorParameter is ParameterElementImpl) { |
| return superConstructorParameter.evaluationResult; |
| } |
| |
| return null; |
| } |
| |
| DartObject? get _superConstructorParameterDefaultValue { |
| var superDefault = superConstructorParameter?.computeConstantValue(); |
| if (superDefault == null) { |
| return null; |
| } |
| |
| var superDefaultType = superDefault.type; |
| if (superDefaultType == null) { |
| return null; |
| } |
| |
| var typeSystem = library?.typeSystem; |
| if (typeSystem == null) { |
| return null; |
| } |
| |
| var requiredType = type.extensionTypeErasure; |
| if (typeSystem.isSubtypeOf(superDefaultType, requiredType)) { |
| return superDefault; |
| } |
| |
| return null; |
| } |
| |
| @override |
| DartObject? computeConstantValue() { |
| if (constantInitializer != null) { |
| return super.computeConstantValue(); |
| } |
| |
| return _superConstructorParameterDefaultValue; |
| } |
| } |
| |
| class DeferredImportElementPrefixImpl extends ImportElementPrefixImpl |
| implements DeferredImportElementPrefix { |
| DeferredImportElementPrefixImpl({ |
| required super.element, |
| }); |
| } |
| |
| class DirectiveUriImpl implements DirectiveUri {} |
| |
| class DirectiveUriWithAugmentationImpl extends DirectiveUriWithSourceImpl |
| implements DirectiveUriWithAugmentation { |
| @override |
| late LibraryAugmentationElementImpl augmentation; |
| |
| DirectiveUriWithAugmentationImpl({ |
| required super.relativeUriString, |
| required super.relativeUri, |
| required super.source, |
| required this.augmentation, |
| }); |
| } |
| |
| class DirectiveUriWithLibraryImpl extends DirectiveUriWithSourceImpl |
| implements DirectiveUriWithLibrary { |
| @override |
| late LibraryElementImpl library; |
| |
| DirectiveUriWithLibraryImpl({ |
| required super.relativeUriString, |
| required super.relativeUri, |
| required super.source, |
| required this.library, |
| }); |
| |
| DirectiveUriWithLibraryImpl.read({ |
| required super.relativeUriString, |
| required super.relativeUri, |
| required super.source, |
| }); |
| } |
| |
| class DirectiveUriWithRelativeUriImpl |
| extends DirectiveUriWithRelativeUriStringImpl |
| implements DirectiveUriWithRelativeUri { |
| @override |
| final Uri relativeUri; |
| |
| DirectiveUriWithRelativeUriImpl({ |
| required super.relativeUriString, |
| required this.relativeUri, |
| }); |
| } |
| |
| class DirectiveUriWithRelativeUriStringImpl extends DirectiveUriImpl |
| implements DirectiveUriWithRelativeUriString { |
| @override |
| final String relativeUriString; |
| |
| DirectiveUriWithRelativeUriStringImpl({ |
| required this.relativeUriString, |
| }); |
| } |
| |
| class DirectiveUriWithSourceImpl extends DirectiveUriWithRelativeUriImpl |
| implements DirectiveUriWithSource { |
| @override |
| final Source source; |
| |
| DirectiveUriWithSourceImpl({ |
| required super.relativeUriString, |
| required super.relativeUri, |
| required this.source, |
| }); |
| } |
| |
| class DirectiveUriWithUnitImpl extends DirectiveUriWithRelativeUriImpl |
| implements DirectiveUriWithUnit { |
| @override |
| final CompilationUnitElementImpl unit; |
| |
| DirectiveUriWithUnitImpl({ |
| required super.relativeUriString, |
| required super.relativeUri, |
| required this.unit, |
| }); |
| |
| @override |
| Source get source => unit.source; |
| } |
| |
| /// The synthetic element representing the declaration of the type `dynamic`. |
| class DynamicElementImpl extends ElementImpl implements TypeDefiningElement { |
| /// Return the unique instance of this class. |
| static DynamicElementImpl get instance => DynamicTypeImpl.instance.element; |
| |
| /// Initialize a newly created instance of this class. Instances of this class |
| /// should <b>not</b> be created except as part of creating the type |
| /// associated with this element. The single instance of this class should be |
| /// accessed through the method [instance]. |
| DynamicElementImpl() : super(Keyword.DYNAMIC.lexeme, -1) { |
| setModifier(Modifier.SYNTHETIC, true); |
| } |
| |
| @override |
| ElementKind get kind => ElementKind.DYNAMIC; |
| |
| @override |
| T? accept<T>(ElementVisitor<T> visitor) => null; |
| } |
| |
| /// A concrete implementation of an [ElementAnnotation]. |
| class ElementAnnotationImpl implements ElementAnnotation { |
| /// The name of the top-level variable used to mark that a function always |
| /// throws, for dead code purposes. |
| static const String _alwaysThrowsVariableName = 'alwaysThrows'; |
| |
| /// The name of the class used to mark an element as being deprecated. |
| static const String _deprecatedClassName = 'Deprecated'; |
| |
| /// The name of the top-level variable used to mark an element as being |
| /// deprecated. |
| static const String _deprecatedVariableName = 'deprecated'; |
| |
| /// The name of the top-level variable used to mark an element as not to be |
| /// stored. |
| static const String _doNotStoreVariableName = 'doNotStore'; |
| |
| /// The name of the top-level variable used to mark a declaration as not to be |
| /// used (for ephemeral testing and debugging only). |
| static const String _doNotSubmitVariableName = 'doNotSubmit'; |
| |
| /// The name of the top-level variable used to mark a method as being a |
| /// factory. |
| static const String _factoryVariableName = 'factory'; |
| |
| /// The name of the top-level variable used to mark a class and its subclasses |
| /// as being immutable. |
| static const String _immutableVariableName = 'immutable'; |
| |
| /// The name of the top-level variable used to mark an element as being |
| /// internal to its package. |
| static const String _internalVariableName = 'internal'; |
| |
| /// The name of the top-level variable used to mark a constructor as being |
| /// literal. |
| static const String _literalVariableName = 'literal'; |
| |
| /// The name of the top-level variable used to mark a returned element as |
| /// requiring use. |
| static const String _mustBeConstVariableName = 'mustBeConst'; |
| |
| /// The name of the top-level variable used to mark a type as having |
| /// "optional" type arguments. |
| static const String _optionalTypeArgsVariableName = 'optionalTypeArgs'; |
| |
| /// The name of the top-level variable used to mark a function as running |
| /// a single test. |
| static const String _isTestVariableName = 'isTest'; |
| |
| /// The name of the top-level variable used to mark a function as running |
| /// a test group. |
| static const String _isTestGroupVariableName = 'isTestGroup'; |
| |
| /// The name of the class used to JS annotate an element. |
| static const String _jsClassName = 'JS'; |
| |
| /// The name of `_js_annotations` library, used to define JS annotations. |
| static const String _jsLibName = '_js_annotations'; |
| |
| /// The name of `meta` library, used to define analysis annotations. |
| static const String _metaLibName = 'meta'; |
| |
| /// The name of `meta_meta` library, used to define annotations for other |
| /// annotations. |
| static const String _metaMetaLibName = 'meta_meta'; |
| |
| /// The name of the top-level variable used to mark a method as requiring |
| /// subclasses to override this method. |
| static const String _mustBeOverridden = 'mustBeOverridden'; |
| |
| /// The name of the top-level variable used to mark a method as requiring |
| /// overriders to call super. |
| static const String _mustCallSuperVariableName = 'mustCallSuper'; |
| |
| /// The name of `angular.meta` library, used to define angular analysis |
| /// annotations. |
| static const String _angularMetaLibName = 'angular.meta'; |
| |
| /// The name of the top-level variable used to mark a member as being nonVirtual. |
| static const String _nonVirtualVariableName = 'nonVirtual'; |
| |
| /// The name of the top-level variable used to mark a method as being expected |
| /// to override an inherited method. |
| static const String _overrideVariableName = 'override'; |
| |
| /// The name of the top-level variable used to mark a method as being |
| /// protected. |
| static const String _protectedVariableName = 'protected'; |
| |
| /// The name of the top-level variable used to mark a member as redeclaring. |
| static const String _redeclareVariableName = 'redeclare'; |
| |
| /// The name of the top-level variable used to mark a class or mixin as being |
| /// reopened. |
| static const String _reopenVariableName = 'reopen'; |
| |
| /// The name of the class used to mark a parameter as being required. |
| static const String _requiredClassName = 'Required'; |
| |
| /// The name of the top-level variable used to mark a parameter as being |
| /// required. |
| static const String _requiredVariableName = 'required'; |
| |
| /// The name of the top-level variable used to mark a class as being sealed. |
| static const String _sealedVariableName = 'sealed'; |
| |
| /// The name of the class used to annotate a class as an annotation with a |
| /// specific set of target element kinds. |
| static const String _targetClassName = 'Target'; |
| |
| /// The name of the class used to mark a returned element as requiring use. |
| static const String _useResultClassName = 'UseResult'; |
| |
| /// The name of the top-level variable used to mark a returned element as |
| /// requiring use. |
| static const String _useResultVariableName = 'useResult'; |
| |
| /// The name of the top-level variable used to mark a member as being visible |
| /// for overriding only. |
| static const String _visibleForOverridingName = 'visibleForOverriding'; |
| |
| /// The name of the top-level variable used to mark a method as being |
| /// visible for templates. |
| static const String _visibleForTemplateVariableName = 'visibleForTemplate'; |
| |
| /// The name of the top-level variable used to mark a method as being |
| /// visible for testing. |
| static const String _visibleForTestingVariableName = 'visibleForTesting'; |
| |
| /// The name of the top-level variable used to mark a method as being |
| /// visible outside of template files. |
| static const String _visibleOutsideTemplateVariableName = |
| 'visibleOutsideTemplate'; |
| |
| @override |
| Element? element; |
| |
| /// The compilation unit in which this annotation appears. |
| CompilationUnitElementImpl compilationUnit; |
| |
| /// The AST of the annotation itself, cloned from the resolved AST for the |
| /// source code. |
| late AnnotationImpl annotationAst; |
| |
| /// The result of evaluating this annotation as a compile-time constant |
| /// expression, or `null` if the compilation unit containing the variable has |
| /// not been resolved. |
| Constant? evaluationResult; |
| |
| /// Any additional errors, other than [evaluationResult] being an |
| /// [InvalidConstant], that came from evaluating the constant expression, |
| /// or `null` if the compilation unit containing the variable has |
| /// not been resolved. |
| /// |
| // TODO(kallentu): Remove this field once we fix up g3's dependency on |
| // annotations having a valid result as well as unresolved errors. |
| List<AnalysisError>? additionalErrors; |
| |
| /// Initialize a newly created annotation. The given [compilationUnit] is the |
| /// compilation unit in which the annotation appears. |
| ElementAnnotationImpl(this.compilationUnit); |
| |
| @override |
| List<AnalysisError> get constantEvaluationErrors { |
| var evaluationResult = this.evaluationResult; |
| var additionalErrors = this.additionalErrors; |
| if (evaluationResult is InvalidConstant) { |
| // When we have an [InvalidConstant], we don't report the additional |
| // errors because this result contains the most relevant error. |
| return [ |
| AnalysisError.tmp( |
| source: source, |
| offset: evaluationResult.offset, |
| length: evaluationResult.length, |
| errorCode: evaluationResult.errorCode, |
| arguments: evaluationResult.arguments, |
| contextMessages: evaluationResult.contextMessages, |
| ) |
| ]; |
| } |
| return additionalErrors ?? const <AnalysisError>[]; |
| } |
| |
| @override |
| AnalysisContext get context => compilationUnit.library.context; |
| |
| @override |
| bool get isAlwaysThrows => _isPackageMetaGetter(_alwaysThrowsVariableName); |
| |
| @override |
| bool get isConstantEvaluated => evaluationResult != null; |
| |
| bool get isDartInternalSince { |
| var element = this.element; |
| if (element is ConstructorElement) { |
| return element.enclosingElement.name == 'Since' && |
| element.library.source.uri.toString() == 'dart:_internal'; |
| } |
| return false; |
| } |
| |
| @override |
| bool get isDeprecated { |
| var element = this.element; |
| if (element is ConstructorElement) { |
| return element.library.isDartCore && |
| element.enclosingElement.name == _deprecatedClassName; |
| } else if (element is PropertyAccessorElement) { |
| return element.library.isDartCore && |
| element.name == _deprecatedVariableName; |
| } |
| return false; |
| } |
| |
| @override |
| bool get isDoNotStore => _isPackageMetaGetter(_doNotStoreVariableName); |
| |
| @override |
| bool get isDoNotSubmit => _isPackageMetaGetter(_doNotSubmitVariableName); |
| |
| @override |
| bool get isFactory => _isPackageMetaGetter(_factoryVariableName); |
| |
| @override |
| bool get isImmutable => _isPackageMetaGetter(_immutableVariableName); |
| |
| @override |
| bool get isInternal => _isPackageMetaGetter(_internalVariableName); |
| |
| @override |
| bool get isIsTest => _isPackageMetaGetter(_isTestVariableName); |
| |
| @override |
| bool get isIsTestGroup => _isPackageMetaGetter(_isTestGroupVariableName); |
| |
| @override |
| bool get isJS => |
| _isConstructor(libraryName: _jsLibName, className: _jsClassName); |
| |
| @override |
| bool get isLiteral => _isPackageMetaGetter(_literalVariableName); |
| |
| @override |
| bool get isMustBeConst => _isPackageMetaGetter(_mustBeConstVariableName); |
| |
| @override |
| bool get isMustBeOverridden => _isPackageMetaGetter(_mustBeOverridden); |
| |
| @override |
| bool get isMustCallSuper => _isPackageMetaGetter(_mustCallSuperVariableName); |
| |
| @override |
| bool get isNonVirtual => _isPackageMetaGetter(_nonVirtualVariableName); |
| |
| @override |
| bool get isOptionalTypeArgs => |
| _isPackageMetaGetter(_optionalTypeArgsVariableName); |
| |
| @override |
| bool get isOverride => _isDartCoreGetter(_overrideVariableName); |
| |
| /// Return `true` if this is an annotation of the form |
| /// `@pragma("vm:entry-point")`. |
| bool get isPragmaVmEntryPoint { |
| if (_isConstructor(libraryName: 'dart.core', className: 'pragma')) { |
| var value = computeConstantValue(); |
| var nameValue = value?.getField('name'); |
| return nameValue?.toStringValue() == 'vm:entry-point'; |
| } |
| return false; |
| } |
| |
| @override |
| bool get isProtected => _isPackageMetaGetter(_protectedVariableName); |
| |
| @override |
| bool get isProxy => false; |
| |
| @override |
| bool get isRedeclare => _isPackageMetaGetter(_redeclareVariableName); |
| |
| @override |
| bool get isReopen => _isPackageMetaGetter(_reopenVariableName); |
| |
| @override |
| bool get isRequired => |
| _isConstructor( |
| libraryName: _metaLibName, className: _requiredClassName) || |
| _isPackageMetaGetter(_requiredVariableName); |
| |
| @override |
| bool get isSealed => _isPackageMetaGetter(_sealedVariableName); |
| |
| @override |
| bool get isTarget => _isConstructor( |
| libraryName: _metaMetaLibName, className: _targetClassName); |
| |
| @override |
| bool get isUseResult => |
| _isConstructor( |
| libraryName: _metaLibName, className: _useResultClassName) || |
| _isPackageMetaGetter(_useResultVariableName); |
| |
| @override |
| bool get isVisibleForOverriding => |
| _isPackageMetaGetter(_visibleForOverridingName); |
| |
| @override |
| bool get isVisibleForTemplate => _isTopGetter( |
| libraryName: _angularMetaLibName, name: _visibleForTemplateVariableName); |
| |
| @override |
| bool get isVisibleForTesting => |
| _isPackageMetaGetter(_visibleForTestingVariableName); |
| |
| @override |
| bool get isVisibleOutsideTemplate => _isTopGetter( |
| libraryName: _angularMetaLibName, |
| name: _visibleOutsideTemplateVariableName); |
| |
| @override |
| LibraryElement get library => compilationUnit.library; |
| |
| /// Get the library containing this annotation. |
| @override |
| Source get librarySource => compilationUnit.librarySource; |
| |
| @override |
| Source get source => compilationUnit.source; |
| |
| @override |
| DartObject? computeConstantValue() { |
| if (evaluationResult == null) { |
| computeConstants( |
| declaredVariables: context.declaredVariables, |
| constants: [this], |
| featureSet: compilationUnit.library.featureSet, |
| configuration: ConstantEvaluationConfiguration(), |
| ); |
| } |
| |
| if (evaluationResult case DartObjectImpl result) { |
| return result; |
| } |
| return null; |
| } |
| |
| @override |
| String toSource() => annotationAst.toSource(); |
| |
| @override |
| String toString() => '@$element'; |
| |
| bool _isConstructor({ |
| required String libraryName, |
| required String className, |
| }) { |
| var element = this.element; |
| return element is ConstructorElement && |
| element.enclosingElement.name == className && |
| element.library.name == libraryName; |
| } |
| |
| bool _isDartCoreGetter(String name) { |
| return _isTopGetter( |
| libraryName: 'dart.core', |
| name: name, |
| ); |
| } |
| |
| bool _isPackageMetaGetter(String name) { |
| return _isTopGetter( |
| libraryName: _metaLibName, |
| name: name, |
| ); |
| } |
| |
| bool _isTopGetter({ |
| required String libraryName, |
| required String name, |
| }) { |
| var element = this.element; |
| return element is PropertyAccessorElement && |
| element.name == name && |
| element.library.name == libraryName; |
| } |
| } |
| |
| /// A base class for concrete implementations of an [Element] or [Element2]. |
| abstract class ElementImpl implements Element, Element2 { |
| static const _metadataFlag_isReady = 1 << 0; |
| static const _metadataFlag_hasDeprecated = 1 << 1; |
| static const _metadataFlag_hasOverride = 1 << 2; |
| |
| /// Cached values for [sinceSdkVersion]. |
| /// |
| /// Only very few elements have `@Since()` annotations, so instead of adding |
| /// an instance field to [ElementImpl], we attach this information this way. |
| /// We ask it only when [Modifier.HAS_SINCE_SDK_VERSION_VALUE] is `true`, so |
| /// don't pay for a hash lookup when we know that the result is `null`. |
| static final Expando<Version> _sinceSdkVersion = Expando<Version>(); |
| |
| static int _NEXT_ID = 0; |
| |
| @override |
| final int id = _NEXT_ID++; |
| |
| /// The enclosing element of this element, or `null` if this element is at the |
| /// root of the element structure. |
| ElementImpl? _enclosingElement; |
| |
| /// The enclosing element of this element, or `null` if this element is at the |
| /// root of the element structure. |
| ElementImpl? _enclosingElement3; |
| |
| Reference? reference; |
| |
| /// The name of this element. |
| String? _name; |
| |
| /// The offset of the name of this element in the file that contains the |
| /// declaration of this element. |
| int _nameOffset = 0; |
| |
| /// The modifiers associated with this element. |
| EnumSet<Modifier> _modifiers = EnumSet.empty(); |
| |
| /// A list containing all of the metadata associated with this element. |
| List<ElementAnnotationImpl> _metadata = const []; |
| |
| /// Cached flags denoting presence of specific annotations in [_metadata]. |
| int _metadataFlags = 0; |
| |
| /// A cached copy of the calculated hashCode for this element. |
| int? _cachedHashCode; |
| |
| /// A cached copy of the calculated location for this element. |
| ElementLocation? _cachedLocation; |
| |
| /// The documentation comment for this element. |
| String? _docComment; |
| |
| /// The offset of the beginning of the element's code in the file that |
| /// contains the element, or `null` if the element is synthetic. |
| int? _codeOffset; |
| |
| /// The length of the element's code, or `null` if the element is synthetic. |
| int? _codeLength; |
| |
| /// Initialize a newly created element to have the given [name] at the given |
| /// [_nameOffset]. |
| ElementImpl(this._name, this._nameOffset, {this.reference}) { |
| reference?.element = this; |
| } |
| |
| @override |
| Element2? get baseElement => this; |
| |
| @override |
| List<Element> get children => const []; |
| |
| @override |
| List<Element2> get children2 => children.cast<Element2>(); |
| |
| /// The length of the element's code, or `null` if the element is synthetic. |
| int? get codeLength => _codeLength; |
| |
| /// The offset of the beginning of the element's code in the file that |
| /// contains the element, or `null` if the element is synthetic. |
| int? get codeOffset => _codeOffset; |
| |
| @override |
| AnalysisContext get context { |
| return _enclosingElement!.context; |
| } |
| |
| @override |
| Element get declaration => this; |
| |
| @override |
| String get displayName => _name ?? ''; |
| |
| @override |
| String? get documentationComment => _docComment; |
| |
| /// The documentation comment source for this element. |
| set documentationComment(String? doc) { |
| _docComment = doc; |
| } |
| |
| @override |
| Element? get enclosingElement => _enclosingElement; |
| |
| /// Set the enclosing element of this element to the given [element]. |
| set enclosingElement(Element? element) { |
| _enclosingElement = element as ElementImpl?; |
| } |
| |
| @override |
| Element2? get enclosingElement2 { |
| var candidate = _enclosingElement; |
| if (candidate is CompilationUnitElementImpl || |
| candidate is AugmentableElement) { |
| throw UnsupportedError('Cannot get an enclosingElement2 for a fragment'); |
| } |
| return candidate as Element2?; |
| } |
| |
| @override |
| Element? get enclosingElement3 => _enclosingElement3; |
| |
| /// Set the enclosing element of this element to the given [element]. |
| set enclosingElement3(Element? element) { |
| _enclosingElement3 = element as ElementImpl?; |
| } |
| |
| /// Return the enclosing unit element (which might be the same as `this`), or |
| /// `null` if this element is not contained in any compilation unit. |
| CompilationUnitElementImpl get enclosingUnit { |
| return _enclosingElement!.enclosingUnit; |
| } |
| |
| @override |
| bool get hasAlwaysThrows { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isAlwaysThrows) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasDeprecated { |
| return (_getMetadataFlags() & _metadataFlag_hasDeprecated) != 0; |
| } |
| |
| @override |
| bool get hasDoNotStore { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isDoNotStore) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasDoNotSubmit { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isDoNotSubmit) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasFactory { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isFactory) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| int get hashCode { |
| // TODO(scheglov): We might want to re-visit this optimization in the future. |
| // We cache the hash code value as this is a very frequently called method. |
| return _cachedHashCode ??= location.hashCode; |
| } |
| |
| @override |
| bool get hasImmutable { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isImmutable) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasInternal { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isInternal) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasIsTest { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isIsTest) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasIsTestGroup { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isIsTestGroup) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasJS { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isJS) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasLiteral { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isLiteral) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasMustBeConst { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isMustBeConst) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasMustBeOverridden { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isMustBeOverridden) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasMustCallSuper { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isMustCallSuper) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasNonVirtual { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isNonVirtual) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasOptionalTypeArgs { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isOptionalTypeArgs) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasOverride { |
| return (_getMetadataFlags() & _metadataFlag_hasOverride) != 0; |
| } |
| |
| /// Return `true` if this element has an annotation of the form |
| /// `@pragma("vm:entry-point")`. |
| bool get hasPragmaVmEntryPoint { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isPragmaVmEntryPoint) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasProtected { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isProtected) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasRedeclare { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isRedeclare) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasReopen { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isReopen) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasRequired { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isRequired) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasSealed { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isSealed) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasUseResult { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isUseResult) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasVisibleForOverriding { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isVisibleForOverriding) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasVisibleForTemplate { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isVisibleForTemplate) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasVisibleForTesting { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isVisibleForTesting) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @override |
| bool get hasVisibleOutsideTemplate { |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isVisibleOutsideTemplate) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /// Return an identifier that uniquely identifies this element among the |
| /// children of this element's parent. |
| String get identifier { |
| var identifier = name!; |
| |
| if (_includeNameOffsetInIdentifier) { |
| identifier += "@$nameOffset"; |
| } |
| |
| return considerCanonicalizeString(identifier); |
| } |
| |
| bool get isNonFunctionTypeAliasesEnabled { |
| return library!.featureSet.isEnabled(Feature.nonfunction_type_aliases); |
| } |
| |
| @override |
| bool get isPrivate { |
| var name = this.name; |
| if (name == null) { |
| return true; |
| } |
| return Identifier.isPrivateName(name); |
| } |
| |
| @override |
| bool get isPublic => !isPrivate; |
| |
| @override |
| bool get isSynthetic { |
| return hasModifier(Modifier.SYNTHETIC); |
| } |
| |
| /// Set whether this element is synthetic. |
| set isSynthetic(bool isSynthetic) { |
| setModifier(Modifier.SYNTHETIC, isSynthetic); |
| } |
| |
| @override |
| LibraryElementImpl? get library => thisOrAncestorOfType(); |
| |
| @override |
| LibraryElement2? get library2 => thisOrAncestorOfType2(); |
| |
| @override |
| Source? get librarySource => library?.source; |
| |
| @override |
| ElementLocation get location { |
| return _cachedLocation ??= ElementLocationImpl.con1(this); |
| } |
| |
| @override |
| List<ElementAnnotationImpl> get metadata { |
| return _metadata; |
| } |
| |
| set metadata(List<ElementAnnotationImpl> metadata) { |
| _metadata = metadata; |
| } |
| |
| @override |
| String? get name => _name; |
| |
| /// Changes the name of this element. |
| set name(String? name) { |
| _name = name; |
| } |
| |
| @override |
| int get nameLength => displayName.length; |
| |
| @override |
| int get nameOffset => _nameOffset; |
| |
| /// Sets the offset of the name of this element in the file that contains the |
| /// declaration of this element. |
| set nameOffset(int offset) { |
| _nameOffset = offset; |
| } |
| |
| @override |
| Element get nonSynthetic => this; |
| |
| @override |
| Element2 get nonSynthetic2 => this; |
| |
| @override |
| AnalysisSession? get session { |
| return enclosingElement?.session; |
| } |
| |
| @override |
| Version? get sinceSdkVersion { |
| if (!hasModifier(Modifier.HAS_SINCE_SDK_VERSION_COMPUTED)) { |
| setModifier(Modifier.HAS_SINCE_SDK_VERSION_COMPUTED, true); |
| var result = SinceSdkVersionComputer().compute(this); |
| if (result != null) { |
| _sinceSdkVersion[this] = result; |
| setModifier(Modifier.HAS_SINCE_SDK_VERSION_VALUE, true); |
| } |
| } |
| if (hasModifier(Modifier.HAS_SINCE_SDK_VERSION_VALUE)) { |
| return _sinceSdkVersion[this]; |
| } |
| return null; |
| } |
| |
| @override |
| Source? get source { |
| return enclosingElement?.source; |
| } |
| |
| /// Whether to include the [nameOffset] in [identifier] to disambiguiate |
| /// elements that might otherwise have the same identifier. |
| bool get _includeNameOffsetInIdentifier { |
| var element = this; |
| if (element is AugmentableElement) { |
| return element.isAugmentation; |
| } |
| return false; |
| } |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| return other is ElementImpl && |
| other.kind == kind && |
| other.location == location; |
| } |
| |
| /// Append a textual representation of this element to the given [builder]. |
| void appendTo(ElementDisplayStringBuilder builder) { |
| builder.writeAbstractElement(this); |
| } |
| |
| @override |
| String displayString2({ |
| bool multiline = false, |
| bool preferTypeAlias = false, |
| }) { |
| var builder = ElementDisplayStringBuilder( |
| multiline: multiline, |
| preferTypeAlias: preferTypeAlias, |
| ); |
| appendTo(builder); |
| return builder.toString(); |
| } |
| |
| /// Set this element as the enclosing element for given [element]. |
| void encloseElement(ElementImpl element) { |
| element.enclosingElement3 = this; |
| element.enclosingElement = this; |
| } |
| |
| /// Set this element as the enclosing element for given [elements]. |
| void encloseElements(List<Element> elements) { |
| for (Element element in elements) { |
| element as ElementImpl; |
| element._enclosingElement3 = this; |
| element._enclosingElement = this; |
| } |
| } |
| |
| @override |
| String getDisplayString({ |
| @Deprecated('Only non-nullable by default mode is supported') |
| bool withNullability = true, |
| bool multiline = false, |
| bool preferTypeAlias = false, |
| }) { |
| var builder = ElementDisplayStringBuilder( |
| multiline: multiline, |
| preferTypeAlias: preferTypeAlias, |
| ); |
| appendTo(builder); |
| return builder.toString(); |
| } |
| |
| @override |
| String getExtendedDisplayName(String? shortName) { |
| shortName ??= displayName; |
| var source = this.source; |
| return "$shortName (${source?.fullName})"; |
| } |
| |
| /// Return `true` if this element has the given [modifier] associated with it. |
| bool hasModifier(Modifier modifier) => _modifiers[modifier]; |
| |
| @override |
| bool isAccessibleIn(LibraryElement library) { |
| if (Identifier.isPrivateName(name!)) { |
| return library == this.library; |
| } |
| return true; |
| } |
| |
| @override |
| bool isAccessibleIn2(LibraryElement2 library) { |
| if (Identifier.isPrivateName(name!)) { |
| return library == library2; |
| } |
| return true; |
| } |
| |
| void resetMetadataFlags() { |
| _metadataFlags = 0; |
| } |
| |
| /// Set the code range for this element. |
| void setCodeRange(int offset, int length) { |
| _codeOffset = offset; |
| _codeLength = length; |
| } |
| |
| /// Set whether the given [modifier] is associated with this element to |
| /// correspond to the given [value]. |
| void setModifier(Modifier modifier, bool value) { |
| _modifiers = _modifiers.updated(modifier, value); |
| } |
| |
| @override |
| E? thisOrAncestorMatching<E extends Element>( |
| bool Function(Element) predicate, |
| ) { |
| Element? element = this; |
| while (element != null && !predicate(element)) { |
| element = element.enclosingElement; |
| } |
| return element as E?; |
| } |
| |
| @override |
| E? thisOrAncestorMatching2<E extends Element2>( |
| bool Function(Element2) predicate, |
| ) { |
| Element2? element = this; |
| while (element != null && !predicate(element)) { |
| element = element.enclosingElement2; |
| } |
| return element as E?; |
| } |
| |
| @override |
| E? thisOrAncestorMatching3<E extends Element>( |
| bool Function(Element) predicate, |
| ) { |
| Element? element = this; |
| while (element != null && !predicate(element)) { |
| element = element.enclosingElement3; |
| } |
| return element as E?; |
| } |
| |
| @override |
| E? thisOrAncestorOfType<E extends Element>() { |
| Element element = this; |
| while (element is! E) { |
| var ancestor = element.enclosingElement; |
| if (ancestor == null) return null; |
| element = ancestor; |
| } |
| return element; |
| } |
| |
| @override |
| E? thisOrAncestorOfType2<E extends Element2>() { |
| Element2 element = this; |
| while (element is! E) { |
| var ancestor = element.enclosingElement2; |
| if (ancestor == null) return null; |
| element = ancestor; |
| } |
| return element; |
| } |
| |
| @override |
| E? thisOrAncestorOfType3<E extends Element>() { |
| Element element = this; |
| while (element is! E) { |
| var ancestor = element.enclosingElement3; |
| if (ancestor == null) return null; |
| element = ancestor; |
| } |
| return element; |
| } |
| |
| @override |
| String toString() { |
| return getDisplayString(); |
| } |
| |
| /// Use the given [visitor] to visit all of the children of this element. |
| /// There is no guarantee of the order in which the children will be visited. |
| @override |
| void visitChildren(ElementVisitor visitor) { |
| for (Element child in children) { |
| child.accept(visitor); |
| } |
| } |
| |
| /// Return flags that denote presence of a few specific annotations. |
| int _getMetadataFlags() { |
| var result = _metadataFlags; |
| |
| // Has at least `_metadataFlag_isReady`. |
| if (result != 0) { |
| return result; |
| } |
| |
| var metadata = this.metadata; |
| for (var i = 0; i < metadata.length; i++) { |
| var annotation = metadata[i]; |
| if (annotation.isDeprecated) { |
| result |= _metadataFlag_hasDeprecated; |
| } else if (annotation.isOverride) { |
| result |= _metadataFlag_hasOverride; |
| } |
| } |
| |
| result |= _metadataFlag_isReady; |
| return _metadataFlags = result; |
| } |
| } |
| |
| /// A concrete implementation of an [ElementLocation]. |
| class ElementLocationImpl implements ElementLocation { |
| /// The character used to separate components in the encoded form. |
| static const int _separatorChar = 0x3B; |
| |
| /// The path to the element whose location is represented by this object. |
| late final List<String> _components; |
| |
| /// Initialize a newly created location to represent the given [element]. |
| ElementLocationImpl.con1(Element element) { |
| List<String> components = <String>[]; |
| Element? ancestor = element; |
| while (ancestor != null) { |
| components.insert(0, (ancestor as ElementImpl).identifier); |
| ancestor = ancestor.enclosingElement; |
| } |
| _components = components.toFixedList(); |
| } |
| |
| /// Initialize a newly created location from the given [encoding]. |
| ElementLocationImpl.con2(String encoding) { |
| _components = _decode(encoding); |
| } |
| |
| /// Initialize a newly created location from the given [components]. |
| ElementLocationImpl.con3(List<String> components) { |
| _components = components; |
| } |
| |
| @override |
| List<String> get components => _components; |
| |
| @override |
| String get encoding { |
| StringBuffer buffer = StringBuffer(); |
| int length = _components.length; |
| for (int i = 0; i < length; i++) { |
| if (i > 0) { |
| buffer.writeCharCode(_separatorChar); |
| } |
| _encode(buffer, _components[i]); |
| } |
| return buffer.toString(); |
| } |
| |
| @override |
| int get hashCode => Object.hashAll(_components); |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other is ElementLocationImpl) { |
| List<String> otherComponents = other._components; |
| int length = _components.length; |
| if (otherComponents.length != length) { |
| return false; |
| } |
| for (int i = 0; i < length; i++) { |
| if (_components[i] != otherComponents[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| @override |
| String toString() => encoding; |
| |
| /// Decode the [encoding] of a location into a list of components and return |
| /// the components. |
| List<String> _decode(String encoding) { |
| List<String> components = <String>[]; |
| StringBuffer buffer = StringBuffer(); |
| int index = 0; |
| int length = encoding.length; |
| while (index < length) { |
| int currentChar = encoding.codeUnitAt(index); |
| if (currentChar == _separatorChar) { |
| if (index + 1 < length && |
| encoding.codeUnitAt(index + 1) == _separatorChar) { |
| buffer.writeCharCode(_separatorChar); |
| index += 2; |
| } else { |
| components.add(buffer.toString()); |
| buffer = StringBuffer(); |
| index++; |
| } |
| } else { |
| buffer.writeCharCode(currentChar); |
| index++; |
| } |
| } |
| components.add(buffer.toString()); |
| return components; |
| } |
| |
| /// Append an encoded form of the given [component] to the given [buffer]. |
| void _encode(StringBuffer buffer, String component) { |
| int length = component.length; |
| for (int i = 0; i < length; i++) { |
| int currentChar = component.codeUnitAt(i); |
| if (currentChar == _separatorChar) { |
| buffer.writeCharCode(_separatorChar); |
| } |
| buffer.writeCharCode(currentChar); |
| } |
| } |
| } |
| |
| /// An [InterfaceElementImpl] which is an enum. |
| class EnumElementImpl extends InterfaceElementImpl |
| with AugmentableElement<EnumElementImpl> |
| implements EnumElement { |
| late MaybeAugmentedEnumElementMixin augmentedInternal = |
| NotAugmentedEnumElementImpl(this); |
| |
| /// 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 |
| MaybeAugmentedEnumElementMixin get augmented { |
| if (isAugmentation) { |
| if (augmentationTarget case var augmentationTarget?) { |
| return augmentationTarget.augmented; |
| } |
| } |
| |
| linkedData?.read(this); |
| return augmentedInternal; |
| } |
| |
| AugmentedEnumElementImpl? get augmentedIfReally { |
| if (augmentationTarget != null) { |
| if (augmented case AugmentedEnumElementImpl augmented) { |
| return augmented; |
| } |
| } |
| return null; |
| } |
| |
| List<FieldElementImpl> get constants { |
| return fields.where((field) => field.isEnumConstant).toList(); |
| } |
| |
| @override |
| ElementKind get kind => ElementKind.ENUM; |
| |
| ConstFieldElementImpl? get valuesField { |
| for (var field in fields) { |
| if (field is ConstFieldElementImpl && |
| field.name == 'values' && |
| field.isSyntheticEnumField) { |
| return field; |
| } |
| } |
| return null; |
| } |
| |
| @override |
| T? accept<T>(ElementVisitor<T> visitor) { |
| return visitor.visitEnumElement(this); |
| } |
| |
| @override |
| void appendTo(ElementDisplayStringBuilder builder) { |
| builder.writeEnumElement(this); |
| } |
| } |
| |
| /// A base class for concrete implementations of an [ExecutableElement]. |
| abstract class ExecutableElementImpl extends _ExistingElementImpl |
| with TypeParameterizedElementMixin, MacroTargetElement |
| implements ExecutableElement { |
| /// A list containing all of the parameters defined by this executable |
| /// element. |
| List<ParameterElement> _parameters = const []; |
| |
| /// The inferred return type of this executable element. |
| DartType? _returnType; |
| |
| /// The type of function defined by this executable element. |
| FunctionType? _type; |
| |
| @override |
| ElementLinkedData? linkedData; |
| |
| /// Initialize a newly created executable element to have the given [name] and |
| /// [offset]. |
| ExecutableElementImpl(String super.name, super.offset, {super.reference}); |
| |
| @override |
| List<Element> get children => [ |
| ...super.children, |
| ...typeParameters, |
| ...parameters, |
| ]; |
| |
| @override |
| Element get enclosingElement => super.enclosingElement!; |
| |
| @override |
| bool get hasImplicitReturnType { |
| return hasModifier(Modifier.IMPLICIT_TYPE); |
| } |
| |
| /// Set whether this executable element has an implicit return type. |
| set hasImplicitReturnType(bool hasImplicitReturnType) { |
| setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType); |
| } |
| |
| bool get invokesSuperSelf { |
| return hasModifier(Modifier.INVOKES_SUPER_SELF); |
| } |
| |
| set invokesSuperSelf(bool value) { |
| setModifier(Modifier.INVOKES_SUPER_SELF, value); |
| } |
| |
| @override |
| bool get isAbstract { |
| return hasModifier(Modifier.ABSTRACT); |
| } |
| |
| @override |
| bool get isAsynchronous { |
| return hasModifier(Modifier.ASYNCHRONOUS); |
| } |
| |
| /// Set whether this executable element's body is asynchronous. |
| set isAsynchronous(bool isAsynchronous) { |
| setModifier(Modifier.ASYNCHRONOUS, isAsynchronous); |
| } |
| |
| @override |
| bool get isExtensionTypeMember { |
| return hasModifier(Modifier.EXTENSION_TYPE_MEMBER); |
| } |
| |
| set isExtensionTypeMember(bool value) { |
| setModifier(Modifier.EXTENSION_TYPE_MEMBER, value); |
| } |
| |
| @override |
| bool get isExternal { |
| return hasModifier(Modifier.EXTERNAL); |
| } |
| |
| /// Set whether this executable element is external. |
| set isExternal(bool isExternal) { |
| setModifier(Modifier.EXTERNAL, isExternal); |
| } |
| |
| @override |
| bool get isGenerator { |
| return hasModifier(Modifier.GENERATOR); |
| } |
| |
| /// Set whether this method's body is a generator. |
| set isGenerator(bool isGenerator) { |
| setModifier(Modifier.GENERATOR, isGenerator); |
| } |
| |
| @override |
| bool get isOperator => false; |
| |
| @override |
| bool get isStatic { |
| return hasModifier(Modifier.STATIC); |
| } |
| |
| set isStatic(bool isStatic) { |
| setModifier(Modifier.STATIC, isStatic); |
| } |
| |
| @override |
| bool get isSynchronous => !isAsynchronous; |
| |
| @override |
| List<ElementAnnotationImpl> get metadata { |
| linkedData?.read(this); |
| return super.metadata; |
| } |
| |
| @override |
| String get name { |
| return super.name!; |
| } |
| |
| @override |
| List<ParameterElement> get parameters { |
| linkedData?.read(this); |
| return _parameters; |
| } |
| |
| /// Set the parameters defined by this executable element to the given |
| /// [parameters]. |
| set parameters(List<ParameterElement> parameters) { |
| for (ParameterElement parameter in parameters) { |
| (parameter as ParameterElementImpl).enclosingElement3 = this; |
| parameter.enclosingElement = this; |
| } |
| _parameters = parameters; |
| } |
| |
| List<ParameterElement> get parameters_unresolved { |
| return _parameters; |
| } |
| |
| @override |
| DartType get returnType { |
| linkedData?.read(this); |
| return _returnType!; |
| } |
| |
| set returnType(DartType returnType) { |
| _returnType = returnType; |
| // We do this because of return type inference. At the moment when we |
| // create a local function element we don't know yet its return type, |
| |