blob: 4713c5c48466f20d23a8b60b616607fabe615c8f [file] [log] [blame]
// 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,