Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: packages/analyzer/lib/src/dart/element/element.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packages/analyzer/lib/src/dart/element/element.dart
diff --git a/packages/analyzer/lib/src/dart/element/element.dart b/packages/analyzer/lib/src/dart/element/element.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6c187856a357f4e632373334880a795e643017b0
--- /dev/null
+++ b/packages/analyzer/lib/src/dart/element/element.dart
@@ -0,0 +1,8461 @@
+// 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.
+
+library analyzer.src.dart.element.element;
+
+import 'dart:collection';
+import 'dart:math' show min;
+
+import 'package:analyzer/dart/ast/ast.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/type.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/dart/element/handle.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/error/codes.dart' show CompileTimeErrorCode;
+import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisContext, AnalysisEngine;
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/task/dart.dart';
+
+/**
+ * A concrete implementation of a [ClassElement].
+ */
+abstract class AbstractClassElementImpl extends ElementImpl
+ implements ClassElement {
+ /**
+ * A list containing all of the accessors (getters and setters) contained in
+ * this class.
+ */
+ List<PropertyAccessorElement> _accessors;
+
+ /**
+ * A list containing all of the fields contained in this class.
+ */
+ List<FieldElement> _fields;
+
+ /**
+ * Initialize a newly created class element to have the given [name] at the
+ * given [offset] in the file that contains the declaration of this element.
+ */
+ AbstractClassElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created class element to have the given [name].
+ */
+ AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ AbstractClassElementImpl.forSerialized(
+ CompilationUnitElementImpl enclosingUnit)
+ : super.forSerialized(enclosingUnit);
+
+ @override
+ List<PropertyAccessorElement> get accessors {
+ return _accessors ?? const <PropertyAccessorElement>[];
+ }
+
+ /**
+ * Set the accessors contained in this class to the given [accessors].
+ */
+ void set accessors(List<PropertyAccessorElement> accessors) {
+ for (PropertyAccessorElement accessor in accessors) {
+ (accessor as PropertyAccessorElementImpl).enclosingElement = this;
+ }
+ this._accessors = accessors;
+ }
+
+ @override
+ String get displayName => name;
+
+ @override
+ List<FieldElement> get fields => _fields ?? const <FieldElement>[];
+
+ /**
+ * Set the fields contained in this class to the given [fields].
+ */
+ void set fields(List<FieldElement> fields) {
+ for (FieldElement field in fields) {
+ (field as FieldElementImpl).enclosingElement = this;
+ }
+ this._fields = fields;
+ }
+
+ @override
+ bool get isEnum;
+
+ @override
+ ElementKind get kind => ElementKind.CLASS;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitClassElement(this);
+
+ @override
+ NamedCompilationUnitMember computeNode() {
+ if (isEnum) {
+ return getNodeMatching((node) => node is EnumDeclaration);
+ } else {
+ return getNodeMatching(
+ (node) => node is ClassDeclaration || node is ClassTypeAlias);
+ }
+ }
+
+ @override
+ ElementImpl getChild(String identifier) {
+ //
+ // The casts in this method are safe because the set methods would have
+ // thrown a CCE if any of the elements in the arrays were not of the
+ // expected types.
+ //
+ for (PropertyAccessorElement accessor in accessors) {
+ PropertyAccessorElementImpl accessorImpl = accessor;
+ if (accessorImpl.identifier == identifier) {
+ return accessorImpl;
+ }
+ }
+ for (FieldElement field in fields) {
+ FieldElementImpl fieldImpl = field;
+ if (fieldImpl.identifier == identifier) {
+ return fieldImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ FieldElement getField(String name) {
+ for (FieldElement fieldElement in fields) {
+ if (name == fieldElement.name) {
+ return fieldElement;
+ }
+ }
+ return null;
+ }
+
+ @override
+ PropertyAccessorElement getGetter(String getterName) {
+ int length = accessors.length;
+ for (int i = 0; i < length; i++) {
+ PropertyAccessorElement accessor = accessors[i];
+ if (accessor.isGetter && accessor.name == getterName) {
+ return accessor;
+ }
+ }
+ return null;
+ }
+
+ @override
+ PropertyAccessorElement getSetter(String setterName) {
+ // TODO (jwren) revisit- should we append '=' here or require clients to
+ // include it?
+ // Do we need the check for isSetter below?
+ if (!StringUtilities.endsWithChar(setterName, 0x3D)) {
+ setterName += '=';
+ }
+ for (PropertyAccessorElement accessor in accessors) {
+ if (accessor.isSetter && accessor.name == setterName) {
+ return accessor;
+ }
+ }
+ return null;
+ }
+
+ @override
+ MethodElement lookUpConcreteMethod(
+ String methodName, LibraryElement library) =>
+ _internalLookUpConcreteMethod(
+ methodName, library, true, new HashSet<ClassElement>());
+
+ @override
+ PropertyAccessorElement lookUpGetter(
+ String getterName, LibraryElement library) =>
+ _internalLookUpGetter(getterName, library, true);
+
+ @override
+ PropertyAccessorElement lookUpInheritedConcreteGetter(
+ String getterName, LibraryElement library) =>
+ _internalLookUpConcreteGetter(getterName, library, false);
+
+ @override
+ MethodElement lookUpInheritedConcreteMethod(
+ String methodName, LibraryElement library) =>
+ _internalLookUpConcreteMethod(
+ methodName, library, false, new HashSet<ClassElement>());
+
+ @override
+ PropertyAccessorElement lookUpInheritedConcreteSetter(
+ String setterName, LibraryElement library) =>
+ _internalLookUpConcreteSetter(setterName, library, false);
+
+ @override
+ MethodElement lookUpInheritedMethod(
+ String methodName, LibraryElement library) =>
+ _internalLookUpMethod(
+ methodName, library, false, new HashSet<ClassElement>());
+
+ @override
+ MethodElement lookUpMethod(String methodName, LibraryElement library) =>
+ _internalLookUpMethod(
+ methodName, library, true, new HashSet<ClassElement>());
+
+ @override
+ PropertyAccessorElement lookUpSetter(
+ String setterName, LibraryElement library) =>
+ _internalLookUpSetter(setterName, library, true);
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(accessors, visitor);
+ safelyVisitChildren(fields, visitor);
+ }
+
+ PropertyAccessorElement _internalLookUpConcreteGetter(
+ String getterName, LibraryElement library, bool includeThisClass) {
+ PropertyAccessorElement getter =
+ _internalLookUpGetter(getterName, library, includeThisClass);
+ while (getter != null && getter.isAbstract) {
+ Element definingClass = getter.enclosingElement;
+ if (definingClass is! ClassElement) {
+ return null;
+ }
+ getter = getImpl(definingClass)
+ ._internalLookUpGetter(getterName, library, false);
+ }
+ return getter;
+ }
+
+ MethodElement _internalLookUpConcreteMethod(
+ String methodName,
+ LibraryElement library,
+ bool includeThisClass,
+ HashSet<ClassElement> visitedClasses) {
+ MethodElement method = _internalLookUpMethod(
+ methodName, library, includeThisClass, visitedClasses);
+ while (method != null && method.isAbstract) {
+ ClassElement definingClass = method.enclosingElement;
+ if (definingClass == null) {
+ return null;
+ }
+ method = getImpl(definingClass)
+ ._internalLookUpMethod(methodName, library, false, visitedClasses);
+ }
+ return method;
+ }
+
+ PropertyAccessorElement _internalLookUpConcreteSetter(
+ String setterName, LibraryElement library, bool includeThisClass) {
+ PropertyAccessorElement setter =
+ _internalLookUpSetter(setterName, library, includeThisClass);
+ while (setter != null && setter.isAbstract) {
+ Element definingClass = setter.enclosingElement;
+ if (definingClass is ClassElementImpl) {
+ setter =
+ definingClass._internalLookUpSetter(setterName, library, false);
+ } else {
+ return null;
+ }
+ }
+ return setter;
+ }
+
+ PropertyAccessorElement _internalLookUpGetter(
+ String getterName, LibraryElement library, bool includeThisClass) {
+ HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
+ ClassElement currentElement = this;
+ if (includeThisClass) {
+ PropertyAccessorElement element = currentElement.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ while (currentElement != null && visitedClasses.add(currentElement)) {
+ for (InterfaceType mixin in currentElement.mixins.reversed) {
+ ClassElement mixinElement = mixin.element;
+ if (mixinElement != null) {
+ PropertyAccessorElement element = mixinElement.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ }
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype == null) {
+ return null;
+ }
+ currentElement = supertype.element;
+ PropertyAccessorElement element = currentElement.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ MethodElement _internalLookUpMethod(String methodName, LibraryElement library,
+ bool includeThisClass, HashSet<ClassElement> visitedClasses) {
+ ClassElement currentElement = this;
+ if (includeThisClass) {
+ MethodElement element = currentElement.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ while (currentElement != null && visitedClasses.add(currentElement)) {
+ for (InterfaceType mixin in currentElement.mixins.reversed) {
+ ClassElement mixinElement = mixin.element;
+ if (mixinElement != null) {
+ MethodElement element = mixinElement.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ }
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype == null) {
+ return null;
+ }
+ currentElement = supertype.element;
+ MethodElement element = currentElement.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ PropertyAccessorElement _internalLookUpSetter(
+ String setterName, LibraryElement library, bool includeThisClass) {
+ HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
+ ClassElement currentElement = this;
+ if (includeThisClass) {
+ PropertyAccessorElement element = currentElement.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ while (currentElement != null && visitedClasses.add(currentElement)) {
+ for (InterfaceType mixin in currentElement.mixins.reversed) {
+ ClassElement mixinElement = mixin.element;
+ if (mixinElement != null) {
+ PropertyAccessorElement element = mixinElement.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ }
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype == null) {
+ return null;
+ }
+ currentElement = supertype.element;
+ PropertyAccessorElement element = currentElement.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the [AbstractClassElementImpl] of the given [classElement]. May
+ * throw an exception if the [AbstractClassElementImpl] cannot be provided
+ * (should not happen though).
+ */
+ static AbstractClassElementImpl getImpl(ClassElement classElement) {
+ if (classElement is ClassElementHandle) {
+ return getImpl(classElement.actualElement);
+ }
+ return classElement as AbstractClassElementImpl;
+ }
+}
+
+/**
+ * For AST nodes that could be in both the getter and setter contexts
+ * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved
+ * elements are stored in the AST node, in an [AuxiliaryElements]. Because
+ * resolved elements are either statically resolved or resolved using propagated
+ * type information, this class is a wrapper for a pair of [ExecutableElement]s,
+ * not just a single [ExecutableElement].
+ */
+class AuxiliaryElements {
+ /**
+ * The element based on propagated type information, or `null` if the AST
+ * structure has not been resolved or if the node could not be resolved.
+ */
+ final ExecutableElement propagatedElement;
+
+ /**
+ * The element based on static type information, or `null` if the AST
+ * structure has not been resolved or if the node could not be resolved.
+ */
+ final ExecutableElement staticElement;
+
+ /**
+ * Initialize a newly created pair to have both the [staticElement] and the
+ * [propagatedElement].
+ */
+ AuxiliaryElements(this.staticElement, this.propagatedElement);
+}
+
+/**
+ * An [AbstractClassElementImpl] which is a class.
+ */
+class ClassElementImpl extends AbstractClassElementImpl
+ with TypeParameterizedElementMixin {
+ /**
+ * The unlinked representation of the class in the summary.
+ */
+ final UnlinkedClass _unlinkedClass;
+
+ /**
+ * A list containing all of the type parameters defined for this class.
+ */
+ List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
+
+ /**
+ * The superclass of the class, or `null` for [Object].
+ */
+ InterfaceType _supertype;
+
+ /**
+ * The type defined by the class.
+ */
+ InterfaceType _type;
+
+ /**
+ * A list containing all of the mixins that are applied to the class being
+ * extended in order to derive the superclass of this class.
+ */
+ List<InterfaceType> _mixins;
+
+ /**
+ * A list containing all of the interfaces that are implemented by this class.
+ */
+ List<InterfaceType> _interfaces;
+
+ /**
+ * For classes which are not mixin applications, a list containing all of the
+ * constructors contained in this class, or `null` if the list of
+ * constructors has not yet been built.
+ *
+ * For classes which are mixin applications, the list of constructors is
+ * computed on the fly by the [constructors] getter, and this field is
+ * `null`.
+ */
+ List<ConstructorElement> _constructors;
+
+ /**
+ * A list containing all of the methods contained in this class.
+ */
+ List<MethodElement> _methods;
+
+ /**
+ * A flag indicating whether the types associated with the instance members of
+ * this class have been inferred.
+ */
+ bool _hasBeenInferred = false;
+
+ /**
+ * The version of this element. The version is changed when the element is
+ * incrementally updated, so that its lists of constructors, accessors and
+ * methods might be different.
+ */
+ int version = 0;
+
+ /**
+ * 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(String name, int offset)
+ : _unlinkedClass = null,
+ super(name, offset);
+
+ /**
+ * Initialize a newly created class element to have the given [name].
+ */
+ ClassElementImpl.forNode(Identifier name)
+ : _unlinkedClass = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ClassElementImpl.forSerialized(
+ this._unlinkedClass, CompilationUnitElementImpl enclosingUnit)
+ : super.forSerialized(enclosingUnit);
+
+ /**
+ * Set whether this class is abstract.
+ */
+ void set abstract(bool isAbstract) {
+ assert(_unlinkedClass == null);
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
+
+ @override
+ List<PropertyAccessorElement> get accessors {
+ if (_unlinkedClass != null && _accessors == null) {
+ _resynthesizeFieldsAndPropertyAccessors();
+ }
+ return _accessors ?? const <PropertyAccessorElement>[];
+ }
+
+ @override
+ void set accessors(List<PropertyAccessorElement> accessors) {
+ assert(_unlinkedClass == null);
+ super.accessors = accessors;
+ }
+
+ @override
+ List<InterfaceType> get allSupertypes {
+ List<InterfaceType> list = new List<InterfaceType>();
+ _collectAllSupertypes(list);
+ return list;
+ }
+
+ @override
+ int get codeLength {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ List<ConstructorElement> get constructors {
+ if (isMixinApplication) {
+ return _computeMixinAppConstructors();
+ }
+ if (_unlinkedClass != null && _constructors == null) {
+ _constructors = _unlinkedClass.executables
+ .where((e) => e.kind == UnlinkedExecutableKind.constructor)
+ .map((e) => new ConstructorElementImpl.forSerialized(e, this))
+ .toList(growable: false);
+ // Ensure at least implicit default constructor.
+ if (_constructors.isEmpty) {
+ ConstructorElementImpl constructor = new ConstructorElementImpl('', -1);
+ constructor.synthetic = true;
+ constructor.enclosingElement = this;
+ _constructors = <ConstructorElement>[constructor];
+ }
+ }
+ assert(_constructors != null);
+ return _constructors ?? const <ConstructorElement>[];
+ }
+
+ /**
+ * Set the constructors contained in this class to the given [constructors].
+ *
+ * Should only be used for class elements that are not mixin applications.
+ */
+ void set constructors(List<ConstructorElement> constructors) {
+ assert(_unlinkedClass == null);
+ assert(!isMixinApplication);
+ for (ConstructorElement constructor in constructors) {
+ (constructor as ConstructorElementImpl).enclosingElement = this;
+ }
+ this._constructors = constructors;
+ }
+
+ @override
+ String get documentationComment {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass?.documentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ /**
+ * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should
+ * be reported for this class.
+ */
+ bool get doesMixinLackConstructors {
+ if (!isMixinApplication && mixins.isEmpty) {
+ // This class is not a mixin application and it doesn't have a "with"
+ // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is
+ // inapplicable.
+ return false;
+ }
+ if (supertype == null) {
+ // Should never happen, since Object is the only class that has no
+ // supertype, and it should have been caught by the test above.
+ assert(false);
+ return false;
+ }
+ // Find the nearest class in the supertype chain that is not a mixin
+ // application.
+ ClassElement nearestNonMixinClass = supertype.element;
+ if (nearestNonMixinClass.isMixinApplication) {
+ // Use a list to keep track of the classes we've seen, so that we won't
+ // go into an infinite loop in the event of a non-trivial loop in the
+ // class hierarchy.
+ List<ClassElement> classesSeen = <ClassElement>[this];
+ while (nearestNonMixinClass.isMixinApplication) {
+ if (classesSeen.contains(nearestNonMixinClass)) {
+ // Loop in the class hierarchy (which is reported elsewhere). Don't
+ // confuse the user with further errors.
+ return false;
+ }
+ classesSeen.add(nearestNonMixinClass);
+ if (nearestNonMixinClass.supertype == null) {
+ // Should never happen, since Object is the only class that has no
+ // supertype, and it is not a mixin application.
+ assert(false);
+ return false;
+ }
+ nearestNonMixinClass = nearestNonMixinClass.supertype.element;
+ }
+ }
+ return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible);
+ }
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
+
+ @override
+ List<FieldElement> get fields {
+ if (_unlinkedClass != null && _fields == null) {
+ _resynthesizeFieldsAndPropertyAccessors();
+ }
+ return _fields ?? const <FieldElement>[];
+ }
+
+ @override
+ void set fields(List<FieldElement> fields) {
+ assert(_unlinkedClass == null);
+ super.fields = fields;
+ }
+
+ bool get hasBeenInferred {
+ if (_unlinkedClass != null) {
+ return context.analysisOptions.strongMode;
+ }
+ return _hasBeenInferred;
+ }
+
+ void set hasBeenInferred(bool hasBeenInferred) {
+ assert(_unlinkedClass == null);
+ _hasBeenInferred = hasBeenInferred;
+ }
+
+ @override
+ bool get hasNonFinalField {
+ List<ClassElement> classesToVisit = new List<ClassElement>();
+ HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
+ classesToVisit.add(this);
+ while (!classesToVisit.isEmpty) {
+ ClassElement currentElement = classesToVisit.removeAt(0);
+ if (visitedClasses.add(currentElement)) {
+ // check fields
+ for (FieldElement field in currentElement.fields) {
+ if (!field.isFinal &&
+ !field.isConst &&
+ !field.isStatic &&
+ !field.isSynthetic) {
+ return true;
+ }
+ }
+ // check mixins
+ for (InterfaceType mixinType in currentElement.mixins) {
+ ClassElement mixinElement = mixinType.element;
+ classesToVisit.add(mixinElement);
+ }
+ // check super
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype != null) {
+ ClassElement superElement = supertype.element;
+ if (superElement != null) {
+ classesToVisit.add(superElement);
+ }
+ }
+ }
+ }
+ // not found
+ return false;
+ }
+
+ /**
+ * Return `true` if the class has a `noSuchMethod()` method distinct from the
+ * one declared in class `Object`, as per the Dart Language Specification
+ * (section 10.4).
+ */
+ bool get hasNoSuchMethod {
+ MethodElement method =
+ lookUpMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME, library);
+ ClassElement definingClass = method?.enclosingElement;
+ return definingClass != null && !definingClass.type.isObject;
+ }
+
+ @override
+ bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER);
+
+ /**
+ * Set whether this class references 'super'.
+ */
+ void set hasReferenceToSuper(bool isReferencedSuper) {
+ setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper);
+ }
+
+ @override
+ bool get hasStaticMember {
+ for (MethodElement method in methods) {
+ if (method.isStatic) {
+ return true;
+ }
+ }
+ for (PropertyAccessorElement accessor in accessors) {
+ if (accessor.isStatic) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ List<InterfaceType> get interfaces {
+ if (_unlinkedClass != null && _interfaces == null) {
+ ResynthesizerContext context = enclosingUnit.resynthesizerContext;
+ _interfaces = _unlinkedClass.interfaces
+ .map((EntityRef t) => context.resolveTypeRef(t, this))
+ .where((DartType type) => type is InterfaceType)
+ .toList(growable: false);
+ }
+ return _interfaces ?? const <InterfaceType>[];
+ }
+
+ void set interfaces(List<InterfaceType> interfaces) {
+ assert(_unlinkedClass == null);
+ _interfaces = interfaces;
+ }
+
+ @override
+ bool get isAbstract {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass.isAbstract;
+ }
+ return hasModifier(Modifier.ABSTRACT);
+ }
+
+ @override
+ bool get isEnum => false;
+
+ @override
+ bool get isMixinApplication {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass.isMixinApplication;
+ }
+ return hasModifier(Modifier.MIXIN_APPLICATION);
+ }
+
+ @override
+ bool get isOrInheritsProxy =>
+ _safeIsOrInheritsProxy(this, new HashSet<ClassElement>());
+
+ @override
+ bool get isProxy {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isProxy) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isValidMixin {
+ if (!context.analysisOptions.enableSuperMixins) {
+ if (hasReferenceToSuper) {
+ return false;
+ }
+ if (!supertype.isObject) {
+ return false;
+ }
+ }
+ for (ConstructorElement constructor in constructors) {
+ if (!constructor.isSynthetic && !constructor.isFactory) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedClass != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedClass.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ List<MethodElement> get methods {
+ if (_unlinkedClass != null) {
+ _methods ??= _unlinkedClass.executables
+ .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
+ .map((e) => new MethodElementImpl.forSerialized(e, this))
+ .toList(growable: false);
+ }
+ return _methods ?? const <MethodElement>[];
+ }
+
+ /**
+ * Set the methods contained in this class to the given [methods].
+ */
+ void set methods(List<MethodElement> methods) {
+ assert(_unlinkedClass == null);
+ for (MethodElement method in methods) {
+ (method as MethodElementImpl).enclosingElement = this;
+ }
+ _methods = methods;
+ }
+
+ /**
+ * Set whether this class is a mixin application.
+ */
+ void set mixinApplication(bool isMixinApplication) {
+ assert(_unlinkedClass == null);
+ setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication);
+ }
+
+ @override
+ List<InterfaceType> get mixins {
+ if (_unlinkedClass != null && _mixins == null) {
+ ResynthesizerContext context = enclosingUnit.resynthesizerContext;
+ _mixins = _unlinkedClass.mixins
+ .map((EntityRef t) => context.resolveTypeRef(t, this))
+ .where((DartType type) => type is InterfaceType)
+ .toList(growable: false);
+ }
+ return _mixins ?? const <InterfaceType>[];
+ }
+
+ void set mixins(List<InterfaceType> mixins) {
+ assert(_unlinkedClass == null);
+ _mixins = mixins;
+ }
+
+ @override
+ String get name {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedClass != null) {
+ return _unlinkedClass.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ InterfaceType get supertype {
+ if (_unlinkedClass != null && _supertype == null) {
+ if (_unlinkedClass.supertype != null) {
+ DartType type = enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_unlinkedClass.supertype, this);
+ if (type is InterfaceType) {
+ _supertype = type;
+ } else {
+ _supertype = context.typeProvider.objectType;
+ }
+ } else if (_unlinkedClass.hasNoSupertype) {
+ return null;
+ } else {
+ _supertype = context.typeProvider.objectType;
+ }
+ }
+ return _supertype;
+ }
+
+ void set supertype(InterfaceType supertype) {
+ assert(_unlinkedClass == null);
+ _supertype = supertype;
+ }
+
+ @override
+ InterfaceType get type {
+ if (_type == null) {
+ InterfaceTypeImpl type = new InterfaceTypeImpl(this);
+ type.typeArguments = typeParameterTypes;
+ _type = type;
+ }
+ return _type;
+ }
+
+ @override
+ TypeParameterizedElementMixin get typeParameterContext => this;
+
+ @override
+ List<TypeParameterElement> get typeParameters {
+ if (_unlinkedClass != null) {
+ return super.typeParameters;
+ }
+ return _typeParameters;
+ }
+
+ /**
+ * Set the type parameters defined for this class to the given
+ * [typeParameters].
+ */
+ void set typeParameters(List<TypeParameterElement> typeParameters) {
+ assert(_unlinkedClass == null);
+ for (TypeParameterElement typeParameter in typeParameters) {
+ (typeParameter as TypeParameterElementImpl).enclosingElement = this;
+ }
+ this._typeParameters = typeParameters;
+ }
+
+ @override
+ List<UnlinkedTypeParam> get unlinkedTypeParams =>
+ _unlinkedClass.typeParameters;
+
+ @override
+ ConstructorElement get unnamedConstructor {
+ for (ConstructorElement element in constructors) {
+ String name = element.displayName;
+ if (name == null || name.isEmpty) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ if (isAbstract) {
+ buffer.write('abstract ');
+ }
+ buffer.write('class ');
+ String name = displayName;
+ if (name == null) {
+ buffer.write("{unnamed class}");
+ } else {
+ buffer.write(name);
+ }
+ int variableCount = typeParameters.length;
+ if (variableCount > 0) {
+ buffer.write("<");
+ for (int i = 0; i < variableCount; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
+ }
+ buffer.write(">");
+ }
+ if (supertype != null && !supertype.isObject) {
+ buffer.write(' extends ');
+ buffer.write(supertype.displayName);
+ }
+ if (mixins.isNotEmpty) {
+ buffer.write(' with ');
+ buffer.write(mixins.map((t) => t.displayName).join(', '));
+ }
+ if (interfaces.isNotEmpty) {
+ buffer.write(' implements ');
+ buffer.write(interfaces.map((t) => t.displayName).join(', '));
+ }
+ }
+
+ @override
+ ElementImpl getChild(String identifier) {
+ ElementImpl child = super.getChild(identifier);
+ if (child != null) {
+ return child;
+ }
+ //
+ // The casts in this method are safe because the set methods would have
+ // thrown a CCE if any of the elements in the arrays were not of the
+ // expected types.
+ //
+ for (ConstructorElement constructor in _constructors) {
+ ConstructorElementImpl constructorImpl = constructor;
+ if (constructorImpl.identifier == identifier) {
+ return constructorImpl;
+ }
+ }
+ for (MethodElement method in methods) {
+ MethodElementImpl methodImpl = method;
+ if (methodImpl.identifier == identifier) {
+ return methodImpl;
+ }
+ }
+ for (TypeParameterElement typeParameter in typeParameters) {
+ TypeParameterElementImpl typeParameterImpl = typeParameter;
+ if (typeParameterImpl.identifier == identifier) {
+ return typeParameterImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ MethodElement getMethod(String methodName) {
+ int length = methods.length;
+ for (int i = 0; i < length; i++) {
+ MethodElement method = methods[i];
+ if (method.name == methodName) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ @override
+ ConstructorElement getNamedConstructor(String name) {
+ for (ConstructorElement element in constructors) {
+ String elementName = element.name;
+ if (elementName != null && elementName == name) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ @override
+ bool isSuperConstructorAccessible(ConstructorElement constructor) {
+ // If this class has no mixins, then all superclass constructors are
+ // accessible.
+ if (mixins.isEmpty) {
+ return true;
+ }
+ // Otherwise only constructors that lack optional parameters are
+ // accessible (see dartbug.com/19576).
+ for (ParameterElement parameter in constructor.parameters) {
+ if (parameter.parameterKind != ParameterKind.REQUIRED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(_constructors, visitor);
+ safelyVisitChildren(methods, visitor);
+ safelyVisitChildren(_typeParameters, visitor);
+ }
+
+ void _collectAllSupertypes(List<InterfaceType> supertypes) {
+ List<InterfaceType> typesToVisit = new List<InterfaceType>();
+ List<ClassElement> visitedClasses = new List<ClassElement>();
+ typesToVisit.add(this.type);
+ while (!typesToVisit.isEmpty) {
+ InterfaceType currentType = typesToVisit.removeAt(0);
+ ClassElement currentElement = currentType.element;
+ if (!visitedClasses.contains(currentElement)) {
+ visitedClasses.add(currentElement);
+ if (!identical(currentType, this.type)) {
+ supertypes.add(currentType);
+ }
+ InterfaceType supertype = currentType.superclass;
+ if (supertype != null) {
+ typesToVisit.add(supertype);
+ }
+ for (InterfaceType type in currentElement.interfaces) {
+ typesToVisit.add(type);
+ }
+ for (InterfaceType type in currentElement.mixins) {
+ ClassElement element = type.element;
+ if (!visitedClasses.contains(element)) {
+ supertypes.add(type);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Compute a list of constructors for this class, which is a mixin
+ * application. If specified, [visitedClasses] is a list of the other mixin
+ * application classes which have been visited on the way to reaching this
+ * one (this is used to detect circularities).
+ */
+ List<ConstructorElement> _computeMixinAppConstructors(
+ [List<ClassElementImpl> visitedClasses = null]) {
+ // First get the list of constructors of the superclass which need to be
+ // forwarded to this class.
+ Iterable<ConstructorElement> constructorsToForward;
+ if (supertype == null) {
+ // Shouldn't ever happen, since the only class with no supertype is
+ // Object, and it isn't a mixin application. But for safety's sake just
+ // assume an empty list.
+ assert(false);
+ constructorsToForward = <ConstructorElement>[];
+ } else if (!supertype.element.isMixinApplication) {
+ List<ConstructorElement> superclassConstructors =
+ supertype.element.constructors;
+ // Filter out any constructors with optional parameters (see
+ // dartbug.com/15101).
+ constructorsToForward =
+ superclassConstructors.where(isSuperConstructorAccessible);
+ } else {
+ if (visitedClasses == null) {
+ visitedClasses = <ClassElementImpl>[this];
+ } else {
+ if (visitedClasses.contains(this)) {
+ // Loop in the class hierarchy. Don't try to forward any
+ // constructors.
+ return <ConstructorElement>[];
+ }
+ visitedClasses.add(this);
+ }
+ try {
+ ClassElementImpl superElement = AbstractClassElementImpl
+ .getImpl(supertype.element) as ClassElementImpl;
+ constructorsToForward =
+ superElement._computeMixinAppConstructors(visitedClasses);
+ } finally {
+ visitedClasses.removeLast();
+ }
+ }
+
+ // Figure out the type parameter substitution we need to perform in order
+ // to produce constructors for this class. We want to be robust in the
+ // face of errors, so drop any extra type arguments and fill in any missing
+ // ones with `dynamic`.
+ List<DartType> parameterTypes =
+ TypeParameterTypeImpl.getTypes(supertype.typeParameters);
+ List<DartType> argumentTypes = new List<DartType>.filled(
+ parameterTypes.length, DynamicTypeImpl.instance);
+ for (int i = 0; i < supertype.typeArguments.length; i++) {
+ if (i >= argumentTypes.length) {
+ break;
+ }
+ argumentTypes[i] = supertype.typeArguments[i];
+ }
+
+ // Now create an implicit constructor for every constructor found above,
+ // substituting type parameters as appropriate.
+ return constructorsToForward
+ .map((ConstructorElement superclassConstructor) {
+ ConstructorElementImpl implicitConstructor =
+ new ConstructorElementImpl(superclassConstructor.name, -1);
+ implicitConstructor.synthetic = true;
+ implicitConstructor.redirectedConstructor = superclassConstructor;
+ List<ParameterElement> superParameters = superclassConstructor.parameters;
+ int count = superParameters.length;
+ if (count > 0) {
+ List<ParameterElement> implicitParameters =
+ new List<ParameterElement>(count);
+ for (int i = 0; i < count; i++) {
+ ParameterElement superParameter = superParameters[i];
+ ParameterElementImpl implicitParameter =
+ new ParameterElementImpl(superParameter.name, -1);
+ implicitParameter.const3 = superParameter.isConst;
+ implicitParameter.final2 = superParameter.isFinal;
+ implicitParameter.parameterKind = superParameter.parameterKind;
+ implicitParameter.synthetic = true;
+ implicitParameter.type =
+ superParameter.type.substitute2(argumentTypes, parameterTypes);
+ implicitParameters[i] = implicitParameter;
+ }
+ implicitConstructor.parameters = implicitParameters;
+ }
+ implicitConstructor.enclosingElement = this;
+ return implicitConstructor;
+ }).toList(growable: false);
+ }
+
+ /**
+ * Resynthesize explicit fields and property accessors and fill [_fields] and
+ * [_accessors] with explicit and implicit elements.
+ */
+ void _resynthesizeFieldsAndPropertyAccessors() {
+ assert(_fields == null);
+ assert(_accessors == null);
+ // Build explicit fields and implicit property accessors.
+ var explicitFields = <FieldElement>[];
+ var implicitAccessors = <PropertyAccessorElement>[];
+ for (UnlinkedVariable v in _unlinkedClass.fields) {
+ FieldElementImpl field =
+ new FieldElementImpl.forSerializedFactory(v, this);
+ explicitFields.add(field);
+ implicitAccessors.add(
+ new PropertyAccessorElementImpl_ImplicitGetter(field)
+ ..enclosingElement = this);
+ if (!field.isConst && !field.isFinal) {
+ implicitAccessors.add(
+ new PropertyAccessorElementImpl_ImplicitSetter(field)
+ ..enclosingElement = this);
+ }
+ }
+ // Build explicit property accessors and implicit fields.
+ var explicitAccessors = <PropertyAccessorElement>[];
+ var implicitFields = <String, FieldElementImpl>{};
+ for (UnlinkedExecutable e in _unlinkedClass.executables) {
+ if (e.kind == UnlinkedExecutableKind.getter ||
+ e.kind == UnlinkedExecutableKind.setter) {
+ PropertyAccessorElementImpl accessor =
+ new PropertyAccessorElementImpl.forSerialized(e, this);
+ explicitAccessors.add(accessor);
+ // Prepare the field type.
+ DartType fieldType;
+ if (e.kind == UnlinkedExecutableKind.getter) {
+ fieldType = accessor.returnType;
+ } else {
+ fieldType = accessor.parameters[0].type;
+ }
+ // Create or update the implicit field.
+ String fieldName = accessor.displayName;
+ FieldElementImpl field = implicitFields[fieldName];
+ if (field == null) {
+ field = new FieldElementImpl(fieldName, -1);
+ implicitFields[fieldName] = field;
+ field.enclosingElement = this;
+ field.synthetic = true;
+ field.final2 = e.kind == UnlinkedExecutableKind.getter;
+ field.type = fieldType;
+ } else {
+ field.final2 = false;
+ }
+ accessor.variable = field;
+ if (e.kind == UnlinkedExecutableKind.getter) {
+ field.getter = accessor;
+ } else {
+ field.setter = accessor;
+ }
+ }
+ }
+ // Combine explicit and implicit fields and property accessors.
+ _fields = <FieldElement>[]
+ ..addAll(explicitFields)
+ ..addAll(implicitFields.values);
+ _accessors = <PropertyAccessorElement>[]
+ ..addAll(explicitAccessors)
+ ..addAll(implicitAccessors);
+ }
+
+ bool _safeIsOrInheritsProxy(
+ ClassElement element, HashSet<ClassElement> visited) {
+ if (visited.contains(element)) {
+ return false;
+ }
+ visited.add(element);
+ if (element.isProxy) {
+ return true;
+ } else if (element.supertype != null &&
+ _safeIsOrInheritsProxy(element.supertype.element, visited)) {
+ return true;
+ }
+ List<InterfaceType> supertypes = element.interfaces;
+ for (int i = 0; i < supertypes.length; i++) {
+ if (_safeIsOrInheritsProxy(supertypes[i].element, visited)) {
+ return true;
+ }
+ }
+ supertypes = element.mixins;
+ for (int i = 0; i < supertypes.length; i++) {
+ if (_safeIsOrInheritsProxy(supertypes[i].element, visited)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+/**
+ * A concrete implementation of a [CompilationUnitElement].
+ */
+class CompilationUnitElementImpl extends UriReferencedElementImpl
+ implements CompilationUnitElement {
+ /**
+ * The context in which this unit is resynthesized, or `null` if the
+ * element is not resynthesized a summary.
+ */
+ final ResynthesizerContext resynthesizerContext;
+
+ /**
+ * The unlinked representation of the unit in the summary.
+ */
+ final UnlinkedUnit _unlinkedUnit;
+
+ /**
+ * The unlinked representation of the part in the summary.
+ */
+ final UnlinkedPart _unlinkedPart;
+
+ /**
+ * The source that corresponds to this compilation unit.
+ */
+ @override
+ Source source;
+
+ /**
+ * The source of the library containing this compilation unit.
+ *
+ * This is the same as the source of the containing [LibraryElement],
+ * except that it does not require the containing [LibraryElement] to be
+ * computed.
+ */
+ Source librarySource;
+
+ /**
+ * A table mapping the offset of a directive to the annotations associated
+ * with that directive, or `null` if none of the annotations in the
+ * compilation unit have annotations.
+ */
+ Map<int, List<ElementAnnotation>> annotationMap = null;
+
+ /**
+ * A list containing all of the top-level accessors (getters and setters)
+ * contained in this compilation unit.
+ */
+ List<PropertyAccessorElement> _accessors;
+
+ /**
+ * A list containing all of the enums contained in this compilation unit.
+ */
+ List<ClassElement> _enums;
+
+ /**
+ * A list containing all of the top-level functions contained in this
+ * compilation unit.
+ */
+ List<FunctionElement> _functions;
+
+ /**
+ * A list containing all of the function type aliases contained in this
+ * compilation unit.
+ */
+ List<FunctionTypeAliasElement> _typeAliases;
+
+ /**
+ * A list containing all of the types contained in this compilation unit.
+ */
+ List<ClassElement> _types;
+
+ /**
+ * A list containing all of the variables contained in this compilation unit.
+ */
+ List<TopLevelVariableElement> _variables;
+
+ /**
+ * A map from offsets to elements of this unit at these offsets.
+ */
+ final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>();
+
+ /**
+ * Resynthesized explicit top-level property accessors.
+ */
+ UnitExplicitTopLevelAccessors _explicitTopLevelAccessors;
+
+ /**
+ * Resynthesized explicit top-level variables.
+ */
+ UnitExplicitTopLevelVariables _explicitTopLevelVariables;
+
+ /**
+ * Description of top-level variable replacements that should be applied
+ * to implicit top-level variables because of re-linking top-level property
+ * accessors between different unit of the same library.
+ */
+ Map<TopLevelVariableElement, TopLevelVariableElement>
+ _topLevelVariableReplaceMap;
+
+ /**
+ * Initialize a newly created compilation unit element to have the given
+ * [name].
+ */
+ CompilationUnitElementImpl(String name)
+ : resynthesizerContext = null,
+ _unlinkedUnit = null,
+ _unlinkedPart = null,
+ super(name, -1);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ CompilationUnitElementImpl.forSerialized(
+ LibraryElementImpl enclosingLibrary,
+ this.resynthesizerContext,
+ this._unlinkedUnit,
+ this._unlinkedPart,
+ String name)
+ : super.forSerialized(null) {
+ _enclosingElement = enclosingLibrary;
+ _name = name;
+ _nameOffset = -1;
+ }
+
+ @override
+ List<PropertyAccessorElement> get accessors {
+ if (_unlinkedUnit != null) {
+ if (_accessors == null) {
+ _explicitTopLevelAccessors ??=
+ resynthesizerContext.buildTopLevelAccessors();
+ _explicitTopLevelVariables ??=
+ resynthesizerContext.buildTopLevelVariables();
+ List<PropertyAccessorElementImpl> accessors =
+ <PropertyAccessorElementImpl>[];
+ accessors.addAll(_explicitTopLevelAccessors.accessors);
+ accessors.addAll(_explicitTopLevelVariables.implicitAccessors);
+ _accessors = accessors;
+ }
+ }
+ return _accessors ?? PropertyAccessorElement.EMPTY_LIST;
+ }
+
+ /**
+ * Set the top-level accessors (getters and setters) contained in this
+ * compilation unit to the given [accessors].
+ */
+ void set accessors(List<PropertyAccessorElement> accessors) {
+ for (PropertyAccessorElement accessor in accessors) {
+ (accessor as PropertyAccessorElementImpl).enclosingElement = this;
+ }
+ this._accessors = accessors;
+ }
+
+ @override
+ int get codeLength {
+ if (_unlinkedUnit != null) {
+ return _unlinkedUnit.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedUnit != null) {
+ return _unlinkedUnit.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ LibraryElement get enclosingElement =>
+ super.enclosingElement as LibraryElement;
+
+ @override
+ CompilationUnitElementImpl get enclosingUnit {
+ return this;
+ }
+
+ @override
+ List<ClassElement> get enums {
+ if (_unlinkedUnit != null) {
+ _enums ??= _unlinkedUnit.enums
+ .map((e) => new EnumElementImpl.forSerialized(e, this))
+ .toList(growable: false);
+ }
+ return _enums ?? const <ClassElement>[];
+ }
+
+ /**
+ * Set the enums contained in this compilation unit to the given [enums].
+ */
+ void set enums(List<ClassElement> enums) {
+ assert(_unlinkedUnit == null);
+ for (ClassElement enumDeclaration in enums) {
+ (enumDeclaration as EnumElementImpl).enclosingElement = this;
+ }
+ this._enums = enums;
+ }
+
+ @override
+ List<FunctionElement> get functions {
+ if (_unlinkedUnit != null) {
+ _functions ??= _unlinkedUnit.executables
+ .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
+ .map((e) => new FunctionElementImpl.forSerialized(e, this))
+ .toList(growable: false);
+ }
+ return _functions ?? const <FunctionElement>[];
+ }
+
+ /**
+ * Set the top-level functions contained in this compilation unit to the given
+ * [functions].
+ */
+ void set functions(List<FunctionElement> functions) {
+ for (FunctionElement function in functions) {
+ (function as FunctionElementImpl).enclosingElement = this;
+ }
+ this._functions = functions;
+ }
+
+ @override
+ List<FunctionTypeAliasElement> get functionTypeAliases {
+ if (_unlinkedUnit != null) {
+ _typeAliases ??= _unlinkedUnit.typedefs
+ .map((t) => new FunctionTypeAliasElementImpl.forSerialized(t, this))
+ .toList(growable: false);
+ }
+ return _typeAliases ?? const <FunctionTypeAliasElement>[];
+ }
+
+ @override
+ int get hashCode => source.hashCode;
+
+ @override
+ bool get hasLoadLibraryFunction {
+ List<FunctionElement> functions = this.functions;
+ for (int i = 0; i < functions.length; i++) {
+ if (functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ String get identifier => source.encoding;
+
+ @override
+ ElementKind get kind => ElementKind.COMPILATION_UNIT;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedPart != null) {
+ return _metadata ??= _buildAnnotations(
+ library.definingCompilationUnit as CompilationUnitElementImpl,
+ _unlinkedPart.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ List<TopLevelVariableElement> get topLevelVariables {
+ if (_unlinkedUnit != null) {
+ if (_variables == null) {
+ _explicitTopLevelAccessors ??=
+ resynthesizerContext.buildTopLevelAccessors();
+ _explicitTopLevelVariables ??=
+ resynthesizerContext.buildTopLevelVariables();
+ List<TopLevelVariableElementImpl> variables =
+ <TopLevelVariableElementImpl>[];
+ variables.addAll(_explicitTopLevelVariables.variables);
+ variables.addAll(_explicitTopLevelAccessors.implicitVariables);
+ // Ensure that getters and setters in different units use
+ // the same top-level variables.
+ (enclosingElement as LibraryElementImpl)
+ .resynthesizerContext
+ .patchTopLevelAccessors();
+ _variables = variables;
+ _topLevelVariableReplaceMap?.forEach((from, to) {
+ int index = _variables.indexOf(from);
+ _variables[index] = to;
+ });
+ _topLevelVariableReplaceMap = null;
+ }
+ }
+ return _variables ?? TopLevelVariableElement.EMPTY_LIST;
+ }
+
+ /**
+ * Set the top-level variables contained in this compilation unit to the given
+ * [variables].
+ */
+ void set topLevelVariables(List<TopLevelVariableElement> variables) {
+ assert(!isResynthesized);
+ for (TopLevelVariableElement field in variables) {
+ (field as TopLevelVariableElementImpl).enclosingElement = this;
+ }
+ this._variables = variables;
+ }
+
+ /**
+ * Set the function type aliases contained in this compilation unit to the
+ * given [typeAliases].
+ */
+ void set typeAliases(List<FunctionTypeAliasElement> typeAliases) {
+ assert(_unlinkedUnit == null);
+ for (FunctionTypeAliasElement typeAlias in typeAliases) {
+ (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this;
+ }
+ this._typeAliases = typeAliases;
+ }
+
+ @override
+ TypeParameterizedElementMixin get typeParameterContext => null;
+
+ @override
+ List<ClassElement> get types {
+ if (_unlinkedUnit != null) {
+ _types ??= _unlinkedUnit.classes
+ .map((c) => new ClassElementImpl.forSerialized(c, this))
+ .toList(growable: false);
+ }
+ return _types ?? const <ClassElement>[];
+ }
+
+ /**
+ * Set the types contained in this compilation unit to the given [types].
+ */
+ void set types(List<ClassElement> types) {
+ assert(_unlinkedUnit == null);
+ for (ClassElement type in types) {
+ // Another implementation of ClassElement is _DeferredClassElement,
+ // which is used to resynthesize classes lazily. We cannot cast it
+ // to ClassElementImpl, and it already can provide correct values of the
+ // 'enclosingElement' property.
+ if (type is ClassElementImpl) {
+ type.enclosingElement = this;
+ }
+ }
+ this._types = types;
+ }
+
+ @override
+ bool operator ==(Object object) =>
+ object is CompilationUnitElementImpl && source == object.source;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this);
+
+ /**
+ * This method is invoked after this unit was incrementally resolved.
+ */
+ void afterIncrementalResolution() {
+ _offsetToElementMap.clear();
+ }
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ if (source == null) {
+ buffer.write("{compilation unit}");
+ } else {
+ buffer.write(source.fullName);
+ }
+ }
+
+ @override
+ CompilationUnit computeNode() => unit;
+
+ /**
+ * Return the annotations associated with the directive at the given [offset],
+ * or an empty list if the directive has no annotations or if there is no
+ * directive at the given offset.
+ */
+ List<ElementAnnotation> getAnnotations(int offset) {
+ if (annotationMap == null) {
+ return const <ElementAnnotation>[];
+ }
+ return annotationMap[offset] ?? const <ElementAnnotation>[];
+ }
+
+ @override
+ ElementImpl getChild(String identifier) {
+ //
+ // The casts in this method are safe because the set methods would have
+ // thrown a CCE if any of the elements in the arrays were not of the
+ // expected types.
+ //
+ for (PropertyAccessorElement accessor in accessors) {
+ PropertyAccessorElementImpl accessorImpl = accessor;
+ if (accessorImpl.identifier == identifier) {
+ return accessorImpl;
+ }
+ }
+ for (TopLevelVariableElement variable in topLevelVariables) {
+ TopLevelVariableElementImpl variableImpl = variable;
+ if (variableImpl.identifier == identifier) {
+ return variableImpl;
+ }
+ }
+ for (FunctionElement function in functions) {
+ FunctionElementImpl functionImpl = function;
+ if (functionImpl.identifier == identifier) {
+ return functionImpl;
+ }
+ }
+ for (FunctionTypeAliasElement typeAlias in functionTypeAliases) {
+ FunctionTypeAliasElementImpl typeAliasImpl = typeAlias;
+ if (typeAliasImpl.identifier == identifier) {
+ return typeAliasImpl;
+ }
+ }
+ for (ClassElement type in types) {
+ ClassElementImpl typeImpl = type;
+ if (typeImpl.name == identifier) {
+ return typeImpl;
+ }
+ }
+ for (ClassElement type in _enums) {
+ EnumElementImpl typeImpl = type;
+ if (typeImpl.identifier == identifier) {
+ return typeImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ Element getElementAt(int offset) {
+ if (_offsetToElementMap.isEmpty) {
+ accept(new _BuildOffsetToElementMap(_offsetToElementMap));
+ }
+ return _offsetToElementMap[offset];
+ }
+
+ @override
+ ClassElement getEnum(String enumName) {
+ for (ClassElement enumDeclaration in _enums) {
+ if (enumDeclaration.name == enumName) {
+ return enumDeclaration;
+ }
+ }
+ return null;
+ }
+
+ @override
+ ClassElement getType(String className) {
+ for (ClassElement type in types) {
+ if (type.name == className) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Replace the given [from] top-level variable with [to] in this compilation unit.
+ */
+ void replaceTopLevelVariable(
+ TopLevelVariableElement from, TopLevelVariableElement to) {
+ if (_unlinkedUnit != null) {
+ // Getters and setter in different units should be patched to use the
+ // same variables before these variables were asked and returned.
+ assert(_variables == null);
+ _topLevelVariableReplaceMap ??=
+ <TopLevelVariableElement, TopLevelVariableElement>{};
+ _topLevelVariableReplaceMap[from] = to;
+ } else {
+ int index = _variables.indexOf(from);
+ _variables[index] = to;
+ }
+ }
+
+ /**
+ * Set the annotations associated with the directive at the given [offset] to
+ * the given list of [annotations].
+ */
+ void setAnnotations(int offset, List<ElementAnnotation> annotations) {
+ annotationMap ??= new HashMap<int, List<ElementAnnotation>>();
+ annotationMap[offset] = annotations;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(accessors, visitor);
+ safelyVisitChildren(_enums, visitor);
+ safelyVisitChildren(functions, visitor);
+ safelyVisitChildren(functionTypeAliases, visitor);
+ safelyVisitChildren(types, visitor);
+ safelyVisitChildren(topLevelVariables, visitor);
+ }
+}
+
+/**
+ * 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(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created field element to have the given [name].
+ */
+ ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ConstFieldElementImpl.forSerialized(
+ UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedVariable, enclosingElement);
+}
+
+/**
+ * A field element representing an enum constant.
+ */
+class ConstFieldElementImpl_EnumValue extends ConstFieldElementImpl_ofEnum {
+ final UnlinkedEnumValue _unlinkedEnumValue;
+ final int _index;
+
+ ConstFieldElementImpl_EnumValue(
+ EnumElementImpl enumElement, this._unlinkedEnumValue, this._index)
+ : super(enumElement);
+
+ @override
+ String get documentationComment {
+ if (_unlinkedEnumValue != null) {
+ return _unlinkedEnumValue?.documentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ @override
+ EvaluationResultImpl get evaluationResult {
+ if (_evaluationResult == null) {
+ Map<String, DartObjectImpl> fieldMap = <String, DartObjectImpl>{
+ name: new DartObjectImpl(
+ context.typeProvider.intType, new IntState(_index))
+ };
+ DartObjectImpl value =
+ new DartObjectImpl(type, new GenericState(fieldMap));
+ _evaluationResult = new EvaluationResultImpl(value);
+ }
+ return _evaluationResult;
+ }
+
+ @override
+ String get name {
+ if (_unlinkedEnumValue != null) {
+ return _unlinkedEnumValue.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedEnumValue != null) {
+ return _unlinkedEnumValue.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ InterfaceType get type => _enum.type;
+}
+
+/**
+ * The synthetic `values` field of an enum.
+ */
+class ConstFieldElementImpl_EnumValues extends ConstFieldElementImpl_ofEnum {
+ ConstFieldElementImpl_EnumValues(EnumElementImpl enumElement)
+ : super(enumElement) {
+ synthetic = true;
+ }
+
+ @override
+ EvaluationResultImpl get evaluationResult {
+ if (_evaluationResult == null) {
+ List<DartObjectImpl> constantValues = <DartObjectImpl>[];
+ for (FieldElement field in _enum.fields) {
+ if (field is ConstFieldElementImpl_EnumValue) {
+ constantValues.add(field.evaluationResult.value);
+ }
+ }
+ _evaluationResult = new EvaluationResultImpl(
+ new DartObjectImpl(type, new ListState(constantValues)));
+ }
+ return _evaluationResult;
+ }
+
+ @override
+ String get name => 'values';
+
+ @override
+ InterfaceType get type {
+ if (_type == null) {
+ InterfaceType listType = context.typeProvider.listType;
+ return _type = listType.instantiate(<DartType>[_enum.type]);
+ }
+ return _type;
+ }
+}
+
+/**
+ * An abstract constant field of an enum.
+ */
+abstract class ConstFieldElementImpl_ofEnum extends ConstFieldElementImpl {
+ final EnumElementImpl _enum;
+
+ ConstFieldElementImpl_ofEnum(this._enum) : super(null, -1) {
+ enclosingElement = _enum;
+ }
+
+ @override
+ void set const3(bool isConst) {
+ assert(false);
+ }
+
+ @override
+ void set evaluationResult(_) {
+ assert(false);
+ }
+
+ @override
+ void set final2(bool isFinal) {
+ assert(false);
+ }
+
+ @override
+ bool get isConst => true;
+
+ @override
+ bool get isStatic => true;
+
+ @override
+ void set static(bool isStatic) {
+ assert(false);
+ }
+
+ void set type(DartType type) {
+ assert(false);
+ }
+}
+
+/**
+ * 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(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created local variable element to have the given [name].
+ */
+ ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ConstLocalVariableElementImpl.forSerialized(UnlinkedVariable unlinkedVariable,
+ ExecutableElementImpl enclosingExecutable)
+ : super.forSerialized(unlinkedVariable, enclosingExecutable);
+}
+
+/**
+ * A concrete implementation of a [ConstructorElement].
+ */
+class ConstructorElementImpl extends ExecutableElementImpl
+ implements ConstructorElement {
+ /**
+ * 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;
+
+ /**
+ * The offset of the `.` before this constructor name or `null` if not named.
+ */
+ int _periodOffset;
+
+ /**
+ * Return the offset of the character immediately following the last character
+ * of this constructor's name, or `null` if not named.
+ */
+ int _nameEnd;
+
+ /**
+ * True if this constructor has been found by constant evaluation to be free
+ * of redirect cycles, and is thus safe to evaluate.
+ */
+ bool _isCycleFree = false;
+
+ /**
+ * Initialize a newly created constructor element to have the given [name] and
+ * [offset].
+ */
+ ConstructorElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created constructor element to have the given [name].
+ */
+ ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ConstructorElementImpl.forSerialized(
+ UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
+ : super.forSerialized(serializedExecutable, enclosingClass);
+
+ /**
+ * Set whether this constructor represents a 'const' constructor.
+ */
+ void set const2(bool isConst) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.CONST, isConst);
+ }
+
+ List<ConstructorInitializer> get constantInitializers {
+ if (serializedExecutable != null && _constantInitializers == null) {
+ _constantInitializers ??= serializedExecutable.constantInitializers
+ .map((i) => _buildConstructorInitializer(i))
+ .toList(growable: false);
+ }
+ return _constantInitializers;
+ }
+
+ void set constantInitializers(
+ List<ConstructorInitializer> constantInitializers) {
+ assert(serializedExecutable == null);
+ _constantInitializers = constantInitializers;
+ }
+
+ @override
+ ClassElementImpl get enclosingElement =>
+ super.enclosingElement as ClassElementImpl;
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext =>
+ super.enclosingElement as ClassElementImpl;
+
+ /**
+ * Set whether this constructor represents a factory method.
+ */
+ void set factory(bool isFactory) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.FACTORY, isFactory);
+ }
+
+ @override
+ bool get isConst {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isConst;
+ }
+ return hasModifier(Modifier.CONST);
+ }
+
+ bool get isCycleFree {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isConst &&
+ !enclosingUnit.resynthesizerContext
+ .isInConstCycle(serializedExecutable.constCycleSlot);
+ }
+ return _isCycleFree;
+ }
+
+ void set isCycleFree(bool isCycleFree) {
+ // This property is updated in ConstantEvaluationEngine even for
+ // resynthesized constructors, so we don't have the usual assert here.
+ _isCycleFree = isCycleFree;
+ }
+
+ @override
+ bool get isDefaultConstructor {
+ // unnamed
+ String name = this.name;
+ if (name != null && name.length != 0) {
+ return false;
+ }
+ // no required parameters
+ for (ParameterElement parameter in parameters) {
+ if (parameter.parameterKind == ParameterKind.REQUIRED) {
+ return false;
+ }
+ }
+ // OK, can be used as default constructor
+ return true;
+ }
+
+ @override
+ bool get isFactory {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isFactory;
+ }
+ return hasModifier(Modifier.FACTORY);
+ }
+
+ @override
+ bool get isStatic => false;
+
+ @override
+ ElementKind get kind => ElementKind.CONSTRUCTOR;
+
+ @override
+ int get nameEnd {
+ if (serializedExecutable != null) {
+ if (serializedExecutable.name.isNotEmpty) {
+ return serializedExecutable.nameEnd;
+ } else {
+ return serializedExecutable.nameOffset + enclosingElement.name.length;
+ }
+ }
+ return _nameEnd;
+ }
+
+ void set nameEnd(int nameEnd) {
+ assert(serializedExecutable == null);
+ _nameEnd = nameEnd;
+ }
+
+ @override
+ int get periodOffset {
+ if (serializedExecutable != null) {
+ if (serializedExecutable.name.isNotEmpty) {
+ return serializedExecutable.periodOffset;
+ }
+ }
+ return _periodOffset;
+ }
+
+ void set periodOffset(int periodOffset) {
+ assert(serializedExecutable == null);
+ _periodOffset = periodOffset;
+ }
+
+ @override
+ ConstructorElement get redirectedConstructor {
+ if (serializedExecutable != null && _redirectedConstructor == null) {
+ if (serializedExecutable.isRedirectedConstructor) {
+ if (serializedExecutable.isFactory) {
+ _redirectedConstructor = enclosingUnit.resynthesizerContext
+ .resolveConstructorRef(
+ enclosingElement, serializedExecutable.redirectedConstructor);
+ } else {
+ _redirectedConstructor = enclosingElement.getNamedConstructor(
+ serializedExecutable.redirectedConstructorName);
+ }
+ } else {
+ return null;
+ }
+ }
+ return _redirectedConstructor;
+ }
+
+ void set redirectedConstructor(ConstructorElement redirectedConstructor) {
+ assert(serializedExecutable == null);
+ _redirectedConstructor = redirectedConstructor;
+ }
+
+ @override
+ DartType get returnType => enclosingElement.type;
+
+ void set returnType(DartType returnType) {
+ assert(false);
+ }
+
+ @override
+ FunctionType get type {
+ return _type ??= new FunctionTypeImpl(this);
+ }
+
+ void set type(FunctionType type) {
+ assert(false);
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ if (enclosingElement == null) {
+ String message;
+ String name = displayName;
+ if (name != null && !name.isEmpty) {
+ message =
+ 'Found constructor element named $name with no enclosing element';
+ } else {
+ message = 'Found unnamed constructor element with no enclosing element';
+ }
+ AnalysisEngine.instance.logger.logError(message);
+ buffer.write('<unknown class>');
+ } else {
+ buffer.write(enclosingElement.displayName);
+ }
+ String name = displayName;
+ if (name != null && !name.isEmpty) {
+ buffer.write(".");
+ buffer.write(name);
+ }
+ super.appendTo(buffer);
+ }
+
+ @override
+ ConstructorDeclaration computeNode() =>
+ getNodeMatching((node) => node is ConstructorDeclaration);
+
+ /**
+ * Resynthesize the AST for the given serialized constructor initializer.
+ */
+ ConstructorInitializer _buildConstructorInitializer(
+ UnlinkedConstructorInitializer serialized) {
+ UnlinkedConstructorInitializerKind kind = serialized.kind;
+ String name = serialized.name;
+ List<Expression> arguments = <Expression>[];
+ {
+ int numArguments = serialized.arguments.length;
+ int numNames = serialized.argumentNames.length;
+ for (int i = 0; i < numArguments; i++) {
+ Expression expression = enclosingUnit.resynthesizerContext
+ .buildExpression(this, serialized.arguments[i]);
+ int nameIndex = numNames + i - numArguments;
+ if (nameIndex >= 0) {
+ expression = AstFactory.namedExpression2(
+ serialized.argumentNames[nameIndex], expression);
+ }
+ arguments.add(expression);
+ }
+ }
+ switch (kind) {
+ case UnlinkedConstructorInitializerKind.field:
+ ConstructorFieldInitializer initializer =
+ AstFactory.constructorFieldInitializer(
+ false,
+ name,
+ enclosingUnit.resynthesizerContext
+ .buildExpression(this, serialized.expression));
+ initializer.fieldName.staticElement = enclosingElement.getField(name);
+ return initializer;
+ case UnlinkedConstructorInitializerKind.superInvocation:
+ SuperConstructorInvocation initializer =
+ AstFactory.superConstructorInvocation2(
+ name.isNotEmpty ? name : null, arguments);
+ ClassElement superElement = enclosingElement.supertype.element;
+ ConstructorElement element = name.isEmpty
+ ? superElement.unnamedConstructor
+ : superElement.getNamedConstructor(name);
+ initializer.staticElement = element;
+ initializer.constructorName?.staticElement = element;
+ return initializer;
+ case UnlinkedConstructorInitializerKind.thisInvocation:
+ RedirectingConstructorInvocation initializer =
+ AstFactory.redirectingConstructorInvocation2(
+ name.isNotEmpty ? name : null, arguments);
+ ConstructorElement element = name.isEmpty
+ ? enclosingElement.unnamedConstructor
+ : enclosingElement.getNamedConstructor(name);
+ initializer.staticElement = element;
+ initializer.constructorName?.staticElement = element;
+ return initializer;
+ }
+ return null;
+ }
+}
+
+/**
+ * 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(String name, int offset)
+ : super(name, offset);
+
+ /**
+ * Initialize a newly created top-level variable element to have the given
+ * [name].
+ */
+ ConstTopLevelVariableElementImpl.forNode(Identifier name)
+ : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ConstTopLevelVariableElementImpl.forSerialized(
+ UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedVariable, enclosingElement);
+}
+
+/**
+ * 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.
+ */
+abstract class 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.
+ */
+ Expression _constantInitializer;
+
+ EvaluationResultImpl _evaluationResult;
+
+ Expression get constantInitializer {
+ if (_constantInitializer == null && _unlinkedConst != null) {
+ _constantInitializer = enclosingUnit.resynthesizerContext
+ .buildExpression(this, _unlinkedConst);
+ }
+ return _constantInitializer;
+ }
+
+ void set constantInitializer(Expression constantInitializer) {
+ assert(_unlinkedConst == null);
+ _constantInitializer = constantInitializer;
+ }
+
+ EvaluationResultImpl get evaluationResult => _evaluationResult;
+
+ void set evaluationResult(EvaluationResultImpl evaluationResult) {
+ _evaluationResult = evaluationResult;
+ }
+
+ /**
+ * If this element is resynthesized from the summary, return the unlinked
+ * initializer, otherwise return `null`.
+ */
+ UnlinkedConst get _unlinkedConst;
+
+ /**
+ * 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) {
+ context?.computeResult(this, CONSTANT_VALUE);
+ }
+ return evaluationResult?.value;
+ }
+}
+
+/**
+ * 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(String name, int nameOffset)
+ : super(name, nameOffset);
+
+ /**
+ * Initialize a newly created parameter element to have the given [name].
+ */
+ DefaultFieldFormalParameterElementImpl.forNode(Identifier name)
+ : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ DefaultFieldFormalParameterElementImpl.forSerialized(
+ UnlinkedParam unlinkedParam, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedParam, enclosingElement);
+}
+
+/**
+ * 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(String name, int nameOffset)
+ : super(name, nameOffset);
+
+ /**
+ * Initialize a newly created parameter element to have the given [name].
+ */
+ DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ DefaultParameterElementImpl.forSerialized(
+ UnlinkedParam unlinkedParam, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedParam, enclosingElement);
+
+ @override
+ DefaultFormalParameter computeNode() =>
+ getNodeMatching((node) => node is DefaultFormalParameter);
+}
+
+/**
+ * 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 as DynamicElementImpl;
+
+ @override
+ DynamicTypeImpl type;
+
+ /**
+ * 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.syntax, -1) {
+ setModifier(Modifier.SYNTHETIC, true);
+ }
+
+ @override
+ ElementKind get kind => ElementKind.DYNAMIC;
+
+ @override
+ accept(ElementVisitor visitor) => null;
+}
+
+/**
+ * A concrete implementation of an [ElementAnnotation].
+ */
+class ElementAnnotationImpl implements ElementAnnotation {
+ /**
+ * The name of the top-level variable used to mark a method parameter as
+ * covariant.
+ */
+ static String _COVARIANT_VARIABLE_NAME = "checked";
+
+ /**
+ * The name of the class used to mark an element as being deprecated.
+ */
+ static String _DEPRECATED_CLASS_NAME = "Deprecated";
+
+ /**
+ * The name of the top-level variable used to mark an element as being
+ * deprecated.
+ */
+ static String _DEPRECATED_VARIABLE_NAME = "deprecated";
+
+ /**
+ * The name of the top-level variable used to mark a method as being a
+ * factory.
+ */
+ static String _FACTORY_VARIABLE_NAME = "factory";
+
+ /**
+ * The name of the class used to JS annotate an element.
+ */
+ static String _JS_CLASS_NAME = "JS";
+
+ /**
+ * The name of `js` library, used to define JS annotations.
+ */
+ static String _JS_LIB_NAME = "js";
+
+ /**
+ * The name of `meta` library, used to define analysis annotations.
+ */
+ static String _META_LIB_NAME = "meta";
+
+ /**
+ * The name of the top-level variable used to mark a method as requiring
+ * overriders to call super.
+ */
+ static String _MUST_CALL_SUPER_VARIABLE_NAME = "mustCallSuper";
+
+ /**
+ * The name of the top-level variable used to mark a method as being expected
+ * to override an inherited method.
+ */
+ static String _OVERRIDE_VARIABLE_NAME = "override";
+
+ /**
+ * The name of the top-level variable used to mark a method as being
+ * protected.
+ */
+ static String _PROTECTED_VARIABLE_NAME = "protected";
+
+ /**
+ * The name of the top-level variable used to mark a class as implementing a
+ * proxy object.
+ */
+ static String PROXY_VARIABLE_NAME = "proxy";
+
+ /**
+ * The name of the class used to mark a parameter as being required.
+ */
+ static String _REQUIRED_CLASS_NAME = "Required";
+
+ /**
+ * The name of the top-level variable used to mark a parameter as being
+ * required.
+ */
+ static String _REQUIRED_VARIABLE_NAME = "required";
+
+ /**
+ * The name of the top-level variable used to mark a member as intended to be
+ * overridden.
+ */
+ static String _VIRTUAL_VARIABLE_NAME = "virtual";
+
+ /**
+ * The element representing the field, variable, or constructor being used as
+ * an annotation.
+ */
+ 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.
+ */
+ Annotation 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.
+ */
+ EvaluationResultImpl evaluationResult;
+
+ /**
+ * Initialize a newly created annotation. The given [compilationUnit] is the
+ * compilation unit in which the annotation appears.
+ */
+ ElementAnnotationImpl(this.compilationUnit);
+
+ @override
+ DartObject get constantValue => evaluationResult?.value;
+
+ @override
+ AnalysisContext get context => compilationUnit.library.context;
+
+ /**
+ * Return `true` if this annotation marks the associated parameter as being
+ * covariant, meaning it is allowed to have a narrower type in an override.
+ */
+ bool get isCovariant =>
+ element is PropertyAccessorElement &&
+ element.name == _COVARIANT_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
+ bool get isDeprecated {
+ if (element?.library?.isDartCore == true) {
+ if (element is ConstructorElement) {
+ return element.enclosingElement.name == _DEPRECATED_CLASS_NAME;
+ } else if (element is PropertyAccessorElement) {
+ return element.name == _DEPRECATED_VARIABLE_NAME;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isFactory =>
+ element is PropertyAccessorElement &&
+ element.name == _FACTORY_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
+ bool get isJS =>
+ element is ConstructorElement &&
+ element.enclosingElement.name == _JS_CLASS_NAME &&
+ element.library?.name == _JS_LIB_NAME;
+
+ @override
+ bool get isMustCallSuper =>
+ element is PropertyAccessorElement &&
+ element.name == _MUST_CALL_SUPER_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
+ bool get isOverride =>
+ element is PropertyAccessorElement &&
+ element.name == _OVERRIDE_VARIABLE_NAME &&
+ element.library?.isDartCore == true;
+
+ @override
+ bool get isProtected =>
+ element is PropertyAccessorElement &&
+ element.name == _PROTECTED_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
+ bool get isProxy =>
+ element is PropertyAccessorElement &&
+ element.name == PROXY_VARIABLE_NAME &&
+ element.library?.isDartCore == true;
+
+ @override
+ bool get isRequired =>
+ element is ConstructorElement &&
+ element.enclosingElement.name == _REQUIRED_CLASS_NAME &&
+ element.library?.name == _META_LIB_NAME ||
+ element is PropertyAccessorElement &&
+ element.name == _REQUIRED_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ /**
+ * Return `true` if this annotation marks the associated member as supporting
+ * overrides.
+ *
+ * This is currently used by fields in Strong Mode, as other members are
+ * already virtual-by-default.
+ */
+ bool get isVirtual =>
+ element is PropertyAccessorElement &&
+ element.name == _VIRTUAL_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ /**
+ * Get the library containing this annotation.
+ */
+ Source get librarySource => compilationUnit.librarySource;
+
+ @override
+ Source get source => compilationUnit.source;
+
+ @override
+ DartObject computeConstantValue() {
+ if (evaluationResult == null) {
+ context?.computeResult(this, CONSTANT_VALUE);
+ }
+ return constantValue;
+ }
+
+ @override
+ String toString() => '@$element';
+}
+
+/**
+ * A base class for concrete implementations of an [Element].
+ */
+abstract class ElementImpl implements Element {
+ /**
+ * An Unicode right arrow.
+ */
+ static final String RIGHT_ARROW = " \u2192 ";
+
+ static int _NEXT_ID = 0;
+
+ 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 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;
+
+ /**
+ * A bit-encoded form of the modifiers associated with this element.
+ */
+ int _modifiers = 0;
+
+ /**
+ * A list containing all of the metadata associated with this element.
+ */
+ List<ElementAnnotation> _metadata;
+
+ /**
+ * 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(String name, this._nameOffset) {
+ this._name = StringUtilities.intern(name);
+ }
+
+ /**
+ * Initialize a newly created element to have the given [name].
+ */
+ ElementImpl.forNode(Identifier name)
+ : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
+
+ /**
+ * Initialize from serialized information.
+ */
+ ElementImpl.forSerialized(this._enclosingElement);
+
+ /**
+ * 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 {
+ if (_enclosingElement == null) {
+ return null;
+ }
+ return _enclosingElement.context;
+ }
+
+ @override
+ String get displayName => _name;
+
+ @override
+ String get documentationComment => _docComment;
+
+ /**
+ * The documentation comment source for this element.
+ */
+ void set documentationComment(String doc) {
+ assert(!isResynthesized);
+ _docComment = doc?.replaceAll('\r\n', '\n');
+ }
+
+ @override
+ Element get enclosingElement => _enclosingElement;
+
+ /**
+ * Set the enclosing element of this element to the given [element].
+ *
+ * Throws [FrozenHashCodeException] if the hashCode can't be changed.
+ */
+ void set enclosingElement(Element element) {
+ _enclosingElement = 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
+ int get hashCode {
+ // TODO: 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.
+ if (_cachedHashCode == null) {
+ _cachedHashCode = location.hashCode;
+ }
+ return _cachedHashCode;
+ }
+
+ /**
+ * Return an identifier that uniquely identifies this element among the
+ * children of this element's parent.
+ */
+ String get identifier => name;
+
+ @override
+ bool get isDeprecated {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isDeprecated) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isFactory {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isFactory) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isJS {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isJS) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isOverride {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isOverride) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isPrivate {
+ String name = displayName;
+ if (name == null) {
+ return true;
+ }
+ return Identifier.isPrivateName(name);
+ }
+
+ @override
+ bool get isProtected {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isProtected) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isPublic => !isPrivate;
+
+ @override
+ bool get isRequired {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isRequired) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return `true` if this element is resynthesized from a summary.
+ */
+ bool get isResynthesized => enclosingUnit?.resynthesizerContext != null;
+
+ @override
+ bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
+
+ @override
+ LibraryElement get library =>
+ getAncestor((element) => element is LibraryElement);
+
+ @override
+ Source get librarySource => library?.source;
+
+ @override
+ ElementLocation get location {
+ if (_cachedLocation == null) {
+ if (library == null) {
+ return new ElementLocationImpl.con1(this);
+ }
+ _cachedLocation = new ElementLocationImpl.con1(this);
+ }
+ return _cachedLocation;
+ }
+
+ List<ElementAnnotation> get metadata {
+ return _metadata ?? const <ElementAnnotation>[];
+ }
+
+ void set metadata(List<ElementAnnotation> metadata) {
+ assert(!isResynthesized);
+ _metadata = metadata;
+ }
+
+ @override
+ String get name => _name;
+
+ /**
+ * Changes the name of this element.
+ *
+ * Throws [FrozenHashCodeException] if the hashCode can't be changed.
+ */
+ void set name(String name) {
+ this._name = name;
+ }
+
+ @override
+ int get nameLength => displayName != null ? displayName.length : 0;
+
+ @override
+ int get nameOffset => _nameOffset;
+
+ /**
+ * Sets the offset of the name of this element in the file that contains the
+ * declaration of this element.
+ *
+ * Throws [FrozenHashCodeException] if the hashCode can't be changed.
+ */
+ void set nameOffset(int offset) {
+ _nameOffset = offset;
+ }
+
+ @override
+ Source get source {
+ if (_enclosingElement == null) {
+ return null;
+ }
+ return _enclosingElement.source;
+ }
+
+ /**
+ * Set whether this element is synthetic.
+ */
+ void set synthetic(bool isSynthetic) {
+ setModifier(Modifier.SYNTHETIC, isSynthetic);
+ }
+
+ /**
+ * Return the context to resolve type parameters in, or `null` if neither this
+ * element nor any of its ancestors is of a kind that can declare type
+ * parameters.
+ */
+ TypeParameterizedElementMixin get typeParameterContext {
+ return _enclosingElement?.typeParameterContext;
+ }
+
+ @override
+ CompilationUnit get unit => context.resolveCompilationUnit(source, library);
+
+ @override
+ bool operator ==(Object object) {
+ if (identical(this, object)) {
+ return true;
+ }
+ return object is Element &&
+ object.kind == kind &&
+ object.location == location;
+ }
+
+ /**
+ * Append to the given [buffer] a comma-separated list of the names of the
+ * types of this element and every enclosing element.
+ */
+ void appendPathTo(StringBuffer buffer) {
+ Element element = this;
+ while (element != null) {
+ if (element != this) {
+ buffer.write(', ');
+ }
+ buffer.write(element.runtimeType);
+ String name = element.name;
+ if (name != null) {
+ buffer.write(' (');
+ buffer.write(name);
+ buffer.write(')');
+ }
+ element = element.enclosingElement;
+ }
+ }
+
+ /**
+ * Append a textual representation of this element to the given [buffer].
+ */
+ void appendTo(StringBuffer buffer) {
+ if (_name == null) {
+ buffer.write("<unnamed ");
+ buffer.write(runtimeType.toString());
+ buffer.write(">");
+ } else {
+ buffer.write(_name);
+ }
+ }
+
+ @override
+ String computeDocumentationComment() => documentationComment;
+
+ @override
+ AstNode computeNode() => getNodeMatching((node) => node is AstNode);
+
+ /**
+ * Set this element as the enclosing element for given [element].
+ */
+ void encloseElement(ElementImpl element) {
+ element.enclosingElement = this;
+ }
+
+ @override
+ Element/*=E*/ getAncestor/*<E extends Element >*/(
+ Predicate<Element> predicate) {
+ Element ancestor = _enclosingElement;
+ while (ancestor != null && !predicate(ancestor)) {
+ ancestor = ancestor.enclosingElement;
+ }
+ return ancestor as Element/*=E*/;
+ }
+
+ /**
+ * Return the child of this element that is uniquely identified by the given
+ * [identifier], or `null` if there is no such child.
+ */
+ ElementImpl getChild(String identifier) => null;
+
+ @override
+ String getExtendedDisplayName(String shortName) {
+ if (shortName == null) {
+ shortName = displayName;
+ }
+ Source source = this.source;
+ if (source != null) {
+ return "$shortName (${source.fullName})";
+ }
+ return shortName;
+ }
+
+ /**
+ * Return the resolved [AstNode] of the given type enclosing [getNameOffset].
+ */
+ AstNode getNodeMatching(Predicate<AstNode> predicate) {
+ CompilationUnit unit = this.unit;
+ if (unit == null) {
+ return null;
+ }
+ int offset = nameOffset;
+ AstNode node = new NodeLocator(offset).searchWithin(unit);
+ if (node == null) {
+ return null;
+ }
+ return node.getAncestor(predicate);
+ }
+
+ /**
+ * Return `true` if this element has the given [modifier] associated with it.
+ */
+ bool hasModifier(Modifier modifier) =>
+ BooleanArray.get(_modifiers, modifier.ordinal);
+
+ @override
+ bool isAccessibleIn(LibraryElement library) {
+ if (Identifier.isPrivateName(name)) {
+ return library == this.library;
+ }
+ return true;
+ }
+
+ /**
+ * Use the given [visitor] to visit all of the [children] in the given array.
+ */
+ void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
+ if (children != null) {
+ for (Element child in children) {
+ child.accept(visitor);
+ }
+ }
+ }
+
+ /**
+ * Set the code range for this element.
+ */
+ void setCodeRange(int offset, int length) {
+ assert(!isResynthesized);
+ _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 = BooleanArray.set(_modifiers, modifier.ordinal, value);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ appendTo(buffer);
+ return buffer.toString();
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ // There are no children to visit
+ }
+
+ /**
+ * Return annotations for the given [unlinkedConsts] in the [unit].
+ */
+ List<ElementAnnotation> _buildAnnotations(
+ CompilationUnitElementImpl unit, List<UnlinkedConst> unlinkedConsts) {
+ int length = unlinkedConsts.length;
+ if (length != 0) {
+ List<ElementAnnotation> annotations = new List<ElementAnnotation>(length);
+ ResynthesizerContext context = unit.resynthesizerContext;
+ for (int i = 0; i < length; i++) {
+ annotations[i] = context.buildAnnotation(this, unlinkedConsts[i]);
+ }
+ return annotations;
+ } else {
+ return const <ElementAnnotation>[];
+ }
+ }
+
+ static int _findElementIndexUsingIdentical(List items, Object item) {
+ int length = items.length;
+ for (int i = 0; i < length; i++) {
+ if (identical(items[i], item)) {
+ return i;
+ }
+ }
+ throw new StateError('Unable to find $item in $items');
+ }
+}
+
+/**
+ * A concrete implementation of an [ElementLocation].
+ */
+class ElementLocationImpl implements ElementLocation {
+ /**
+ * The character used to separate components in the encoded form.
+ */
+ static int _SEPARATOR_CHAR = 0x3B;
+
+ /**
+ * The path to the element whose location is represented by this object.
+ */
+ List<String> _components;
+
+ /**
+ * The object managing [indexKeyId] and [indexLocationId].
+ */
+ Object indexOwner;
+
+ /**
+ * A cached id of this location in index.
+ */
+ int indexKeyId;
+
+ /**
+ * A cached id of this location in index.
+ */
+ int indexLocationId;
+
+ /**
+ * Initialize a newly created location to represent the given [element].
+ */
+ ElementLocationImpl.con1(Element element) {
+ List<String> components = new List<String>();
+ Element ancestor = element;
+ while (ancestor != null) {
+ components.insert(0, (ancestor as ElementImpl).identifier);
+ ancestor = ancestor.enclosingElement;
+ }
+ this._components = components;
+ }
+
+ /**
+ * Initialize a newly created location from the given [encoding].
+ */
+ ElementLocationImpl.con2(String encoding) {
+ this._components = _decode(encoding);
+ }
+
+ /**
+ * Initialize a newly created location from the given [components].
+ */
+ ElementLocationImpl.con3(List<String> components) {
+ this._components = components;
+ }
+
+ @override
+ List<String> get components => _components;
+
+ @override
+ String get encoding {
+ StringBuffer buffer = new StringBuffer();
+ int length = _components.length;
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ buffer.writeCharCode(_SEPARATOR_CHAR);
+ }
+ _encode(buffer, _components[i]);
+ }
+ return buffer.toString();
+ }
+
+ @override
+ int get hashCode {
+ int result = 0;
+ for (int i = 0; i < _components.length; i++) {
+ String component = _components[i];
+ result = JenkinsSmiHash.combine(result, component.hashCode);
+ }
+ return result;
+ }
+
+ @override
+ bool operator ==(Object object) {
+ if (identical(this, object)) {
+ return true;
+ }
+ if (object is ElementLocationImpl) {
+ List<String> otherComponents = object._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 = new List<String>();
+ StringBuffer buffer = new StringBuffer();
+ int index = 0;
+ int length = encoding.length;
+ while (index < length) {
+ int currentChar = encoding.codeUnitAt(index);
+ if (currentChar == _SEPARATOR_CHAR) {
+ if (index + 1 < length &&
+ encoding.codeUnitAt(index + 1) == _SEPARATOR_CHAR) {
+ buffer.writeCharCode(_SEPARATOR_CHAR);
+ index += 2;
+ } else {
+ components.add(buffer.toString());
+ buffer = new 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 == _SEPARATOR_CHAR) {
+ buffer.writeCharCode(_SEPARATOR_CHAR);
+ }
+ buffer.writeCharCode(currentChar);
+ }
+ }
+}
+
+/**
+ * An [AbstractClassElementImpl] which is an enum.
+ */
+class EnumElementImpl extends AbstractClassElementImpl {
+ /**
+ * The unlinked representation of the enum in the summary.
+ */
+ final UnlinkedEnum _unlinkedEnum;
+
+ /**
+ * The type defined by the enum.
+ */
+ InterfaceType _type;
+
+ /**
+ * 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(String name, int offset)
+ : _unlinkedEnum = null,
+ super(name, offset);
+
+ /**
+ * Initialize a newly created class element to have the given [name].
+ */
+ EnumElementImpl.forNode(Identifier name)
+ : _unlinkedEnum = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ EnumElementImpl.forSerialized(
+ this._unlinkedEnum, CompilationUnitElementImpl enclosingUnit)
+ : super.forSerialized(enclosingUnit);
+
+ /**
+ * Set whether this class is abstract.
+ */
+ void set abstract(bool isAbstract) {
+ assert(_unlinkedEnum == null);
+ }
+
+ @override
+ List<PropertyAccessorElement> get accessors {
+ if (_unlinkedEnum != null && _accessors == null) {
+ _resynthesizeFieldsAndPropertyAccessors();
+ }
+ return _accessors ?? const <PropertyAccessorElement>[];
+ }
+
+ @override
+ void set accessors(List<PropertyAccessorElement> accessors) {
+ assert(_unlinkedEnum == null);
+ super.accessors = accessors;
+ }
+
+ @override
+ List<InterfaceType> get allSupertypes => <InterfaceType>[supertype];
+
+ @override
+ int get codeLength {
+ if (_unlinkedEnum != null) {
+ return _unlinkedEnum.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedEnum != null) {
+ return _unlinkedEnum.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ List<ConstructorElement> get constructors {
+ // The equivalent code for enums in the spec shows a single constructor,
+ // but that constructor is not callable (since it is a compile-time error
+ // to subclass, mix-in, implement, or explicitly instantiate an enum).
+ // So we represent this as having no constructors.
+ return const <ConstructorElement>[];
+ }
+
+ @override
+ String get documentationComment {
+ if (_unlinkedEnum != null) {
+ return _unlinkedEnum?.documentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ @override
+ List<FieldElement> get fields {
+ if (_unlinkedEnum != null && _fields == null) {
+ _resynthesizeFieldsAndPropertyAccessors();
+ }
+ return _fields ?? const <FieldElement>[];
+ }
+
+ @override
+ void set fields(List<FieldElement> fields) {
+ assert(_unlinkedEnum == null);
+ super.fields = fields;
+ }
+
+ @override
+ bool get hasNonFinalField => false;
+
+ @override
+ bool get hasReferenceToSuper => false;
+
+ @override
+ bool get hasStaticMember => true;
+
+ @override
+ List<InterfaceType> get interfaces => const <InterfaceType>[];
+
+ @override
+ bool get isAbstract => false;
+
+ @override
+ bool get isEnum => true;
+
+ @override
+ bool get isMixinApplication => false;
+
+ @override
+ bool get isOrInheritsProxy => false;
+
+ @override
+ bool get isProxy => false;
+
+ @override
+ bool get isValidMixin => false;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedEnum != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedEnum.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ List<MethodElement> get methods => const <MethodElement>[];
+
+ @override
+ List<InterfaceType> get mixins => const <InterfaceType>[];
+
+ @override
+ String get name {
+ if (_unlinkedEnum != null) {
+ return _unlinkedEnum.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedEnum != null) {
+ return _unlinkedEnum.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ InterfaceType get supertype => context.typeProvider.objectType;
+
+ @override
+ InterfaceType get type {
+ if (_type == null) {
+ InterfaceTypeImpl type = new InterfaceTypeImpl(this);
+ type.typeArguments = const <DartType>[];
+ _type = type;
+ }
+ return _type;
+ }
+
+ @override
+ List<TypeParameterElement> get typeParameters =>
+ const <TypeParameterElement>[];
+
+ @override
+ ConstructorElement get unnamedConstructor => null;
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write('enum ');
+ String name = displayName;
+ if (name == null) {
+ buffer.write("{unnamed enum}");
+ } else {
+ buffer.write(name);
+ }
+ }
+
+ @override
+ MethodElement getMethod(String name) => null;
+
+ @override
+ ConstructorElement getNamedConstructor(String name) => null;
+
+ @override
+ bool isSuperConstructorAccessible(ConstructorElement constructor) => false;
+
+ void _resynthesizeFieldsAndPropertyAccessors() {
+ List<FieldElementImpl> fields = <FieldElementImpl>[];
+ // Build the 'index' field.
+ fields.add(new FieldElementImpl('index', -1)
+ ..enclosingElement = this
+ ..synthetic = true
+ ..final2 = true
+ ..type = context.typeProvider.intType);
+ // Build the 'values' field.
+ fields.add(new ConstFieldElementImpl_EnumValues(this));
+ // Build fields for all enum constants.
+ for (int i = 0; i < _unlinkedEnum.values.length; i++) {
+ UnlinkedEnumValue unlinkedValue = _unlinkedEnum.values[i];
+ ConstFieldElementImpl_EnumValue field =
+ new ConstFieldElementImpl_EnumValue(this, unlinkedValue, i);
+ fields.add(field);
+ }
+ // done
+ _fields = fields;
+ _accessors = fields
+ .map((FieldElementImpl field) =>
+ new PropertyAccessorElementImpl_ImplicitGetter(field)
+ ..enclosingElement = this)
+ .toList(growable: false);
+ }
+}
+
+/**
+ * A base class for concrete implementations of an [ExecutableElement].
+ */
+abstract class ExecutableElementImpl extends ElementImpl
+ with TypeParameterizedElementMixin
+ implements ExecutableElement {
+ /**
+ * The unlinked representation of the executable in the summary.
+ */
+ final UnlinkedExecutable serializedExecutable;
+
+ /**
+ * A list containing all of the functions defined within this executable
+ * element.
+ */
+ List<FunctionElement> _functions;
+
+ /**
+ * A list containing all of the labels defined within this executable element.
+ */
+ List<LabelElement> _labels;
+
+ /**
+ * A list containing all of the local variables defined within this executable
+ * element.
+ */
+ List<LocalVariableElement> _localVariables;
+
+ /**
+ * A list containing all of the parameters defined by this executable element.
+ */
+ List<ParameterElement> _parameters;
+
+ /**
+ * A list containing all of the type parameters defined for this executable
+ * element.
+ */
+ List<TypeParameterElement> _typeParameters;
+
+ /**
+ * The return type defined by this executable element.
+ */
+ DartType _returnType;
+
+ /**
+ * The type of function defined by this executable element.
+ */
+ FunctionType _type;
+
+ /**
+ * Initialize a newly created executable element to have the given [name] and
+ * [offset].
+ */
+ ExecutableElementImpl(String name, int offset)
+ : serializedExecutable = null,
+ super(name, offset);
+
+ /**
+ * Initialize a newly created executable element to have the given [name].
+ */
+ ExecutableElementImpl.forNode(Identifier name)
+ : serializedExecutable = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ExecutableElementImpl.forSerialized(
+ this.serializedExecutable, ElementImpl enclosingElement)
+ : super.forSerialized(enclosingElement);
+
+ /**
+ * Set whether this executable element's body is asynchronous.
+ */
+ void set asynchronous(bool isAsynchronous) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.ASYNCHRONOUS, isAsynchronous);
+ }
+
+ @override
+ int get codeLength {
+ if (serializedExecutable != null) {
+ return serializedExecutable.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (serializedExecutable != null) {
+ return serializedExecutable.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ String get displayName {
+ if (serializedExecutable != null) {
+ return serializedExecutable.name;
+ }
+ return super.displayName;
+ }
+
+ @override
+ String get documentationComment {
+ if (serializedExecutable != null) {
+ return serializedExecutable?.documentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ /**
+ * Set whether this executable element is external.
+ */
+ void set external(bool isExternal) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.EXTERNAL, isExternal);
+ }
+
+ @override
+ List<FunctionElement> get functions {
+ if (serializedExecutable != null) {
+ _functions ??= FunctionElementImpl.resynthesizeList(
+ this, serializedExecutable.localFunctions);
+ }
+ return _functions ?? const <FunctionElement>[];
+ }
+
+ /**
+ * Set the functions defined within this executable element to the given
+ * [functions].
+ */
+ void set functions(List<FunctionElement> functions) {
+ assert(serializedExecutable == null);
+ for (FunctionElement function in functions) {
+ (function as FunctionElementImpl).enclosingElement = this;
+ }
+ this._functions = functions;
+ }
+
+ /**
+ * Set whether this method's body is a generator.
+ */
+ void set generator(bool isGenerator) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.GENERATOR, isGenerator);
+ }
+
+ @override
+ bool get hasImplicitReturnType {
+ if (serializedExecutable != null) {
+ return serializedExecutable.returnType == null &&
+ serializedExecutable.kind != UnlinkedExecutableKind.constructor;
+ }
+ return hasModifier(Modifier.IMPLICIT_TYPE);
+ }
+
+ /**
+ * Set whether this executable element has an implicit return type.
+ */
+ void set hasImplicitReturnType(bool hasImplicitReturnType) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType);
+ }
+
+ @override
+ bool get isAbstract {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isAbstract;
+ }
+ return hasModifier(Modifier.ABSTRACT);
+ }
+
+ @override
+ bool get isAsynchronous {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isAsynchronous;
+ }
+ return hasModifier(Modifier.ASYNCHRONOUS);
+ }
+
+ @override
+ bool get isExternal {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isExternal;
+ }
+ return hasModifier(Modifier.EXTERNAL);
+ }
+
+ @override
+ bool get isGenerator {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isGenerator;
+ }
+ return hasModifier(Modifier.GENERATOR);
+ }
+
+ @override
+ bool get isOperator => false;
+
+ @override
+ bool get isSynchronous => !isAsynchronous;
+
+ @override
+ List<LabelElement> get labels {
+ if (serializedExecutable != null) {
+ _labels ??= LabelElementImpl.resynthesizeList(
+ this, serializedExecutable.localLabels);
+ }
+ return _labels ?? const <LabelElement>[];
+ }
+
+ /**
+ * Set the labels defined within this executable element to the given
+ * [labels].
+ */
+ void set labels(List<LabelElement> labels) {
+ assert(serializedExecutable == null);
+ for (LabelElement label in labels) {
+ (label as LabelElementImpl).enclosingElement = this;
+ }
+ this._labels = labels;
+ }
+
+ @override
+ List<LocalVariableElement> get localVariables {
+ if (serializedExecutable != null && _localVariables == null) {
+ List<UnlinkedVariable> unlinkedVariables =
+ serializedExecutable.localVariables;
+ int length = unlinkedVariables.length;
+ if (length != 0) {
+ List<LocalVariableElementImpl> localVariables =
+ new List<LocalVariableElementImpl>(length);
+ for (int i = 0; i < length; i++) {
+ localVariables[i] = new LocalVariableElementImpl.forSerializedFactory(
+ unlinkedVariables[i], this);
+ }
+ _localVariables = localVariables;
+ } else {
+ _localVariables = const <LocalVariableElement>[];
+ }
+ }
+ return _localVariables ?? const <LocalVariableElement>[];
+ }
+
+ /**
+ * Set the local variables defined within this executable element to the given
+ * [variables].
+ */
+ void set localVariables(List<LocalVariableElement> variables) {
+ assert(serializedExecutable == null);
+ for (LocalVariableElement variable in variables) {
+ (variable as LocalVariableElementImpl).enclosingElement = this;
+ }
+ this._localVariables = variables;
+ }
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (serializedExecutable != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, serializedExecutable.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ String get name {
+ if (serializedExecutable != null) {
+ return serializedExecutable.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (serializedExecutable != null) {
+ return serializedExecutable.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ List<ParameterElement> get parameters {
+ if (serializedExecutable != null) {
+ _parameters ??= ParameterElementImpl.resynthesizeList(
+ serializedExecutable.parameters, this);
+ }
+ return _parameters ?? const <ParameterElement>[];
+ }
+
+ /**
+ * Set the parameters defined by this executable element to the given
+ * [parameters].
+ */
+ void set parameters(List<ParameterElement> parameters) {
+ assert(serializedExecutable == null);
+ for (ParameterElement parameter in parameters) {
+ (parameter as ParameterElementImpl).enclosingElement = this;
+ }
+ this._parameters = parameters;
+ }
+
+ @override
+ DartType get returnType {
+ if (serializedExecutable != null && _returnType == null) {
+ bool isSetter =
+ serializedExecutable.kind == UnlinkedExecutableKind.setter;
+ _returnType = enclosingUnit.resynthesizerContext.resolveLinkedType(
+ serializedExecutable.inferredReturnTypeSlot,
+ typeParameterContext) ??
+ enclosingUnit.resynthesizerContext.resolveTypeRef(
+ serializedExecutable.returnType, typeParameterContext,
+ defaultVoid: isSetter && context.analysisOptions.strongMode);
+ }
+ return _returnType;
+ }
+
+ void set returnType(DartType returnType) {
+ assert(serializedExecutable == null);
+ _returnType = returnType;
+ }
+
+ @override
+ FunctionType get type {
+ if (serializedExecutable != null) {
+ _type ??= new FunctionTypeImpl.elementWithNameAndArgs(
+ this, null, allEnclosingTypeParameterTypes, false);
+ }
+ return _type;
+ }
+
+ void set type(FunctionType type) {
+ assert(serializedExecutable == null);
+ _type = type;
+ }
+
+ @override
+ TypeParameterizedElementMixin get typeParameterContext => this;
+
+ @override
+ List<TypeParameterElement> get typeParameters {
+ if (serializedExecutable != null) {
+ return super.typeParameters;
+ }
+ return _typeParameters ?? const <TypeParameterElement>[];
+ }
+
+ /**
+ * Set the type parameters defined by this executable element to the given
+ * [typeParameters].
+ */
+ void set typeParameters(List<TypeParameterElement> typeParameters) {
+ assert(serializedExecutable == null);
+ for (TypeParameterElement parameter in typeParameters) {
+ (parameter as TypeParameterElementImpl).enclosingElement = this;
+ }
+ this._typeParameters = typeParameters;
+ }
+
+ @override
+ List<UnlinkedTypeParam> get unlinkedTypeParams =>
+ serializedExecutable.typeParameters;
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ if (this.kind != ElementKind.GETTER) {
+ int typeParameterCount = typeParameters.length;
+ if (typeParameterCount > 0) {
+ buffer.write('<');
+ for (int i = 0; i < typeParameterCount; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
+ }
+ buffer.write('>');
+ }
+ buffer.write("(");
+ String closing = null;
+ ParameterKind kind = ParameterKind.REQUIRED;
+ int parameterCount = parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ ParameterElement parameter = parameters[i];
+ ParameterKind parameterKind = parameter.parameterKind;
+ if (parameterKind != kind) {
+ if (closing != null) {
+ buffer.write(closing);
+ }
+ if (parameterKind == ParameterKind.POSITIONAL) {
+ buffer.write("[");
+ closing = "]";
+ } else if (parameterKind == ParameterKind.NAMED) {
+ buffer.write("{");
+ closing = "}";
+ } else {
+ closing = null;
+ }
+ }
+ kind = parameterKind;
+ parameter.appendToWithoutDelimiters(buffer);
+ }
+ if (closing != null) {
+ buffer.write(closing);
+ }
+ buffer.write(")");
+ }
+ if (type != null) {
+ buffer.write(ElementImpl.RIGHT_ARROW);
+ buffer.write(type.returnType);
+ }
+ }
+
+ @override
+ ElementImpl getChild(String identifier) {
+ for (FunctionElement function in _functions) {
+ FunctionElementImpl functionImpl = function;
+ if (functionImpl.identifier == identifier) {
+ return functionImpl;
+ }
+ }
+ for (LabelElement label in _labels) {
+ LabelElementImpl labelImpl = label;
+ if (labelImpl.identifier == identifier) {
+ return labelImpl;
+ }
+ }
+ for (LocalVariableElement variable in _localVariables) {
+ LocalVariableElementImpl variableImpl = variable;
+ if (variableImpl.identifier == identifier) {
+ return variableImpl;
+ }
+ }
+ for (ParameterElement parameter in parameters) {
+ ParameterElementImpl parameterImpl = parameter;
+ if (parameterImpl.identifier == identifier) {
+ return parameterImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(typeParameters, visitor);
+ safelyVisitChildren(parameters, visitor);
+ safelyVisitChildren(_functions, visitor);
+ safelyVisitChildren(_labels, visitor);
+ safelyVisitChildren(_localVariables, visitor);
+ }
+}
+
+/**
+ * A concrete implementation of an [ExportElement].
+ */
+class ExportElementImpl extends UriReferencedElementImpl
+ implements ExportElement {
+ /**
+ * The unlinked representation of the export in the summary.
+ */
+ final UnlinkedExportPublic _unlinkedExportPublic;
+
+ /**
+ * The unlinked representation of the export in the summary.
+ */
+ final UnlinkedExportNonPublic _unlinkedExportNonPublic;
+
+ /**
+ * The library that is exported from this library by this export directive.
+ */
+ LibraryElement _exportedLibrary;
+
+ /**
+ * The combinators that were specified as part of the export directive in the
+ * order in which they were specified.
+ */
+ List<NamespaceCombinator> _combinators;
+
+ /**
+ * The URI that was selected based on the [context] declared variables.
+ */
+ String _selectedUri;
+
+ /**
+ * Initialize a newly created export element at the given [offset].
+ */
+ ExportElementImpl(int offset)
+ : _unlinkedExportPublic = null,
+ _unlinkedExportNonPublic = null,
+ super(null, offset);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ExportElementImpl.forSerialized(this._unlinkedExportPublic,
+ this._unlinkedExportNonPublic, LibraryElementImpl enclosingLibrary)
+ : super.forSerialized(enclosingLibrary);
+
+ @override
+ List<NamespaceCombinator> get combinators {
+ if (_unlinkedExportPublic != null && _combinators == null) {
+ _combinators = ImportElementImpl
+ ._buildCombinators(_unlinkedExportPublic.combinators);
+ }
+ return _combinators ?? const <NamespaceCombinator>[];
+ }
+
+ void set combinators(List<NamespaceCombinator> combinators) {
+ assert(_unlinkedExportPublic == null);
+ _combinators = combinators;
+ }
+
+ @override
+ LibraryElement get exportedLibrary {
+ if (_unlinkedExportNonPublic != null && _exportedLibrary == null) {
+ LibraryElementImpl library = enclosingElement as LibraryElementImpl;
+ _exportedLibrary = library.resynthesizerContext.buildExportedLibrary(uri);
+ }
+ return _exportedLibrary;
+ }
+
+ void set exportedLibrary(LibraryElement exportedLibrary) {
+ assert(_unlinkedExportNonPublic == null);
+ _exportedLibrary = exportedLibrary;
+ }
+
+ @override
+ String get identifier => exportedLibrary.name;
+
+ @override
+ ElementKind get kind => ElementKind.EXPORT;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedExportNonPublic != null) {
+ return _metadata ??= _buildAnnotations(
+ library.definingCompilationUnit as CompilationUnitElementImpl,
+ _unlinkedExportNonPublic.annotations);
+ }
+ return super.metadata;
+ }
+
+ void set metadata(List<ElementAnnotation> metadata) {
+ assert(_unlinkedExportNonPublic == null);
+ super.metadata = metadata;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedExportNonPublic != null) {
+ return _unlinkedExportNonPublic.offset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ String get uri {
+ if (_unlinkedExportPublic != null) {
+ return _selectedUri ??= _selectUri(
+ _unlinkedExportPublic.uri, _unlinkedExportPublic.configurations);
+ }
+ return super.uri;
+ }
+
+ @override
+ void set uri(String uri) {
+ assert(_unlinkedExportPublic == null);
+ super.uri = uri;
+ }
+
+ @override
+ int get uriEnd {
+ if (_unlinkedExportNonPublic != null) {
+ return _unlinkedExportNonPublic.uriEnd;
+ }
+ return super.uriEnd;
+ }
+
+ @override
+ void set uriEnd(int uriEnd) {
+ assert(_unlinkedExportNonPublic == null);
+ super.uriEnd = uriEnd;
+ }
+
+ @override
+ int get uriOffset {
+ if (_unlinkedExportNonPublic != null) {
+ return _unlinkedExportNonPublic.uriOffset;
+ }
+ return super.uriOffset;
+ }
+
+ @override
+ void set uriOffset(int uriOffset) {
+ assert(_unlinkedExportNonPublic == null);
+ super.uriOffset = uriOffset;
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitExportElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write("export ");
+ (exportedLibrary as LibraryElementImpl).appendTo(buffer);
+ }
+}
+
+/**
+ * A concrete implementation of a [FieldElement].
+ */
+class FieldElementImpl extends PropertyInducingElementImpl
+ implements FieldElement {
+ /**
+ * Initialize a newly created synthetic field element to have the given [name]
+ * at the given [offset].
+ */
+ FieldElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created field element to have the given [name].
+ */
+ FieldElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ FieldElementImpl.forSerialized(
+ UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedVariable, enclosingElement);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ factory FieldElementImpl.forSerializedFactory(
+ UnlinkedVariable unlinkedVariable, ClassElementImpl enclosingClass) {
+ if (unlinkedVariable.initializer?.bodyExpr != null &&
+ (unlinkedVariable.isConst ||
+ unlinkedVariable.isFinal && !unlinkedVariable.isStatic)) {
+ return new ConstFieldElementImpl.forSerialized(
+ unlinkedVariable, enclosingClass);
+ } else {
+ return new FieldElementImpl.forSerialized(
+ unlinkedVariable, enclosingClass);
+ }
+ }
+
+ @override
+ ClassElement get enclosingElement => super.enclosingElement as ClassElement;
+
+ @override
+ bool get isEnumConstant =>
+ enclosingElement != null ? enclosingElement.isEnum : false;
+
+ @override
+ bool get isStatic {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.isStatic;
+ }
+ return hasModifier(Modifier.STATIC);
+ }
+
+ @override
+ bool get isVirtual {
+ for (ElementAnnotationImpl annotation in metadata) {
+ if (annotation.isVirtual) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ ElementKind get kind => ElementKind.FIELD;
+
+ /**
+ * Set whether this field is static.
+ */
+ void set static(bool isStatic) {
+ assert(_unlinkedVariable == null);
+ setModifier(Modifier.STATIC, isStatic);
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
+
+ @override
+ AstNode computeNode() {
+ if (isEnumConstant) {
+ return getNodeMatching((node) => node is EnumConstantDeclaration);
+ } else {
+ return getNodeMatching((node) => node is VariableDeclaration);
+ }
+ }
+}
+
+/**
+ * A [ParameterElementImpl] that has the additional information of the
+ * [FieldElement] associated with the parameter.
+ */
+class FieldFormalParameterElementImpl extends ParameterElementImpl
+ implements FieldFormalParameterElement {
+ /**
+ * The field associated with this field formal parameter.
+ */
+ FieldElement _field;
+
+ /**
+ * Initialize a newly created parameter element to have the given [name] and
+ * [nameOffset].
+ */
+ FieldFormalParameterElementImpl(String name, int nameOffset)
+ : super(name, nameOffset);
+
+ /**
+ * Initialize a newly created parameter element to have the given [name].
+ */
+ FieldFormalParameterElementImpl.forNode(Identifier name)
+ : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ FieldFormalParameterElementImpl.forSerialized(
+ UnlinkedParam unlinkedParam, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedParam, enclosingElement);
+
+ @override
+ FieldElement get field {
+ if (_unlinkedParam != null && _field == null) {
+ Element enclosingClass = enclosingElement?.enclosingElement;
+ if (enclosingClass is ClassElement) {
+ _field = enclosingClass.getField(_unlinkedParam.name);
+ }
+ }
+ return _field;
+ }
+
+ void set field(FieldElement field) {
+ assert(_unlinkedParam == null);
+ _field = field;
+ }
+
+ @override
+ bool get isInitializingFormal => true;
+
+ @override
+ DartType get type {
+ if (_unlinkedParam != null && _unlinkedParam.type == null) {
+ _type ??= field?.type ?? DynamicTypeImpl.instance;
+ }
+ return super.type;
+ }
+
+ @override
+ void set type(DartType type) {
+ assert(_unlinkedParam == null);
+ _type = type;
+ }
+
+ @override
+ accept(ElementVisitor visitor) =>
+ visitor.visitFieldFormalParameterElement(this);
+}
+
+/**
+ * A concrete implementation of a [FunctionElement].
+ */
+class FunctionElementImpl extends ExecutableElementImpl
+ implements FunctionElement {
+ /**
+ * The offset to the beginning of the visible range for this element.
+ */
+ int _visibleRangeOffset = 0;
+
+ /**
+ * The length of the visible range for this element, or `-1` if this element
+ * does not have a visible range.
+ */
+ int _visibleRangeLength = -1;
+
+ /**
+ * Initialize a newly created function element to have the given [name] and
+ * [offset].
+ */
+ FunctionElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created function element to have the given [name].
+ */
+ FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize a newly created function element to have no name and the given
+ * [nameOffset]. This is used for function expressions, that have no name.
+ */
+ FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ FunctionElementImpl.forSerialized(
+ UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement)
+ : super.forSerialized(serializedExecutable, enclosingElement);
+
+ /**
+ * Synthesize an unnamed function element that takes [parameters] and returns
+ * [returnType].
+ */
+ FunctionElementImpl.synthetic(
+ List<ParameterElement> parameters, DartType returnType)
+ : super("", -1) {
+ synthetic = true;
+ this.returnType = returnType;
+ this.parameters = parameters;
+
+ type = new FunctionTypeImpl(this);
+ }
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext {
+ return (enclosingElement as ElementImpl).typeParameterContext;
+ }
+
+ @override
+ String get identifier {
+ String identifier = super.identifier;
+ Element enclosing = this.enclosingElement;
+ if (enclosing is ExecutableElement) {
+ int id = ElementImpl._findElementIndexUsingIdentical(
+ enclosing.functions, this);
+ identifier += "@$id";
+ }
+ return identifier;
+ }
+
+ @override
+ bool get isEntryPoint {
+ return isStatic && displayName == FunctionElement.MAIN_FUNCTION_NAME;
+ }
+
+ @override
+ bool get isStatic => enclosingElement is CompilationUnitElement;
+
+ @override
+ ElementKind get kind => ElementKind.FUNCTION;
+
+ @override
+ SourceRange get visibleRange {
+ if (serializedExecutable != null) {
+ if (serializedExecutable.visibleLength == 0) {
+ return null;
+ }
+ return new SourceRange(serializedExecutable.visibleOffset,
+ serializedExecutable.visibleLength);
+ }
+ if (_visibleRangeLength < 0) {
+ return null;
+ }
+ return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ String name = displayName;
+ if (name != null) {
+ buffer.write(name);
+ }
+ super.appendTo(buffer);
+ }
+
+ @override
+ FunctionDeclaration computeNode() =>
+ getNodeMatching((node) => node is FunctionDeclaration);
+
+ /**
+ * Set the visible range for this element to the range starting at the given
+ * [offset] with the given [length].
+ */
+ void setVisibleRange(int offset, int length) {
+ assert(serializedExecutable == null);
+ _visibleRangeOffset = offset;
+ _visibleRangeLength = length;
+ }
+
+ /**
+ * Set the parameters defined by this type alias to the given [parameters]
+ * without becoming the parent of the parameters. This should only be used by
+ * the [TypeResolverVisitor] when creating a synthetic type alias.
+ */
+ void shareParameters(List<ParameterElement> parameters) {
+ this._parameters = parameters;
+ }
+
+ /**
+ * Set the type parameters defined by this type alias to the given
+ * [parameters] without becoming the parent of the parameters. This should
+ * only be used by the [TypeResolverVisitor] when creating a synthetic type
+ * alias.
+ */
+ void shareTypeParameters(List<TypeParameterElement> typeParameters) {
+ this._typeParameters = typeParameters;
+ }
+
+ /**
+ * Create and return [FunctionElement]s for the given [unlinkedFunctions].
+ */
+ static List<FunctionElement> resynthesizeList(
+ ExecutableElementImpl executableElement,
+ List<UnlinkedExecutable> unlinkedFunctions) {
+ int length = unlinkedFunctions.length;
+ if (length != 0) {
+ List<FunctionElement> elements = new List<FunctionElement>(length);
+ for (int i = 0; i < length; i++) {
+ elements[i] = new FunctionElementImpl.forSerialized(
+ unlinkedFunctions[i], executableElement);
+ }
+ return elements;
+ } else {
+ return const <FunctionElement>[];
+ }
+ }
+}
+
+/**
+ * Implementation of [FunctionElementImpl] for a function typed parameter.
+ */
+class FunctionElementImpl_forFunctionTypedParameter
+ extends FunctionElementImpl {
+ @override
+ final CompilationUnitElementImpl enclosingUnit;
+
+ /**
+ * The enclosing function typed [ParameterElementImpl].
+ */
+ final ParameterElementImpl _parameter;
+
+ FunctionElementImpl_forFunctionTypedParameter(
+ this.enclosingUnit, this._parameter)
+ : super('', -1);
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext =>
+ _parameter.typeParameterContext;
+
+ @override
+ bool get isSynthetic => true;
+}
+
+/**
+ * Implementation of [FunctionElementImpl] for a synthetic function element
+ * that was synthesized by a LUB computation.
+ */
+class FunctionElementImpl_forLUB extends FunctionElementImpl {
+ @override
+ final CompilationUnitElementImpl enclosingUnit;
+
+ @override
+ final TypeParameterizedElementMixin enclosingTypeParameterContext;
+
+ final EntityRef _entityRef;
+
+ FunctionElementImpl_forLUB(
+ this.enclosingUnit, this.enclosingTypeParameterContext, this._entityRef)
+ : super('', -1);
+
+ @override
+ bool get isSynthetic => true;
+
+ @override
+ List<ParameterElement> get parameters {
+ return _parameters ??= ParameterElementImpl
+ .resynthesizeList(_entityRef.syntheticParams, this, synthetic: true);
+ }
+
+ @override
+ void set parameters(List<ParameterElement> parameters) {
+ assert(false);
+ }
+
+ @override
+ DartType get returnType {
+ return _returnType ??= enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_entityRef.syntheticReturnType, typeParameterContext);
+ }
+
+ @override
+ void set returnType(DartType returnType) {
+ assert(false);
+ }
+
+ @override
+ FunctionType get type {
+ return _type ??=
+ new FunctionTypeImpl.elementWithNameAndArgs(this, null, null, false);
+ }
+
+ @override
+ void set type(FunctionType type) {
+ assert(false);
+ }
+}
+
+/**
+ * A concrete implementation of a [FunctionTypeAliasElement].
+ */
+class FunctionTypeAliasElementImpl extends ElementImpl
+ with TypeParameterizedElementMixin
+ implements FunctionTypeAliasElement {
+ /**
+ * The unlinked representation of the type in the summary.
+ */
+ final UnlinkedTypedef _unlinkedTypedef;
+
+ /**
+ * A list containing all of the parameters defined by this type alias.
+ */
+ List<ParameterElement> _parameters;
+
+ /**
+ * The return type defined by this type alias.
+ */
+ DartType _returnType;
+
+ /**
+ * The type of function defined by this type alias.
+ */
+ FunctionType _type;
+
+ /**
+ * A list containing all of the type parameters defined for this type.
+ */
+ List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
+
+ /**
+ * Initialize a newly created type alias element to have the given name.
+ *
+ * [name] the name of this element
+ * [nameOffset] the offset of the name of this element in the file that
+ * contains the declaration of this element
+ */
+ FunctionTypeAliasElementImpl(String name, int nameOffset)
+ : _unlinkedTypedef = null,
+ super(name, nameOffset);
+
+ /**
+ * Initialize a newly created type alias element to have the given [name].
+ */
+ FunctionTypeAliasElementImpl.forNode(Identifier name)
+ : _unlinkedTypedef = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ FunctionTypeAliasElementImpl.forSerialized(
+ this._unlinkedTypedef, CompilationUnitElementImpl enclosingUnit)
+ : super.forSerialized(enclosingUnit);
+
+ @override
+ int get codeLength {
+ if (_unlinkedTypedef != null) {
+ return _unlinkedTypedef.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedTypedef != null) {
+ return _unlinkedTypedef.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ String get displayName => name;
+
+ @override
+ String get documentationComment {
+ if (_unlinkedTypedef != null) {
+ return _unlinkedTypedef?.documentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ @override
+ CompilationUnitElement get enclosingElement =>
+ super.enclosingElement as CompilationUnitElement;
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
+
+ @override
+ CompilationUnitElementImpl get enclosingUnit =>
+ _enclosingElement as CompilationUnitElementImpl;
+
+ @override
+ ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedTypedef != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedTypedef.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ String get name {
+ if (_unlinkedTypedef != null) {
+ return _unlinkedTypedef.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedTypedef != null) {
+ return _unlinkedTypedef.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ List<ParameterElement> get parameters {
+ if (_unlinkedTypedef != null) {
+ _parameters ??= ParameterElementImpl.resynthesizeList(
+ _unlinkedTypedef.parameters, this);
+ }
+ return _parameters ?? const <ParameterElement>[];
+ }
+
+ /**
+ * Set the parameters defined by this type alias to the given [parameters].
+ */
+ void set parameters(List<ParameterElement> parameters) {
+ assert(_unlinkedTypedef == null);
+ if (parameters != null) {
+ for (ParameterElement parameter in parameters) {
+ (parameter as ParameterElementImpl).enclosingElement = this;
+ }
+ }
+ this._parameters = parameters;
+ }
+
+ @override
+ DartType get returnType {
+ if (_unlinkedTypedef != null && _returnType == null) {
+ _returnType = enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_unlinkedTypedef.returnType, this);
+ }
+ return _returnType;
+ }
+
+ void set returnType(DartType returnType) {
+ assert(_unlinkedTypedef == null);
+ _returnType = returnType;
+ }
+
+ @override
+ FunctionType get type {
+ if (_unlinkedTypedef != null && _type == null) {
+ _type = new FunctionTypeImpl.forTypedef(this);
+ }
+ return _type;
+ }
+
+ void set type(FunctionType type) {
+ assert(_unlinkedTypedef == null);
+ _type = type;
+ }
+
+ @override
+ TypeParameterizedElementMixin get typeParameterContext => this;
+
+ @override
+ List<TypeParameterElement> get typeParameters {
+ if (_unlinkedTypedef != null) {
+ return super.typeParameters;
+ }
+ return _typeParameters;
+ }
+
+ /**
+ * Set the type parameters defined for this type to the given
+ * [typeParameters].
+ */
+ void set typeParameters(List<TypeParameterElement> typeParameters) {
+ assert(_unlinkedTypedef == null);
+ for (TypeParameterElement typeParameter in typeParameters) {
+ (typeParameter as TypeParameterElementImpl).enclosingElement = this;
+ }
+ this._typeParameters = typeParameters;
+ }
+
+ @override
+ List<UnlinkedTypeParam> get unlinkedTypeParams =>
+ _unlinkedTypedef.typeParameters;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write("typedef ");
+ buffer.write(displayName);
+ int typeParameterCount = _typeParameters.length;
+ if (typeParameterCount > 0) {
+ buffer.write("<");
+ for (int i = 0; i < typeParameterCount; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
+ }
+ buffer.write(">");
+ }
+ buffer.write("(");
+ int parameterCount = _parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ (_parameters[i] as ParameterElementImpl).appendTo(buffer);
+ }
+ buffer.write(")");
+ if (type != null) {
+ buffer.write(ElementImpl.RIGHT_ARROW);
+ buffer.write(type.returnType);
+ } else if (returnType != null) {
+ buffer.write(ElementImpl.RIGHT_ARROW);
+ buffer.write(returnType);
+ }
+ }
+
+ @override
+ FunctionTypeAlias computeNode() =>
+ getNodeMatching((node) => node is FunctionTypeAlias);
+
+ @override
+ ElementImpl getChild(String identifier) {
+ for (ParameterElement parameter in parameters) {
+ ParameterElementImpl parameterImpl = parameter;
+ if (parameterImpl.identifier == identifier) {
+ return parameterImpl;
+ }
+ }
+ for (TypeParameterElement typeParameter in _typeParameters) {
+ TypeParameterElementImpl typeParameterImpl = typeParameter;
+ if (typeParameterImpl.identifier == identifier) {
+ return typeParameterImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(parameters, visitor);
+ safelyVisitChildren(_typeParameters, visitor);
+ }
+}
+
+/**
+ * A concrete implementation of a [HideElementCombinator].
+ */
+class HideElementCombinatorImpl implements HideElementCombinator {
+ /**
+ * The unlinked representation of the combinator in the summary.
+ */
+ final UnlinkedCombinator _unlinkedCombinator;
+
+ /**
+ * The names that are not to be made visible in the importing library even if
+ * they are defined in the imported library.
+ */
+ List<String> _hiddenNames;
+
+ HideElementCombinatorImpl() : _unlinkedCombinator = null;
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ HideElementCombinatorImpl.forSerialized(this._unlinkedCombinator);
+
+ @override
+ List<String> get hiddenNames {
+ if (_unlinkedCombinator != null) {
+ _hiddenNames ??= _unlinkedCombinator.hides.toList(growable: false);
+ }
+ return _hiddenNames ?? const <String>[];
+ }
+
+ void set hiddenNames(List<String> hiddenNames) {
+ assert(_unlinkedCombinator == null);
+ _hiddenNames = hiddenNames;
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write("show ");
+ int count = hiddenNames.length;
+ for (int i = 0; i < count; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ buffer.write(hiddenNames[i]);
+ }
+ return buffer.toString();
+ }
+}
+
+/**
+ * A concrete implementation of an [ImportElement].
+ */
+class ImportElementImpl extends UriReferencedElementImpl
+ implements ImportElement {
+ /**
+ * The unlinked representation of the import in the summary.
+ */
+ final UnlinkedImport _unlinkedImport;
+
+ /**
+ * The index of the dependency in the `imports` list.
+ */
+ final int _linkedDependency;
+
+ /**
+ * The offset of the prefix of this import in the file that contains the this
+ * import directive, or `-1` if this import is synthetic.
+ */
+ int _prefixOffset = 0;
+
+ /**
+ * The library that is imported into this library by this import directive.
+ */
+ LibraryElement _importedLibrary;
+
+ /**
+ * The combinators that were specified as part of the import directive in the
+ * order in which they were specified.
+ */
+ List<NamespaceCombinator> _combinators;
+
+ /**
+ * The prefix that was specified as part of the import directive, or `null` if
+ * there was no prefix specified.
+ */
+ PrefixElement _prefix;
+
+ /**
+ * The URI that was selected based on the [context] declared variables.
+ */
+ String _selectedUri;
+
+ /**
+ * Initialize a newly created import element at the given [offset].
+ * The offset may be `-1` if the import is synthetic.
+ */
+ ImportElementImpl(int offset)
+ : _unlinkedImport = null,
+ _linkedDependency = null,
+ super(null, offset);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ImportElementImpl.forSerialized(this._unlinkedImport, this._linkedDependency,
+ LibraryElementImpl enclosingLibrary)
+ : super.forSerialized(enclosingLibrary);
+
+ @override
+ List<NamespaceCombinator> get combinators {
+ if (_unlinkedImport != null && _combinators == null) {
+ _combinators = _buildCombinators(_unlinkedImport.combinators);
+ }
+ return _combinators ?? const <NamespaceCombinator>[];
+ }
+
+ void set combinators(List<NamespaceCombinator> combinators) {
+ assert(_unlinkedImport == null);
+ _combinators = combinators;
+ }
+
+ /**
+ * Set whether this import is for a deferred library.
+ */
+ void set deferred(bool isDeferred) {
+ assert(_unlinkedImport == null);
+ setModifier(Modifier.DEFERRED, isDeferred);
+ }
+
+ @override
+ String get identifier => "${importedLibrary.identifier}@$nameOffset";
+
+ @override
+ LibraryElement get importedLibrary {
+ if (_linkedDependency != null) {
+ if (_importedLibrary == null) {
+ LibraryElementImpl library = enclosingElement as LibraryElementImpl;
+ if (_linkedDependency == 0) {
+ _importedLibrary = library;
+ } else {
+ _importedLibrary = library.resynthesizerContext
+ .buildImportedLibrary(_linkedDependency);
+ }
+ }
+ }
+ return _importedLibrary;
+ }
+
+ void set importedLibrary(LibraryElement importedLibrary) {
+ assert(_unlinkedImport == null);
+ _importedLibrary = importedLibrary;
+ }
+
+ @override
+ bool get isDeferred {
+ if (_unlinkedImport != null) {
+ return _unlinkedImport.isDeferred;
+ }
+ return hasModifier(Modifier.DEFERRED);
+ }
+
+ @override
+ bool get isSynthetic {
+ if (_unlinkedImport != null) {
+ return _unlinkedImport.isImplicit;
+ }
+ return super.isSynthetic;
+ }
+
+ @override
+ ElementKind get kind => ElementKind.IMPORT;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedImport != null) {
+ return _metadata ??= _buildAnnotations(
+ library.definingCompilationUnit as CompilationUnitElementImpl,
+ _unlinkedImport.annotations);
+ }
+ return super.metadata;
+ }
+
+ void set metadata(List<ElementAnnotation> metadata) {
+ assert(_unlinkedImport == null);
+ super.metadata = metadata;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedImport != null) {
+ if (_unlinkedImport.isImplicit) {
+ return -1;
+ }
+ return _unlinkedImport.offset;
+ }
+ return super.nameOffset;
+ }
+
+ PrefixElement get prefix {
+ if (_unlinkedImport != null) {
+ if (_unlinkedImport.prefixReference != 0 && _prefix == null) {
+ LibraryElementImpl library = enclosingElement as LibraryElementImpl;
+ _prefix = new PrefixElementImpl.forSerialized(_unlinkedImport, library);
+ }
+ }
+ return _prefix;
+ }
+
+ void set prefix(PrefixElement prefix) {
+ assert(_unlinkedImport == null);
+ _prefix = prefix;
+ }
+
+ @override
+ int get prefixOffset {
+ if (_unlinkedImport != null) {
+ return _unlinkedImport.prefixOffset;
+ }
+ return _prefixOffset;
+ }
+
+ void set prefixOffset(int prefixOffset) {
+ assert(_unlinkedImport == null);
+ _prefixOffset = prefixOffset;
+ }
+
+ @override
+ String get uri {
+ if (_unlinkedImport != null) {
+ if (_unlinkedImport.isImplicit) {
+ return null;
+ }
+ return _selectedUri ??=
+ _selectUri(_unlinkedImport.uri, _unlinkedImport.configurations);
+ }
+ return super.uri;
+ }
+
+ @override
+ void set uri(String uri) {
+ assert(_unlinkedImport == null);
+ super.uri = uri;
+ }
+
+ @override
+ int get uriEnd {
+ if (_unlinkedImport != null) {
+ if (_unlinkedImport.isImplicit) {
+ return -1;
+ }
+ return _unlinkedImport.uriEnd;
+ }
+ return super.uriEnd;
+ }
+
+ @override
+ void set uriEnd(int uriEnd) {
+ assert(_unlinkedImport == null);
+ super.uriEnd = uriEnd;
+ }
+
+ @override
+ int get uriOffset {
+ if (_unlinkedImport != null) {
+ if (_unlinkedImport.isImplicit) {
+ return -1;
+ }
+ return _unlinkedImport.uriOffset;
+ }
+ return super.uriOffset;
+ }
+
+ @override
+ void set uriOffset(int uriOffset) {
+ assert(_unlinkedImport == null);
+ super.uriOffset = uriOffset;
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitImportElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write("import ");
+ (importedLibrary as LibraryElementImpl).appendTo(buffer);
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ prefix?.accept(visitor);
+ }
+
+ static List<NamespaceCombinator> _buildCombinators(
+ List<UnlinkedCombinator> unlinkedCombinators) {
+ int length = unlinkedCombinators.length;
+ if (length != 0) {
+ List<NamespaceCombinator> combinators =
+ new List<NamespaceCombinator>(length);
+ for (int i = 0; i < length; i++) {
+ UnlinkedCombinator unlinkedCombinator = unlinkedCombinators[i];
+ combinators[i] = unlinkedCombinator.shows.isNotEmpty
+ ? new ShowElementCombinatorImpl.forSerialized(unlinkedCombinator)
+ : new HideElementCombinatorImpl.forSerialized(unlinkedCombinator);
+ }
+ return combinators;
+ } else {
+ return const <NamespaceCombinator>[];
+ }
+ }
+}
+
+/**
+ * A concrete implementation of a [LabelElement].
+ */
+class LabelElementImpl extends ElementImpl implements LabelElement {
+ /**
+ * The unlinked representation of the label in the summary.
+ */
+ final UnlinkedLabel _unlinkedLabel;
+
+ /**
+ * A flag indicating whether this label is associated with a `switch`
+ * statement.
+ */
+ // TODO(brianwilkerson) Make this a modifier.
+ final bool _onSwitchStatement;
+
+ /**
+ * A flag indicating whether this label is associated with a `switch` member
+ * (`case` or `default`).
+ */
+ // TODO(brianwilkerson) Make this a modifier.
+ final bool _onSwitchMember;
+
+ /**
+ * Initialize a newly created label element to have the given [name].
+ * [onSwitchStatement] should be `true` if this label is associated with a
+ * `switch` statement and [onSwitchMember] should be `true` if this label is
+ * associated with a `switch` member.
+ */
+ LabelElementImpl(String name, int nameOffset, this._onSwitchStatement,
+ this._onSwitchMember)
+ : _unlinkedLabel = null,
+ super(name, nameOffset);
+
+ /**
+ * Initialize a newly created label element to have the given [name].
+ * [_onSwitchStatement] should be `true` if this label is associated with a
+ * `switch` statement and [_onSwitchMember] should be `true` if this label is
+ * associated with a `switch` member.
+ */
+ LabelElementImpl.forNode(
+ Identifier name, this._onSwitchStatement, this._onSwitchMember)
+ : _unlinkedLabel = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ LabelElementImpl.forSerialized(
+ UnlinkedLabel unlinkedLabel, ExecutableElementImpl enclosingExecutable)
+ : _unlinkedLabel = unlinkedLabel,
+ _onSwitchStatement = unlinkedLabel.isOnSwitchStatement,
+ _onSwitchMember = unlinkedLabel.isOnSwitchMember,
+ super.forSerialized(enclosingExecutable);
+
+ @override
+ String get displayName => name;
+
+ @override
+ ExecutableElement get enclosingElement =>
+ super.enclosingElement as ExecutableElement;
+
+ /**
+ * Return `true` if this label is associated with a `switch` member (`case` or
+ * `default`).
+ */
+ bool get isOnSwitchMember => _onSwitchMember;
+
+ /**
+ * Return `true` if this label is associated with a `switch` statement.
+ */
+ bool get isOnSwitchStatement => _onSwitchStatement;
+
+ @override
+ ElementKind get kind => ElementKind.LABEL;
+
+ @override
+ String get name {
+ if (_unlinkedLabel != null) {
+ return _unlinkedLabel.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedLabel != null) {
+ return _unlinkedLabel.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitLabelElement(this);
+
+ /**
+ * Create and return [LabelElement]s for the given [unlinkedLabels].
+ */
+ static List<LabelElement> resynthesizeList(
+ ExecutableElementImpl enclosingExecutable,
+ List<UnlinkedLabel> unlinkedLabels) {
+ int length = unlinkedLabels.length;
+ if (length != 0) {
+ List<LabelElement> elements = new List<LabelElement>(length);
+ for (int i = 0; i < length; i++) {
+ elements[i] = new LabelElementImpl.forSerialized(
+ unlinkedLabels[i], enclosingExecutable);
+ }
+ return elements;
+ } else {
+ return const <LabelElement>[];
+ }
+ }
+}
+
+/**
+ * A concrete implementation of a [LibraryElement].
+ */
+class LibraryElementImpl extends ElementImpl implements LibraryElement {
+ /**
+ * The analysis context in which this library is defined.
+ */
+ final AnalysisContext context;
+
+ final LibraryResynthesizerContext resynthesizerContext;
+
+ final UnlinkedUnit _unlinkedDefiningUnit;
+
+ /**
+ * The compilation unit that defines this library.
+ */
+ CompilationUnitElement _definingCompilationUnit;
+
+ /**
+ * The entry point for this library, or `null` if this library does not have
+ * an entry point.
+ */
+ FunctionElement _entryPoint;
+
+ /**
+ * A list containing specifications of all of the imports defined in this
+ * library.
+ */
+ List<ImportElement> _imports;
+
+ /**
+ * A list containing specifications of all of the exports defined in this
+ * library.
+ */
+ List<ExportElement> _exports;
+
+ /**
+ * A list containing the strongly connected component in the import/export
+ * graph in which the current library resides. Computed on demand, null
+ * if not present. If _libraryCycle is set, then the _libraryCycle field
+ * for all libraries reachable from this library in the import/export graph
+ * is also set.
+ */
+ List<LibraryElement> _libraryCycle = null;
+
+ /**
+ * A list containing all of the compilation units that are included in this
+ * library using a `part` directive.
+ */
+ List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST;
+
+ /**
+ * The element representing the synthetic function `loadLibrary` that is
+ * defined for this library, or `null` if the element has not yet been created.
+ */
+ FunctionElement _loadLibraryFunction;
+
+ @override
+ final int nameLength;
+
+ /**
+ * The export [Namespace] of this library, `null` if it has not been
+ * computed yet.
+ */
+ Namespace _exportNamespace;
+
+ /**
+ * The public [Namespace] of this library, `null` if it has not been
+ * computed yet.
+ */
+ Namespace _publicNamespace;
+
+ /**
+ * A bit-encoded form of the capabilities associated with this library.
+ */
+ int _resolutionCapabilities = 0;
+
+ /**
+ * The cached list of prefixes.
+ */
+ List<PrefixElement> _prefixes;
+
+ /**
+ * Initialize a newly created library element in the given [context] to have
+ * the given [name] and [offset].
+ */
+ LibraryElementImpl(this.context, String name, int offset, this.nameLength)
+ : resynthesizerContext = null,
+ _unlinkedDefiningUnit = null,
+ super(name, offset);
+
+ /**
+ * Initialize a newly created library element in the given [context] to have
+ * the given [name].
+ */
+ LibraryElementImpl.forNode(this.context, LibraryIdentifier name)
+ : nameLength = name != null ? name.length : 0,
+ resynthesizerContext = null,
+ _unlinkedDefiningUnit = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ LibraryElementImpl.forSerialized(this.context, String name, int offset,
+ this.nameLength, this.resynthesizerContext, this._unlinkedDefiningUnit)
+ : super.forSerialized(null) {
+ _name = name;
+ _nameOffset = offset;
+ setResolutionCapability(
+ LibraryResolutionCapability.resolvedTypeNames, true);
+ setResolutionCapability(
+ LibraryResolutionCapability.constantExpressions, true);
+ }
+
+ @override
+ int get codeLength {
+ CompilationUnitElement unit = _definingCompilationUnit;
+ if (unit is CompilationUnitElementImpl) {
+ return unit.codeLength;
+ }
+ return null;
+ }
+
+ @override
+ int get codeOffset {
+ CompilationUnitElement unit = _definingCompilationUnit;
+ if (unit is CompilationUnitElementImpl) {
+ return unit.codeOffset;
+ }
+ return null;
+ }
+
+ @override
+ CompilationUnitElement get definingCompilationUnit =>
+ _definingCompilationUnit;
+
+ /**
+ * Set the compilation unit that defines this library to the given compilation
+ * [unit].
+ */
+ void set definingCompilationUnit(CompilationUnitElement unit) {
+ assert((unit as CompilationUnitElementImpl).librarySource == unit.source);
+ (unit as CompilationUnitElementImpl).enclosingElement = this;
+ this._definingCompilationUnit = unit;
+ }
+
+ @override
+ String get documentationComment {
+ if (_unlinkedDefiningUnit != null) {
+ return _unlinkedDefiningUnit?.libraryDocumentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ FunctionElement get entryPoint {
+ if (resynthesizerContext != null) {
+ _entryPoint ??= resynthesizerContext.findEntryPoint();
+ }
+ return _entryPoint;
+ }
+
+ void set entryPoint(FunctionElement entryPoint) {
+ _entryPoint = entryPoint;
+ }
+
+ @override
+ List<LibraryElement> get exportedLibraries {
+ HashSet<LibraryElement> libraries = new HashSet<LibraryElement>();
+ for (ExportElement element in exports) {
+ LibraryElement library = element.exportedLibrary;
+ if (library != null) {
+ libraries.add(library);
+ }
+ }
+ return libraries.toList(growable: false);
+ }
+
+ @override
+ Namespace get exportNamespace {
+ if (resynthesizerContext != null) {
+ _exportNamespace ??= resynthesizerContext.buildExportNamespace();
+ }
+ return _exportNamespace;
+ }
+
+ void set exportNamespace(Namespace exportNamespace) {
+ _exportNamespace = exportNamespace;
+ }
+
+ @override
+ List<ExportElement> get exports {
+ if (_unlinkedDefiningUnit != null && _exports == null) {
+ List<UnlinkedExportNonPublic> unlinkedNonPublicExports =
+ _unlinkedDefiningUnit.exports;
+ List<UnlinkedExportPublic> unlinkedPublicExports =
+ _unlinkedDefiningUnit.publicNamespace.exports;
+ assert(
+ _unlinkedDefiningUnit.exports.length == unlinkedPublicExports.length);
+ int length = unlinkedNonPublicExports.length;
+ if (length != 0) {
+ List<ExportElement> exports = new List<ExportElement>(length);
+ for (int i = 0; i < length; i++) {
+ UnlinkedExportPublic serializedExportPublic =
+ unlinkedPublicExports[i];
+ UnlinkedExportNonPublic serializedExportNonPublic =
+ unlinkedNonPublicExports[i];
+ exports[i] = new ExportElementImpl.forSerialized(
+ serializedExportPublic, serializedExportNonPublic, library);
+ }
+ _exports = exports;
+ } else {
+ _exports = const <ExportElement>[];
+ }
+ }
+ return _exports ?? const <ExportElement>[];
+ }
+
+ /**
+ * Set the specifications of all of the exports defined in this library to the
+ * given list of [exports].
+ */
+ void set exports(List<ExportElement> exports) {
+ assert(_unlinkedDefiningUnit == null);
+ for (ExportElement exportElement in exports) {
+ (exportElement as ExportElementImpl).enclosingElement = this;
+ }
+ this._exports = exports;
+ }
+
+ @override
+ bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI);
+
+ /**
+ * Set whether this library has an import of a "dart-ext" URI.
+ */
+ void set hasExtUri(bool hasExtUri) {
+ setModifier(Modifier.HAS_EXT_URI, hasExtUri);
+ }
+
+ @override
+ bool get hasLoadLibraryFunction {
+ if (_definingCompilationUnit.hasLoadLibraryFunction) {
+ return true;
+ }
+ for (int i = 0; i < _parts.length; i++) {
+ if (_parts[i].hasLoadLibraryFunction) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ String get identifier => _definingCompilationUnit.source.encoding;
+
+ @override
+ List<LibraryElement> get importedLibraries {
+ HashSet<LibraryElement> libraries = new HashSet<LibraryElement>();
+ for (ImportElement element in imports) {
+ LibraryElement library = element.importedLibrary;
+ if (library != null) {
+ libraries.add(library);
+ }
+ }
+ return libraries.toList(growable: false);
+ }
+
+ @override
+ List<ImportElement> get imports {
+ if (_unlinkedDefiningUnit != null && _imports == null) {
+ List<UnlinkedImport> unlinkedImports = _unlinkedDefiningUnit.imports;
+ int length = unlinkedImports.length;
+ if (length != 0) {
+ List<ImportElement> imports = new List<ImportElement>(length);
+ LinkedLibrary linkedLibrary = resynthesizerContext.linkedLibrary;
+ for (int i = 0; i < length; i++) {
+ imports[i] = new ImportElementImpl.forSerialized(
+ unlinkedImports[i], linkedLibrary.importDependencies[i], library);
+ }
+ _imports = imports;
+ } else {
+ _imports = const <ImportElement>[];
+ }
+ }
+ return _imports ?? ImportElement.EMPTY_LIST;
+ }
+
+ /**
+ * Set the specifications of all of the imports defined in this library to the
+ * given list of [imports].
+ */
+ void set imports(List<ImportElement> imports) {
+ assert(_unlinkedDefiningUnit == null);
+ for (ImportElement importElement in imports) {
+ (importElement as ImportElementImpl).enclosingElement = this;
+ PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl;
+ if (prefix != null) {
+ prefix.enclosingElement = this;
+ }
+ }
+ this._imports = imports;
+ this._prefixes = null;
+ }
+
+ @override
+ bool get isBrowserApplication =>
+ entryPoint != null && isOrImportsBrowserLibrary;
+
+ @override
+ bool get isDartAsync => name == "dart.async";
+
+ @override
+ bool get isDartCore => name == "dart.core";
+
+ @override
+ bool get isInSdk =>
+ StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E);
+
+ /**
+ * Return `true` if the receiver directly or indirectly imports the
+ * 'dart:html' libraries.
+ */
+ bool get isOrImportsBrowserLibrary {
+ List<LibraryElement> visited = new List<LibraryElement>();
+ Source htmlLibSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
+ visited.add(this);
+ for (int index = 0; index < visited.length; index++) {
+ LibraryElement library = visited[index];
+ Source source = library.definingCompilationUnit.source;
+ if (source == htmlLibSource) {
+ return true;
+ }
+ for (LibraryElement importedLibrary in library.importedLibraries) {
+ if (!visited.contains(importedLibrary)) {
+ visited.add(importedLibrary);
+ }
+ }
+ for (LibraryElement exportedLibrary in library.exportedLibraries) {
+ if (!visited.contains(exportedLibrary)) {
+ visited.add(exportedLibrary);
+ }
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isResynthesized {
+ return resynthesizerContext != null;
+ }
+
+ @override
+ ElementKind get kind => ElementKind.LIBRARY;
+
+ @override
+ LibraryElement get library => this;
+
+ @override
+ List<LibraryElement> get libraryCycle {
+ if (_libraryCycle != null) {
+ return _libraryCycle;
+ }
+
+ // Global counter for this run of the algorithm
+ int counter = 0;
+ // The discovery times of each library
+ Map<LibraryElementImpl, int> indices = {};
+ // The set of scc candidates
+ Set<LibraryElementImpl> active = new Set();
+ // The stack of discovered elements
+ List<LibraryElementImpl> stack = [];
+ // For a given library that has not yet been processed by this run of the
+ // algorithm, compute the strongly connected components.
+ int scc(LibraryElementImpl library) {
+ int index = counter++;
+ int root = index;
+ indices[library] = index;
+ active.add(library);
+ stack.add(library);
+ LibraryElementImpl getActualLibrary(LibraryElement lib) {
+ // TODO(paulberry): this means that computing a library cycle will be
+ // expensive for libraries resynthesized from summaries, since it will
+ // require fully resynthesizing all the libraries in the cycle as well
+ // as any libraries they import or export. Try to find a better way.
+ if (lib is LibraryElementHandle) {
+ return lib.actualElement;
+ } else {
+ return lib;
+ }
+ }
+
+ void recurse(LibraryElementImpl child) {
+ if (!indices.containsKey(child)) {
+ // We haven't visited this child yet, so recurse on the child,
+ // returning the lowest numbered node reachable from the child. If
+ // the child can reach a root which is lower numbered than anything
+ // we've reached so far, update the root.
+ root = min(root, scc(child));
+ } else if (active.contains(child)) {
+ // The child has been visited, but has not yet been placed into a
+ // component. If the child is higher than anything we've seen so far
+ // update the root appropriately.
+ root = min(root, indices[child]);
+ }
+ }
+
+ // Recurse on all of the children in the import/export graph, filtering
+ // out those for which library cycles have already been computed.
+ library.exportedLibraries
+ .map(getActualLibrary)
+ .where((l) => l._libraryCycle == null)
+ .forEach(recurse);
+ library.importedLibraries
+ .map(getActualLibrary)
+ .where((l) => l._libraryCycle == null)
+ .forEach(recurse);
+
+ if (root == index) {
+ // This is the root of a strongly connected component.
+ // Pop the elements, and share the component across all
+ // of the elements.
+ List<LibraryElement> component = <LibraryElement>[];
+ LibraryElementImpl cur = null;
+ do {
+ cur = stack.removeLast();
+ active.remove(cur);
+ component.add(cur);
+ cur._libraryCycle = component;
+ } while (cur != library);
+ }
+ return root;
+ }
+
+ scc(library);
+ return _libraryCycle;
+ }
+
+ @override
+ FunctionElement get loadLibraryFunction {
+ assert(_loadLibraryFunction != null);
+ return _loadLibraryFunction;
+ }
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedDefiningUnit != null) {
+ _metadata ??= _buildAnnotations(
+ _definingCompilationUnit as CompilationUnitElementImpl,
+ _unlinkedDefiningUnit.libraryAnnotations);
+ return _metadata;
+ }
+ return super.metadata;
+ }
+
+ @override
+ List<CompilationUnitElement> get parts => _parts;
+
+ /**
+ * Set the compilation units that are included in this library using a `part`
+ * directive to the given list of [parts].
+ */
+ void set parts(List<CompilationUnitElement> parts) {
+ for (CompilationUnitElement compilationUnit in parts) {
+ assert((compilationUnit as CompilationUnitElementImpl).librarySource ==
+ source);
+ (compilationUnit as CompilationUnitElementImpl).enclosingElement = this;
+ }
+ this._parts = parts;
+ }
+
+ @override
+ List<PrefixElement> get prefixes {
+ if (_prefixes == null) {
+ HashSet<PrefixElement> prefixes = new HashSet<PrefixElement>();
+ for (ImportElement element in imports) {
+ PrefixElement prefix = element.prefix;
+ if (prefix != null) {
+ prefixes.add(prefix);
+ }
+ }
+ _prefixes = prefixes.toList(growable: false);
+ }
+ return _prefixes;
+ }
+
+ @override
+ Namespace get publicNamespace {
+ if (resynthesizerContext != null) {
+ _publicNamespace ??= resynthesizerContext.buildPublicNamespace();
+ }
+ return _publicNamespace;
+ }
+
+ void set publicNamespace(Namespace publicNamespace) {
+ _publicNamespace = publicNamespace;
+ }
+
+ @override
+ Source get source {
+ if (_definingCompilationUnit == null) {
+ return null;
+ }
+ return _definingCompilationUnit.source;
+ }
+
+ @override
+ List<CompilationUnitElement> get units {
+ List<CompilationUnitElement> units = new List<CompilationUnitElement>();
+ units.add(_definingCompilationUnit);
+ units.addAll(_parts);
+ return units;
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);
+
+ /**
+ * Create the [FunctionElement] to be returned by [loadLibraryFunction],
+ * using types provided by [typeProvider].
+ */
+ void createLoadLibraryFunction(TypeProvider typeProvider) {
+ FunctionElementImpl function =
+ new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1);
+ function.synthetic = true;
+ function.enclosingElement = this;
+ function.returnType = typeProvider.futureDynamicType;
+ function.type = new FunctionTypeImpl(function);
+ _loadLibraryFunction = function;
+ }
+
+ @override
+ ElementImpl getChild(String identifier) {
+ CompilationUnitElementImpl unitImpl = _definingCompilationUnit;
+ if (unitImpl.identifier == identifier) {
+ return unitImpl;
+ }
+ for (CompilationUnitElement part in _parts) {
+ CompilationUnitElementImpl partImpl = part;
+ if (partImpl.identifier == identifier) {
+ return partImpl;
+ }
+ }
+ for (ImportElement importElement in imports) {
+ ImportElementImpl importElementImpl = importElement;
+ if (importElementImpl.identifier == identifier) {
+ return importElementImpl;
+ }
+ }
+ for (ExportElement exportElement in exports) {
+ ExportElementImpl exportElementImpl = exportElement;
+ if (exportElementImpl.identifier == identifier) {
+ return exportElementImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) {
+ var imports = this.imports;
+ int count = imports.length;
+ List<ImportElement> importList = new List<ImportElement>();
+ for (int i = 0; i < count; i++) {
+ if (identical(imports[i].prefix, prefixElement)) {
+ importList.add(imports[i]);
+ }
+ }
+ return importList;
+ }
+
+ @override
+ ClassElement getType(String className) {
+ ClassElement type = _definingCompilationUnit.getType(className);
+ if (type != null) {
+ return type;
+ }
+ for (CompilationUnitElement part in _parts) {
+ type = part.getType(className);
+ if (type != null) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ /** Given an update to this library which may have added or deleted edges
+ * in the import/export graph originating from this node only, remove any
+ * cached library cycles in the element model which may have been invalidated.
+ */
+ void invalidateLibraryCycles() {
+ // If we have pre-computed library cycle information, then we must
+ // invalidate the information both on this element, and on certain
+ // other elements. Edges originating at this node may have been
+ // added or deleted. A deleted edge that points outside of this cycle
+ // cannot change the cycle information for anything outside of this cycle,
+ // and so it is sufficient to delete the cached library information on this
+ // cycle. An added edge which points to another node within the cycle
+ // only invalidates the cycle. An added edge which points to a node earlier
+ // in the topological sort of cycles induces no invalidation (since there
+ // are by definition no back edges from earlier cycles in the topological
+ // order, and hence no possible cycle can have been introduced. The only
+ // remaining case is that we have added an edge to a node which is later
+ // in the topological sort of cycles. This can induce cycles, since it
+ // represents a new back edge. It would be sufficient to invalidate the
+ // cycle information for all nodes that are between the target and the
+ // node in the topological order. For simplicity, we simply invalidate
+ // all nodes which are reachable from the source node.
+ // Note that in the invalidation phase, we do not cut off when we encounter
+ // a node with no library cycle information, since we do not know whether
+ // we are in the case where invalidation has already been performed, or we
+ // are in the case where library cycles have simply never been computed from
+ // a newly reachable node.
+ Set<LibraryElementImpl> active = new HashSet();
+ void invalidate(LibraryElement element) {
+ LibraryElementImpl library =
+ element is LibraryElementHandle ? element.actualElement : element;
+ if (active.add(library)) {
+ if (library._libraryCycle != null) {
+ library._libraryCycle.forEach(invalidate);
+ library._libraryCycle = null;
+ }
+ library.exportedLibraries.forEach(invalidate);
+ library.importedLibraries.forEach(invalidate);
+ }
+ }
+
+ invalidate(this);
+ }
+
+ /**
+ * Set whether the library has the given [capability] to
+ * correspond to the given [value].
+ */
+ void setResolutionCapability(
+ LibraryResolutionCapability capability, bool value) {
+ _resolutionCapabilities =
+ BooleanArray.set(_resolutionCapabilities, capability.index, value);
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ _definingCompilationUnit?.accept(visitor);
+ safelyVisitChildren(exports, visitor);
+ safelyVisitChildren(imports, visitor);
+ safelyVisitChildren(_parts, visitor);
+ }
+
+ /**
+ * Return `true` if the [library] has the given [capability].
+ */
+ static bool hasResolutionCapability(
+ LibraryElement library, LibraryResolutionCapability capability) {
+ return library is LibraryElementImpl &&
+ BooleanArray.get(library._resolutionCapabilities, capability.index);
+ }
+}
+
+/**
+ * Enum of possible resolution capabilities that a [LibraryElementImpl] has.
+ */
+enum LibraryResolutionCapability {
+ /**
+ * All elements have their types resolved.
+ */
+ resolvedTypeNames,
+
+ /**
+ * All (potentially) constants expressions are set into corresponding
+ * elements.
+ */
+ constantExpressions,
+}
+
+/**
+ * The context in which the library is resynthesized.
+ */
+abstract class LibraryResynthesizerContext {
+ /**
+ * Return the [LinkedLibrary] that corresponds to the library being
+ * resynthesized.
+ */
+ LinkedLibrary get linkedLibrary;
+
+ /**
+ * Return the exported [LibraryElement] for with the given [relativeUri].
+ */
+ LibraryElement buildExportedLibrary(String relativeUri);
+
+ /**
+ * Return the export namespace of the library.
+ */
+ Namespace buildExportNamespace();
+
+ /**
+ * Return the imported [LibraryElement] for the given dependency in the
+ * linked library.
+ */
+ LibraryElement buildImportedLibrary(int dependency);
+
+ /**
+ * Return the public namespace of the library.
+ */
+ Namespace buildPublicNamespace();
+
+ /**
+ * Find the entry point of the library.
+ */
+ FunctionElement findEntryPoint();
+
+ /**
+ * Ensure that getters and setters in different units use the same
+ * top-level variables.
+ */
+ void patchTopLevelAccessors();
+}
+
+/**
+ * A concrete implementation of a [LocalVariableElement].
+ */
+class LocalVariableElementImpl extends NonParameterVariableElementImpl
+ implements LocalVariableElement {
+ /**
+ * The offset to the beginning of the visible range for this element.
+ */
+ int _visibleRangeOffset = 0;
+
+ /**
+ * The length of the visible range for this element, or `-1` if this element
+ * does not have a visible range.
+ */
+ int _visibleRangeLength = -1;
+
+ /**
+ * Initialize a newly created method element to have the given [name] and
+ * [offset].
+ */
+ LocalVariableElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created local variable element to have the given [name].
+ */
+ LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ LocalVariableElementImpl.forSerialized(UnlinkedVariable unlinkedVariable,
+ ExecutableElementImpl enclosingExecutable)
+ : super.forSerialized(unlinkedVariable, enclosingExecutable);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ factory LocalVariableElementImpl.forSerializedFactory(
+ UnlinkedVariable unlinkedVariable,
+ ExecutableElementImpl enclosingExecutable) {
+ if (unlinkedVariable.isConst &&
+ unlinkedVariable.initializer?.bodyExpr != null) {
+ return new ConstLocalVariableElementImpl.forSerialized(
+ unlinkedVariable, enclosingExecutable);
+ } else {
+ return new LocalVariableElementImpl.forSerialized(
+ unlinkedVariable, enclosingExecutable);
+ }
+ }
+
+ @override
+ String get identifier {
+ String identifier = super.identifier;
+ Element enclosing = this.enclosingElement;
+ if (enclosing is ExecutableElement) {
+ int id = ElementImpl._findElementIndexUsingIdentical(
+ enclosing.localVariables, this);
+ identifier += "@$id";
+ }
+ return identifier;
+ }
+
+ @override
+ bool get isPotentiallyMutatedInClosure => true;
+
+ @override
+ bool get isPotentiallyMutatedInScope => true;
+
+ @override
+ ElementKind get kind => ElementKind.LOCAL_VARIABLE;
+
+ @override
+ SourceRange get visibleRange {
+ if (_unlinkedVariable != null) {
+ if (_unlinkedVariable.visibleLength == 0) {
+ return null;
+ }
+ return new SourceRange(
+ _unlinkedVariable.visibleOffset, _unlinkedVariable.visibleLength);
+ }
+ if (_visibleRangeLength < 0) {
+ return null;
+ }
+ return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write(type);
+ buffer.write(" ");
+ buffer.write(displayName);
+ }
+
+ @override
+ Declaration computeNode() => getNodeMatching(
+ (node) => node is DeclaredIdentifier || node is VariableDeclaration);
+
+ /**
+ * Set the visible range for this element to the range starting at the given
+ * [offset] with the given [length].
+ */
+ void setVisibleRange(int offset, int length) {
+ assert(_unlinkedVariable == null);
+ _visibleRangeOffset = offset;
+ _visibleRangeLength = length;
+ }
+}
+
+/**
+ * A concrete implementation of a [MethodElement].
+ */
+class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
+ /**
+ * Initialize a newly created method element to have the given [name] at the
+ * given [offset].
+ */
+ MethodElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created method element to have the given [name].
+ */
+ MethodElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ MethodElementImpl.forSerialized(
+ UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
+ : super.forSerialized(serializedExecutable, enclosingClass);
+
+ /**
+ * Set whether this method is abstract.
+ */
+ void set abstract(bool isAbstract) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
+
+ @override
+ List<TypeParameterType> get allEnclosingTypeParameterTypes {
+ if (isStatic) {
+ return const <TypeParameterType>[];
+ }
+ return super.allEnclosingTypeParameterTypes;
+ }
+
+ @override
+ String get displayName {
+ String displayName = super.displayName;
+ if ("unary-" == displayName) {
+ return "-";
+ }
+ return displayName;
+ }
+
+ @override
+ ClassElement get enclosingElement => super.enclosingElement as ClassElement;
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext =>
+ super.enclosingElement as ClassElementImpl;
+
+ @override
+ bool get isOperator {
+ String name = displayName;
+ if (name.isEmpty) {
+ return false;
+ }
+ int first = name.codeUnitAt(0);
+ return !((0x61 <= first && first <= 0x7A) ||
+ (0x41 <= first && first <= 0x5A) ||
+ first == 0x5F ||
+ first == 0x24);
+ }
+
+ @override
+ bool get isStatic {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isStatic;
+ }
+ return hasModifier(Modifier.STATIC);
+ }
+
+ @override
+ ElementKind get kind => ElementKind.METHOD;
+
+ @override
+ String get name {
+ String name = super.name;
+ if (name == '-' && parameters.isEmpty) {
+ return 'unary-';
+ }
+ return super.name;
+ }
+
+ /**
+ * Set whether this method is static.
+ */
+ void set static(bool isStatic) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.STATIC, isStatic);
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write(displayName);
+ super.appendTo(buffer);
+ }
+
+ @override
+ MethodDeclaration computeNode() =>
+ getNodeMatching((node) => node is MethodDeclaration);
+}
+
+/**
+ * The constants for all of the modifiers defined by the Dart language and for a
+ * few additional flags that are useful.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class Modifier implements Comparable<Modifier> {
+ /**
+ * Indicates that the modifier 'abstract' was applied to the element.
+ */
+ static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0);
+
+ /**
+ * Indicates that an executable element has a body marked as being
+ * asynchronous.
+ */
+ static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1);
+
+ /**
+ * Indicates that the modifier 'const' was applied to the element.
+ */
+ static const Modifier CONST = const Modifier('CONST', 2);
+
+ /**
+ * Indicates that the import element represents a deferred library.
+ */
+ static const Modifier DEFERRED = const Modifier('DEFERRED', 3);
+
+ /**
+ * Indicates that a class element was defined by an enum declaration.
+ */
+ static const Modifier ENUM = const Modifier('ENUM', 4);
+
+ /**
+ * Indicates that a class element was defined by an enum declaration.
+ */
+ static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5);
+
+ /**
+ * Indicates that the modifier 'factory' was applied to the element.
+ */
+ static const Modifier FACTORY = const Modifier('FACTORY', 6);
+
+ /**
+ * Indicates that the modifier 'final' was applied to the element.
+ */
+ static const Modifier FINAL = const Modifier('FINAL', 7);
+
+ /**
+ * Indicates that an executable element has a body marked as being a
+ * generator.
+ */
+ static const Modifier GENERATOR = const Modifier('GENERATOR', 8);
+
+ /**
+ * Indicates that the pseudo-modifier 'get' was applied to the element.
+ */
+ static const Modifier GETTER = const Modifier('GETTER', 9);
+
+ /**
+ * A flag used for libraries indicating that the defining compilation unit
+ * contains at least one import directive whose URI uses the "dart-ext"
+ * scheme.
+ */
+ static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10);
+
+ /**
+ * Indicates that the associated element did not have an explicit type
+ * associated with it. If the element is an [ExecutableElement], then the
+ * type being referred to is the return type.
+ */
+ static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 11);
+
+ /**
+ * Indicates that a class is a mixin application.
+ */
+ static const Modifier MIXIN_APPLICATION =
+ const Modifier('MIXIN_APPLICATION', 12);
+
+ /**
+ * Indicates that a class contains an explicit reference to 'super'.
+ */
+ static const Modifier REFERENCES_SUPER =
+ const Modifier('REFERENCES_SUPER', 13);
+
+ /**
+ * Indicates that the pseudo-modifier 'set' was applied to the element.
+ */
+ static const Modifier SETTER = const Modifier('SETTER', 14);
+
+ /**
+ * Indicates that the modifier 'static' was applied to the element.
+ */
+ static const Modifier STATIC = const Modifier('STATIC', 15);
+
+ /**
+ * Indicates that the element does not appear in the source code but was
+ * implicitly created. For example, if a class does not define any
+ * constructors, an implicit zero-argument constructor will be created and it
+ * will be marked as being synthetic.
+ */
+ static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16);
+
+ static const List<Modifier> values = const [
+ ABSTRACT,
+ ASYNCHRONOUS,
+ CONST,
+ DEFERRED,
+ ENUM,
+ EXTERNAL,
+ FACTORY,
+ FINAL,
+ GENERATOR,
+ GETTER,
+ HAS_EXT_URI,
+ IMPLICIT_TYPE,
+ MIXIN_APPLICATION,
+ REFERENCES_SUPER,
+ SETTER,
+ STATIC,
+ SYNTHETIC
+ ];
+
+ /**
+ * The name of this modifier.
+ */
+ final String name;
+
+ /**
+ * The ordinal value of the modifier.
+ */
+ final int ordinal;
+
+ const Modifier(this.name, this.ordinal);
+
+ @override
+ int get hashCode => ordinal;
+
+ @override
+ int compareTo(Modifier other) => ordinal - other.ordinal;
+
+ @override
+ String toString() => name;
+}
+
+/**
+ * A concrete implementation of a [MultiplyDefinedElement].
+ */
+class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
+ /**
+ * The unique integer identifier of this element.
+ */
+ final int id = ElementImpl._NEXT_ID++;
+
+ /**
+ * The analysis context in which the multiply defined elements are defined.
+ */
+ final AnalysisContext context;
+
+ /**
+ * The name of the conflicting elements.
+ */
+ String _name;
+
+ /**
+ * A list containing all of the elements defined in SDK libraries that
+ * conflict.
+ */
+ final List<Element> sdkElements;
+
+ /**
+ * A list containing all of the elements defined in non-SDK libraries that
+ * conflict.
+ */
+ final List<Element> nonSdkElements;
+
+ /**
+ * Initialize a newly created element in the given [context] to represent a
+ * list of conflicting [sdkElements] and [nonSdkElements]. At least one of the
+ * lists must contain more than one element.
+ */
+ MultiplyDefinedElementImpl(
+ this.context, this.sdkElements, this.nonSdkElements) {
+ if (nonSdkElements.length > 0) {
+ _name = nonSdkElements[0].name;
+ } else {
+ _name = sdkElements[0].name;
+ }
+ }
+
+ @override
+ List<Element> get conflictingElements {
+ if (sdkElements.isEmpty) {
+ return nonSdkElements;
+ } else if (nonSdkElements.isEmpty) {
+ return sdkElements;
+ }
+ List<Element> elements = nonSdkElements.toList();
+ elements.addAll(sdkElements);
+ return elements;
+ }
+
+ @override
+ String get displayName => _name;
+
+ @override
+ String get documentationComment => null;
+
+ @override
+ Element get enclosingElement => null;
+
+ @override
+ bool get isDeprecated => false;
+
+ @override
+ bool get isFactory => false;
+
+ @override
+ bool get isJS => false;
+
+ @override
+ bool get isOverride => false;
+
+ @override
+ bool get isPrivate {
+ String name = displayName;
+ if (name == null) {
+ return false;
+ }
+ return Identifier.isPrivateName(name);
+ }
+
+ @override
+ bool get isProtected => false;
+
+ @override
+ bool get isPublic => !isPrivate;
+
+ @override
+ bool get isRequired => false;
+
+ @override
+ bool get isSynthetic => true;
+
+ @override
+ ElementKind get kind => ElementKind.ERROR;
+
+ @override
+ LibraryElement get library => null;
+
+ @override
+ Source get librarySource => null;
+
+ @override
+ ElementLocation get location => null;
+
+ @override
+ List<ElementAnnotation> get metadata => const <ElementAnnotation>[];
+
+ @override
+ String get name => _name;
+
+ @override
+ int get nameLength => displayName != null ? displayName.length : 0;
+
+ @override
+ int get nameOffset => -1;
+
+ @override
+ Source get source => null;
+
+ @override
+ DartType get type => DynamicTypeImpl.instance;
+
+ @override
+ CompilationUnit get unit => null;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this);
+
+ @override
+ String computeDocumentationComment() => null;
+
+ @override
+ AstNode computeNode() => null;
+
+ @override
+ Element/*=E*/ getAncestor/*<E extends Element >*/(
+ Predicate<Element> predicate) =>
+ null;
+
+ @override
+ String getExtendedDisplayName(String shortName) {
+ if (shortName != null) {
+ return shortName;
+ }
+ return displayName;
+ }
+
+ @override
+ bool isAccessibleIn(LibraryElement library) {
+ for (Element element in conflictingElements) {
+ if (element.isAccessibleIn(library)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ bool needsSeparator = false;
+ void writeList(List<Element> elements) {
+ for (Element element in elements) {
+ if (needsSeparator) {
+ buffer.write(", ");
+ } else {
+ needsSeparator = true;
+ }
+ if (element is ElementImpl) {
+ element.appendTo(buffer);
+ } else {
+ buffer.write(element);
+ }
+ }
+ }
+
+ buffer.write("[");
+ writeList(nonSdkElements);
+ writeList(sdkElements);
+ buffer.write("]");
+ return buffer.toString();
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ // There are no children to visit
+ }
+
+ /**
+ * Return an element in the given [context] that represents the fact that the
+ * [firstElement] and [secondElement] conflict. (If the elements are the same,
+ * then one of the two will be returned directly.)
+ */
+ static Element fromElements(
+ AnalysisContext context, Element firstElement, Element secondElement) {
+ Set<Element> sdkElements = new HashSet<Element>.identity();
+ Set<Element> nonSdkElements = new HashSet<Element>.identity();
+ void add(Element element) {
+ if (element != null) {
+ if (element is MultiplyDefinedElementImpl) {
+ sdkElements.addAll(element.sdkElements);
+ nonSdkElements.addAll(element.nonSdkElements);
+ } else if (element.library.isInSdk) {
+ sdkElements.add(element);
+ } else {
+ nonSdkElements.add(element);
+ }
+ }
+ }
+
+ add(firstElement);
+ add(secondElement);
+ int nonSdkCount = nonSdkElements.length;
+ if (nonSdkCount == 0) {
+ int sdkCount = sdkElements.length;
+ if (sdkCount == 0) {
+ return null;
+ } else if (sdkCount == 1) {
+ return sdkElements.first;
+ }
+ } else if (nonSdkCount == 1) {
+ return nonSdkElements.first;
+ }
+ return new MultiplyDefinedElementImpl(
+ context,
+ sdkElements.toList(growable: false),
+ nonSdkElements.toList(growable: false));
+ }
+}
+
+/**
+ * A [MethodElementImpl], with the additional information of a list of
+ * [ExecutableElement]s from which this element was composed.
+ */
+class MultiplyInheritedMethodElementImpl extends MethodElementImpl
+ implements MultiplyInheritedExecutableElement {
+ /**
+ * A list the array of executable elements that were used to compose this
+ * element.
+ */
+ List<ExecutableElement> _elements = MethodElement.EMPTY_LIST;
+
+ MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) {
+ synthetic = true;
+ }
+
+ @override
+ List<ExecutableElement> get inheritedElements => _elements;
+
+ void set inheritedElements(List<ExecutableElement> elements) {
+ this._elements = elements;
+ }
+}
+
+/**
+ * A [PropertyAccessorElementImpl], with the additional information of a list of
+ * [ExecutableElement]s from which this element was composed.
+ */
+class MultiplyInheritedPropertyAccessorElementImpl
+ extends PropertyAccessorElementImpl
+ implements MultiplyInheritedExecutableElement {
+ /**
+ * A list the array of executable elements that were used to compose this
+ * element.
+ */
+ List<ExecutableElement> _elements = PropertyAccessorElement.EMPTY_LIST;
+
+ MultiplyInheritedPropertyAccessorElementImpl(Identifier name)
+ : super.forNode(name) {
+ synthetic = true;
+ }
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
+
+ @override
+ List<ExecutableElement> get inheritedElements => _elements;
+
+ void set inheritedElements(List<ExecutableElement> elements) {
+ this._elements = elements;
+ }
+}
+
+/**
+ * A [VariableElementImpl], which is not a parameter.
+ */
+abstract class NonParameterVariableElementImpl extends VariableElementImpl {
+ /**
+ * The unlinked representation of the variable in the summary.
+ */
+ final UnlinkedVariable _unlinkedVariable;
+
+ /**
+ * Initialize a newly created variable element to have the given [name] and
+ * [offset].
+ */
+ NonParameterVariableElementImpl(String name, int offset)
+ : _unlinkedVariable = null,
+ super(name, offset);
+
+ /**
+ * Initialize a newly created variable element to have the given [name].
+ */
+ NonParameterVariableElementImpl.forNode(Identifier name)
+ : _unlinkedVariable = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ NonParameterVariableElementImpl.forSerialized(
+ this._unlinkedVariable, ElementImpl enclosingElement)
+ : super.forSerialized(enclosingElement);
+
+ @override
+ int get codeLength {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ void set const3(bool isConst) {
+ assert(_unlinkedVariable == null);
+ super.const3 = isConst;
+ }
+
+ @override
+ String get documentationComment {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable?.documentationComment?.text;
+ }
+ return super.documentationComment;
+ }
+
+ @override
+ void set final2(bool isFinal) {
+ assert(_unlinkedVariable == null);
+ super.final2 = isFinal;
+ }
+
+ @override
+ bool get hasImplicitType {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.type == null;
+ }
+ return super.hasImplicitType;
+ }
+
+ @override
+ void set hasImplicitType(bool hasImplicitType) {
+ assert(_unlinkedVariable == null);
+ super.hasImplicitType = hasImplicitType;
+ }
+
+ @override
+ FunctionElement get initializer {
+ if (_unlinkedVariable != null && _initializer == null) {
+ UnlinkedExecutable unlinkedInitializer = _unlinkedVariable.initializer;
+ if (unlinkedInitializer != null) {
+ _initializer = new FunctionElementImpl.forSerialized(
+ unlinkedInitializer, this)..synthetic = true;
+ } else {
+ return null;
+ }
+ }
+ return super.initializer;
+ }
+
+ /**
+ * Set the function representing this variable's initializer to the given
+ * [function].
+ */
+ void set initializer(FunctionElement function) {
+ assert(_unlinkedVariable == null);
+ super.initializer = function;
+ }
+
+ @override
+ bool get isConst {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.isConst;
+ }
+ return super.isConst;
+ }
+
+ @override
+ bool get isFinal {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.isFinal;
+ }
+ return super.isFinal;
+ }
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedVariable != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedVariable.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ String get name {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedVariable != null) {
+ return _unlinkedVariable.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ DartType get type {
+ if (_unlinkedVariable != null && _type == null) {
+ _type = enclosingUnit.resynthesizerContext.resolveLinkedType(
+ _unlinkedVariable.inferredTypeSlot, typeParameterContext) ??
+ enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_unlinkedVariable.type, typeParameterContext);
+ }
+ return super.type;
+ }
+
+ void set type(DartType type) {
+ assert(_unlinkedVariable == null);
+ _type = type;
+ }
+
+ /**
+ * Subclasses need this getter, see [ConstVariableElement._unlinkedConst].
+ */
+ UnlinkedConst get _unlinkedConst => _unlinkedVariable?.initializer?.bodyExpr;
+}
+
+/**
+ * A concrete implementation of a [ParameterElement].
+ */
+class ParameterElementImpl extends VariableElementImpl
+ with ParameterElementMixin
+ implements ParameterElement {
+ /**
+ * The unlinked representation of the parameter in the summary.
+ */
+ final UnlinkedParam _unlinkedParam;
+
+ /**
+ * A list containing all of the parameters defined by this parameter element.
+ * There will only be parameters if this parameter is a function typed
+ * parameter.
+ */
+ List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST;
+
+ /**
+ * A list containing all of the type parameters defined for this parameter
+ * element. There will only be parameters if this parameter is a function
+ * typed parameter.
+ */
+ List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
+
+ /**
+ * The kind of this parameter.
+ */
+ ParameterKind _parameterKind;
+
+ /**
+ * The Dart code of the default value.
+ */
+ String _defaultValueCode;
+
+ /**
+ * The offset to the beginning of the visible range for this element.
+ */
+ int _visibleRangeOffset = 0;
+
+ /**
+ * The length of the visible range for this element, or `-1` if this element
+ * does not have a visible range.
+ */
+ int _visibleRangeLength = -1;
+
+ bool _inheritsCovariant = false;
+
+ /**
+ * Initialize a newly created parameter element to have the given [name] and
+ * [nameOffset].
+ */
+ ParameterElementImpl(String name, int nameOffset)
+ : _unlinkedParam = null,
+ super(name, nameOffset);
+
+ /**
+ * Initialize a newly created parameter element to have the given [name].
+ */
+ ParameterElementImpl.forNode(Identifier name)
+ : _unlinkedParam = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ParameterElementImpl.forSerialized(
+ this._unlinkedParam, ElementImpl enclosingElement)
+ : super.forSerialized(enclosingElement);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ factory ParameterElementImpl.forSerializedFactory(
+ UnlinkedParam unlinkedParameter, ElementImpl enclosingElement,
+ {bool synthetic: false}) {
+ ParameterElementImpl element;
+ if (unlinkedParameter.isInitializingFormal) {
+ if (unlinkedParameter.kind == UnlinkedParamKind.required) {
+ element = new FieldFormalParameterElementImpl.forSerialized(
+ unlinkedParameter, enclosingElement);
+ } else {
+ element = new DefaultFieldFormalParameterElementImpl.forSerialized(
+ unlinkedParameter, enclosingElement);
+ }
+ } else {
+ if (unlinkedParameter.kind == UnlinkedParamKind.required) {
+ element = new ParameterElementImpl.forSerialized(
+ unlinkedParameter, enclosingElement);
+ } else {
+ element = new DefaultParameterElementImpl.forSerialized(
+ unlinkedParameter, enclosingElement);
+ }
+ }
+ element.synthetic = synthetic;
+ return element;
+ }
+
+ /**
+ * Creates a synthetic parameter with [name], [type] and [kind].
+ */
+ factory ParameterElementImpl.synthetic(
+ String name, DartType type, ParameterKind kind) {
+ ParameterElementImpl element = new ParameterElementImpl(name, -1);
+ element.type = type;
+ element.synthetic = true;
+ element.parameterKind = kind;
+ return element;
+ }
+
+ @override
+ int get codeLength {
+ if (_unlinkedParam != null) {
+ return _unlinkedParam.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedParam != null) {
+ return _unlinkedParam.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ void set const3(bool isConst) {
+ assert(_unlinkedParam == null);
+ super.const3 = isConst;
+ }
+
+ @override
+ String get defaultValueCode {
+ if (_unlinkedParam != null) {
+ if (_unlinkedParam.initializer?.bodyExpr == null) {
+ return null;
+ }
+ return _unlinkedParam.defaultValueCode;
+ }
+ return _defaultValueCode;
+ }
+
+ /**
+ * Set Dart code of the default value.
+ */
+ void set defaultValueCode(String defaultValueCode) {
+ assert(_unlinkedParam == null);
+ this._defaultValueCode = StringUtilities.intern(defaultValueCode);
+ }
+
+ @override
+ void set final2(bool isFinal) {
+ assert(_unlinkedParam == null);
+ super.final2 = isFinal;
+ }
+
+ @override
+ bool get hasImplicitType {
+ if (_unlinkedParam != null) {
+ return _unlinkedParam.type == null;
+ }
+ return super.hasImplicitType;
+ }
+
+ @override
+ void set hasImplicitType(bool hasImplicitType) {
+ assert(_unlinkedParam == null);
+ super.hasImplicitType = hasImplicitType;
+ }
+
+ /**
+ * True if this parameter inherits from a covariant parameter. This happens
+ * when it overrides a method in a supertype that has a corresponding
+ * covariant parameter.
+ */
+ bool get inheritsCovariant {
+ if (_unlinkedParam != null) {
+ return enclosingUnit.resynthesizerContext
+ .inheritsCovariant(_unlinkedParam.inheritsCovariantSlot);
+ } else {
+ return _inheritsCovariant;
+ }
+ }
+
+ /**
+ * Record whether or not this parameter inherits from a covariant parameter.
+ */
+ void set inheritsCovariant(bool value) {
+ assert(_unlinkedParam == null);
+ _inheritsCovariant = value;
+ }
+
+ @override
+ FunctionElement get initializer {
+ if (_unlinkedParam != null && _initializer == null) {
+ UnlinkedExecutable unlinkedInitializer = _unlinkedParam.initializer;
+ if (unlinkedInitializer != null) {
+ _initializer = new FunctionElementImpl.forSerialized(
+ unlinkedInitializer, this)..synthetic = true;
+ } else {
+ return null;
+ }
+ }
+ return super.initializer;
+ }
+
+ /**
+ * Set the function representing this variable's initializer to the given
+ * [function].
+ */
+ void set initializer(FunctionElement function) {
+ assert(_unlinkedParam == null);
+ super.initializer = function;
+ }
+
+ @override
+ bool get isConst {
+ if (_unlinkedParam != null) {
+ return false;
+ }
+ return super.isConst;
+ }
+
+ @override
+ bool get isCovariant {
+ if (inheritsCovariant) {
+ return true;
+ }
+ for (ElementAnnotationImpl annotation in metadata) {
+ if (annotation.isCovariant) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isFinal {
+ if (_unlinkedParam != null) {
+ return false;
+ }
+ return super.isFinal;
+ }
+
+ @override
+ bool get isInitializingFormal => false;
+
+ @override
+ bool get isPotentiallyMutatedInClosure => true;
+
+ @override
+ bool get isPotentiallyMutatedInScope => true;
+
+ @override
+ ElementKind get kind => ElementKind.PARAMETER;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedParam != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedParam.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ String get name {
+ if (_unlinkedParam != null) {
+ return _unlinkedParam.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedParam != null) {
+ if (isSynthetic) {
+ return -1;
+ }
+ return _unlinkedParam.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ ParameterKind get parameterKind {
+ if (_unlinkedParam != null && _parameterKind == null) {
+ switch (_unlinkedParam.kind) {
+ case UnlinkedParamKind.named:
+ _parameterKind = ParameterKind.NAMED;
+ break;
+ case UnlinkedParamKind.positional:
+ _parameterKind = ParameterKind.POSITIONAL;
+ break;
+ case UnlinkedParamKind.required:
+ _parameterKind = ParameterKind.REQUIRED;
+ break;
+ }
+ }
+ return _parameterKind;
+ }
+
+ void set parameterKind(ParameterKind parameterKind) {
+ assert(_unlinkedParam == null);
+ _parameterKind = parameterKind;
+ }
+
+ @override
+ List<ParameterElement> get parameters {
+ _resynthesizeTypeAndParameters();
+ return _parameters;
+ }
+
+ /**
+ * Set the parameters defined by this executable element to the given
+ * [parameters].
+ */
+ void set parameters(List<ParameterElement> parameters) {
+ for (ParameterElement parameter in parameters) {
+ (parameter as ParameterElementImpl).enclosingElement = this;
+ }
+ this._parameters = parameters;
+ }
+
+ @override
+ DartType get type {
+ _resynthesizeTypeAndParameters();
+ return super.type;
+ }
+
+ @override
+ List<TypeParameterElement> get typeParameters => _typeParameters;
+
+ /**
+ * Set the type parameters defined by this parameter element to the given
+ * [typeParameters].
+ */
+ void set typeParameters(List<TypeParameterElement> typeParameters) {
+ for (TypeParameterElement parameter in typeParameters) {
+ (parameter as TypeParameterElementImpl).enclosingElement = this;
+ }
+ this._typeParameters = typeParameters;
+ }
+
+ @override
+ SourceRange get visibleRange {
+ if (_unlinkedParam != null) {
+ if (_unlinkedParam.visibleLength == 0) {
+ return null;
+ }
+ return new SourceRange(
+ _unlinkedParam.visibleOffset, _unlinkedParam.visibleLength);
+ }
+ if (_visibleRangeLength < 0) {
+ return null;
+ }
+ return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
+ }
+
+ /**
+ * Subclasses need this getter, see [ConstVariableElement._unlinkedConst].
+ */
+ UnlinkedConst get _unlinkedConst => _unlinkedParam?.initializer?.bodyExpr;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ String left = "";
+ String right = "";
+ while (true) {
+ if (parameterKind == ParameterKind.NAMED) {
+ left = "{";
+ right = "}";
+ } else if (parameterKind == ParameterKind.POSITIONAL) {
+ left = "[";
+ right = "]";
+ } else if (parameterKind == ParameterKind.REQUIRED) {}
+ break;
+ }
+ buffer.write(left);
+ appendToWithoutDelimiters(buffer);
+ buffer.write(right);
+ }
+
+ @override
+ FormalParameter computeNode() =>
+ getNodeMatching((node) => node is FormalParameter);
+
+ @override
+ ElementImpl getChild(String identifier) {
+ for (ParameterElement parameter in _parameters) {
+ ParameterElementImpl parameterImpl = parameter;
+ if (parameterImpl.identifier == identifier) {
+ return parameterImpl;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Set the visible range for this element to the range starting at the given
+ * [offset] with the given [length].
+ */
+ void setVisibleRange(int offset, int length) {
+ assert(_unlinkedParam == null);
+ _visibleRangeOffset = offset;
+ _visibleRangeLength = length;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(parameters, visitor);
+ }
+
+ /**
+ * If this element is resynthesized, and its type and parameters have not
+ * been build yet, build them and remember in the corresponding fields.
+ */
+ void _resynthesizeTypeAndParameters() {
+ if (_unlinkedParam != null && _type == null) {
+ if (_unlinkedParam.isFunctionTyped) {
+ CompilationUnitElementImpl enclosingUnit = this.enclosingUnit;
+ FunctionElementImpl parameterTypeElement =
+ new FunctionElementImpl_forFunctionTypedParameter(
+ enclosingUnit, this);
+ if (!isSynthetic) {
+ parameterTypeElement.enclosingElement = this;
+ }
+ List<ParameterElement> subParameters = ParameterElementImpl
+ .resynthesizeList(_unlinkedParam.parameters, this,
+ synthetic: isSynthetic);
+ if (isSynthetic) {
+ parameterTypeElement.parameters = subParameters;
+ } else {
+ _parameters = subParameters;
+ parameterTypeElement.shareParameters(subParameters);
+ }
+ parameterTypeElement.returnType = enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_unlinkedParam.type, typeParameterContext);
+ FunctionTypeImpl parameterType =
+ new FunctionTypeImpl.elementWithNameAndArgs(parameterTypeElement,
+ null, typeParameterContext.allTypeParameterTypes, false);
+ parameterTypeElement.type = parameterType;
+ _type = parameterType;
+ } else {
+ _type = enclosingUnit.resynthesizerContext.resolveLinkedType(
+ _unlinkedParam.inferredTypeSlot, typeParameterContext) ??
+ enclosingUnit.resynthesizerContext
+ .resolveTypeRef(_unlinkedParam.type, typeParameterContext);
+ }
+ }
+ }
+
+ /**
+ * Create and return [ParameterElement]s for the given [unlinkedParameters].
+ */
+ static List<ParameterElement> resynthesizeList(
+ List<UnlinkedParam> unlinkedParameters, ElementImpl enclosingElement,
+ {bool synthetic: false}) {
+ int length = unlinkedParameters.length;
+ if (length != 0) {
+ List<ParameterElement> parameters = new List<ParameterElement>(length);
+ for (int i = 0; i < length; i++) {
+ parameters[i] = new ParameterElementImpl.forSerializedFactory(
+ unlinkedParameters[i], enclosingElement,
+ synthetic: synthetic);
+ }
+ return parameters;
+ } else {
+ return const <ParameterElement>[];
+ }
+ }
+}
+
+/**
+ * The parameter of an implicit setter.
+ */
+class ParameterElementImpl_ofImplicitSetter extends ParameterElementImpl {
+ final PropertyAccessorElementImpl_ImplicitSetter setter;
+
+ ParameterElementImpl_ofImplicitSetter(
+ PropertyAccessorElementImpl_ImplicitSetter setter)
+ : setter = setter,
+ super('_${setter.variable.name}', setter.variable.nameOffset) {
+ enclosingElement = setter;
+ synthetic = true;
+ parameterKind = ParameterKind.REQUIRED;
+ }
+
+ @override
+ bool get isCovariant {
+ if (inheritsCovariant) {
+ return true;
+ }
+ for (ElementAnnotationImpl annotation in setter.variable.metadata) {
+ if (annotation.isCovariant) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ DartType get type => setter.variable.type;
+
+ @override
+ void set type(DartType type) {
+ assert(false); // Should never be called.
+ }
+}
+
+/**
+ * A mixin that provides a common implementation for methods defined in
+ * [ParameterElement].
+ */
+abstract class ParameterElementMixin implements ParameterElement {
+ @override
+ void appendToWithoutDelimiters(StringBuffer buffer) {
+ buffer.write(type);
+ buffer.write(" ");
+ buffer.write(displayName);
+ if (defaultValueCode != null) {
+ if (parameterKind == ParameterKind.NAMED) {
+ buffer.write(": ");
+ }
+ if (parameterKind == ParameterKind.POSITIONAL) {
+ buffer.write(" = ");
+ }
+ buffer.write(defaultValueCode);
+ }
+ }
+}
+
+/**
+ * A concrete implementation of a [PrefixElement].
+ */
+class PrefixElementImpl extends ElementImpl implements PrefixElement {
+ /**
+ * The unlinked representation of the import in the summary.
+ */
+ final UnlinkedImport _unlinkedImport;
+
+ /**
+ * Initialize a newly created method element to have the given [name] and
+ * [nameOffset].
+ */
+ PrefixElementImpl(String name, int nameOffset)
+ : _unlinkedImport = null,
+ super(name, nameOffset);
+
+ /**
+ * Initialize a newly created prefix element to have the given [name].
+ */
+ PrefixElementImpl.forNode(Identifier name)
+ : _unlinkedImport = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ PrefixElementImpl.forSerialized(
+ this._unlinkedImport, LibraryElementImpl enclosingLibrary)
+ : super.forSerialized(enclosingLibrary);
+
+ @override
+ String get displayName => name;
+
+ @override
+ LibraryElement get enclosingElement =>
+ super.enclosingElement as LibraryElement;
+
+ @override
+ String get identifier => "_${super.identifier}";
+
+ @override
+ List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
+
+ @override
+ ElementKind get kind => ElementKind.PREFIX;
+
+ @override
+ String get name {
+ if (_unlinkedImport != null) {
+ if (_name == null) {
+ LibraryElementImpl library = enclosingElement as LibraryElementImpl;
+ int prefixId = _unlinkedImport.prefixReference;
+ return _name = library._unlinkedDefiningUnit.references[prefixId].name;
+ }
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedImport != null) {
+ return _unlinkedImport.prefixOffset;
+ }
+ return super.nameOffset;
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitPrefixElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write("as ");
+ super.appendTo(buffer);
+ }
+}
+
+/**
+ * A concrete implementation of a [PropertyAccessorElement].
+ */
+class PropertyAccessorElementImpl extends ExecutableElementImpl
+ implements PropertyAccessorElement {
+ /**
+ * The variable associated with this accessor.
+ */
+ PropertyInducingElement variable;
+
+ /**
+ * Initialize a newly created property accessor element to have the given
+ * [name] and [offset].
+ */
+ PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created property accessor element to have the given
+ * [name].
+ */
+ PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ PropertyAccessorElementImpl.forSerialized(
+ UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement)
+ : super.forSerialized(serializedExecutable, enclosingElement);
+
+ /**
+ * Initialize a newly created synthetic property accessor element to be
+ * associated with the given [variable].
+ */
+ PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
+ : super(variable.name, variable.nameOffset) {
+ this.variable = variable;
+ static = variable.isStatic;
+ synthetic = true;
+ }
+
+ /**
+ * Set whether this accessor is abstract.
+ */
+ void set abstract(bool isAbstract) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
+
+ @override
+ List<TypeParameterType> get allEnclosingTypeParameterTypes {
+ if (isStatic) {
+ return const <TypeParameterType>[];
+ }
+ return super.allEnclosingTypeParameterTypes;
+ }
+
+ @override
+ PropertyAccessorElement get correspondingGetter {
+ if (isGetter || variable == null) {
+ return null;
+ }
+ return variable.getter;
+ }
+
+ @override
+ PropertyAccessorElement get correspondingSetter {
+ if (isSetter || variable == null) {
+ return null;
+ }
+ return variable.setter;
+ }
+
+ @override
+ String get displayName {
+ if (serializedExecutable != null && isSetter) {
+ String name = serializedExecutable.name;
+ assert(name.endsWith('='));
+ return name.substring(0, name.length - 1);
+ }
+ return super.displayName;
+ }
+
+ @override
+ TypeParameterizedElementMixin get enclosingTypeParameterContext {
+ return (enclosingElement as ElementImpl).typeParameterContext;
+ }
+
+ /**
+ * Set whether this accessor is a getter.
+ */
+ void set getter(bool isGetter) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.GETTER, isGetter);
+ }
+
+ @override
+ String get identifier {
+ String name = displayName;
+ String suffix = isGetter ? "?" : "=";
+ return "$name$suffix";
+ }
+
+ @override
+ bool get isGetter {
+ if (serializedExecutable != null) {
+ return serializedExecutable.kind == UnlinkedExecutableKind.getter;
+ }
+ return hasModifier(Modifier.GETTER);
+ }
+
+ @override
+ bool get isSetter {
+ if (serializedExecutable != null) {
+ return serializedExecutable.kind == UnlinkedExecutableKind.setter;
+ }
+ return hasModifier(Modifier.SETTER);
+ }
+
+ @override
+ bool get isStatic {
+ if (serializedExecutable != null) {
+ return serializedExecutable.isStatic ||
+ variable is TopLevelVariableElement;
+ }
+ return hasModifier(Modifier.STATIC);
+ }
+
+ @override
+ ElementKind get kind {
+ if (isGetter) {
+ return ElementKind.GETTER;
+ }
+ return ElementKind.SETTER;
+ }
+
+ @override
+ String get name {
+ if (serializedExecutable != null) {
+ return serializedExecutable.name;
+ }
+ if (isSetter) {
+ return "${super.name}=";
+ }
+ return super.name;
+ }
+
+ /**
+ * Set whether this accessor is a setter.
+ */
+ void set setter(bool isSetter) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.SETTER, isSetter);
+ }
+
+ /**
+ * Set whether this accessor is static.
+ */
+ void set static(bool isStatic) {
+ assert(serializedExecutable == null);
+ setModifier(Modifier.STATIC, isStatic);
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write(isGetter ? "get " : "set ");
+ buffer.write(variable.displayName);
+ super.appendTo(buffer);
+ }
+
+ @override
+ AstNode computeNode() {
+ if (isSynthetic) {
+ return null;
+ }
+ if (enclosingElement is ClassElement) {
+ return getNodeMatching((node) => node is MethodDeclaration);
+ } else if (enclosingElement is CompilationUnitElement) {
+ return getNodeMatching((node) => node is FunctionDeclaration);
+ }
+ return null;
+ }
+}
+
+/**
+ * Implicit getter for a [PropertyInducingElementImpl].
+ */
+class PropertyAccessorElementImpl_ImplicitGetter
+ extends PropertyAccessorElementImpl {
+ /**
+ * Create the implicit getter and bind it to the [property].
+ */
+ PropertyAccessorElementImpl_ImplicitGetter(
+ PropertyInducingElementImpl property)
+ : super.forVariable(property) {
+ property.getter = this;
+ enclosingElement = property.enclosingElement;
+ }
+
+ @override
+ bool get hasImplicitReturnType => variable.hasImplicitType;
+
+ @override
+ bool get isGetter => true;
+
+ @override
+ DartType get returnType => variable.type;
+
+ @override
+ void set returnType(DartType returnType) {
+ assert(false); // Should never be called.
+ }
+
+ @override
+ FunctionType get type {
+ return _type ??= new FunctionTypeImpl(this);
+ }
+
+ @override
+ void set type(FunctionType type) {
+ assert(false); // Should never be called.
+ }
+}
+
+/**
+ * Implicit setter for a [PropertyInducingElementImpl].
+ */
+class PropertyAccessorElementImpl_ImplicitSetter
+ extends PropertyAccessorElementImpl {
+ /**
+ * Create the implicit setter and bind it to the [property].
+ */
+ PropertyAccessorElementImpl_ImplicitSetter(
+ PropertyInducingElementImpl property)
+ : super.forVariable(property) {
+ property.setter = this;
+ }
+
+ @override
+ bool get isSetter => true;
+
+ @override
+ List<ParameterElement> get parameters {
+ return _parameters ??= <ParameterElement>[
+ new ParameterElementImpl_ofImplicitSetter(this)
+ ];
+ }
+
+ @override
+ DartType get returnType => VoidTypeImpl.instance;
+
+ @override
+ void set returnType(DartType returnType) {
+ assert(false); // Should never be called.
+ }
+
+ @override
+ FunctionType get type {
+ return _type ??= new FunctionTypeImpl(this);
+ }
+
+ @override
+ void set type(FunctionType type) {
+ assert(false); // Should never be called.
+ }
+}
+
+/**
+ * A concrete implementation of a [PropertyInducingElement].
+ */
+abstract class PropertyInducingElementImpl
+ extends NonParameterVariableElementImpl implements PropertyInducingElement {
+ /**
+ * The getter associated with this element.
+ */
+ PropertyAccessorElement getter;
+
+ /**
+ * The setter associated with this element, or `null` if the element is
+ * effectively `final` and therefore does not have a setter associated with
+ * it.
+ */
+ PropertyAccessorElement setter;
+
+ /**
+ * The propagated type of this variable, or `null` if type propagation has not
+ * been performed.
+ */
+ DartType _propagatedType;
+
+ /**
+ * Initialize a newly created synthetic element to have the given [name] and
+ * [offset].
+ */
+ PropertyInducingElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created element to have the given [name].
+ */
+ PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ PropertyInducingElementImpl.forSerialized(
+ UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedVariable, enclosingElement);
+
+ @override
+ DartType get propagatedType {
+ if (_unlinkedVariable != null && _propagatedType == null) {
+ _propagatedType = enclosingUnit.resynthesizerContext.resolveLinkedType(
+ _unlinkedVariable.propagatedTypeSlot, typeParameterContext);
+ }
+ return _propagatedType;
+ }
+
+ void set propagatedType(DartType propagatedType) {
+ assert(_unlinkedVariable == null);
+ _propagatedType = propagatedType;
+ }
+}
+
+/**
+ * The context in which elements are resynthesized.
+ */
+abstract class ResynthesizerContext {
+ /**
+ * Build [ElementAnnotationImpl] for the given [UnlinkedConst].
+ */
+ ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc);
+
+ /**
+ * Build [Expression] for the given [UnlinkedConst].
+ */
+ Expression buildExpression(ElementImpl context, UnlinkedConst uc);
+
+ /**
+ * Build explicit top-level property accessors.
+ */
+ UnitExplicitTopLevelAccessors buildTopLevelAccessors();
+
+ /**
+ * Build explicit top-level variables.
+ */
+ UnitExplicitTopLevelVariables buildTopLevelVariables();
+
+ /**
+ * Return `true` if the given parameter [slot] inherits `@covariant` behavior.
+ */
+ bool inheritsCovariant(int slot);
+
+ /**
+ * Return `true` if the given const constructor [slot] is a part of a cycle.
+ */
+ bool isInConstCycle(int slot);
+
+ /**
+ * Resolve an [EntityRef] into a constructor. If the reference is
+ * unresolved, return `null`.
+ */
+ ConstructorElement resolveConstructorRef(
+ TypeParameterizedElementMixin typeParameterContext, EntityRef entry);
+
+ /**
+ * Build the appropriate [DartType] object corresponding to a slot id in the
+ * [LinkedUnit.types] table.
+ */
+ DartType resolveLinkedType(
+ int slot, TypeParameterizedElementMixin typeParameterContext);
+
+ /**
+ * Resolve an [EntityRef] into a type. If the reference is
+ * unresolved, return [DynamicTypeImpl.instance].
+ *
+ * TODO(paulberry): or should we have a class representing an
+ * unresolved type, for consistency with the full element model?
+ */
+ DartType resolveTypeRef(
+ EntityRef type, TypeParameterizedElementMixin typeParameterContext,
+ {bool defaultVoid: false, bool instantiateToBoundsAllowed: true});
+}
+
+/**
+ * A concrete implementation of a [ShowElementCombinator].
+ */
+class ShowElementCombinatorImpl implements ShowElementCombinator {
+ /**
+ * The unlinked representation of the combinator in the summary.
+ */
+ final UnlinkedCombinator _unlinkedCombinator;
+
+ /**
+ * The names that are to be made visible in the importing library if they are
+ * defined in the imported library.
+ */
+ List<String> _shownNames;
+
+ /**
+ * The offset of the character immediately following the last character of
+ * this node.
+ */
+ int _end = -1;
+
+ /**
+ * The offset of the 'show' keyword of this element.
+ */
+ int _offset = 0;
+
+ ShowElementCombinatorImpl() : _unlinkedCombinator = null;
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ ShowElementCombinatorImpl.forSerialized(this._unlinkedCombinator);
+
+ @override
+ int get end {
+ if (_unlinkedCombinator != null) {
+ return _unlinkedCombinator.end;
+ }
+ return _end;
+ }
+
+ void set end(int end) {
+ assert(_unlinkedCombinator == null);
+ _end = end;
+ }
+
+ @override
+ int get offset {
+ if (_unlinkedCombinator != null) {
+ return _unlinkedCombinator.offset;
+ }
+ return _offset;
+ }
+
+ void set offset(int offset) {
+ assert(_unlinkedCombinator == null);
+ _offset = offset;
+ }
+
+ @override
+ List<String> get shownNames {
+ if (_unlinkedCombinator != null) {
+ _shownNames ??= _unlinkedCombinator.shows.toList(growable: false);
+ }
+ return _shownNames ?? const <String>[];
+ }
+
+ void set shownNames(List<String> shownNames) {
+ assert(_unlinkedCombinator == null);
+ _shownNames = shownNames;
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write("show ");
+ int count = shownNames.length;
+ for (int i = 0; i < count; i++) {
+ if (i > 0) {
+ buffer.write(", ");
+ }
+ buffer.write(shownNames[i]);
+ }
+ return buffer.toString();
+ }
+}
+
+/**
+ * A concrete implementation of a [TopLevelVariableElement].
+ */
+class TopLevelVariableElementImpl extends PropertyInducingElementImpl
+ implements TopLevelVariableElement {
+ /**
+ * Initialize a newly created synthetic top-level variable element to have the
+ * given [name] and [offset].
+ */
+ TopLevelVariableElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created top-level variable element to have the given
+ * [name].
+ */
+ TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ TopLevelVariableElementImpl.forSerialized(
+ UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
+ : super.forSerialized(unlinkedVariable, enclosingElement);
+
+ @override
+ bool get isStatic => true;
+
+ @override
+ ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);
+
+ @override
+ VariableDeclaration computeNode() =>
+ getNodeMatching((node) => node is VariableDeclaration);
+}
+
+/**
+ * A concrete implementation of a [TypeParameterElement].
+ */
+class TypeParameterElementImpl extends ElementImpl
+ implements TypeParameterElement {
+ /**
+ * The unlinked representation of the type parameter in the summary.
+ */
+ final UnlinkedTypeParam _unlinkedTypeParam;
+
+ /**
+ * The number of type parameters whose scope overlaps this one, and which are
+ * declared earlier in the file.
+ *
+ * TODO(scheglov) make private?
+ */
+ final int nestingLevel;
+
+ /**
+ * The type defined by this type parameter.
+ */
+ TypeParameterType _type;
+
+ /**
+ * The type representing the bound associated with this parameter, or `null`
+ * if this parameter does not have an explicit bound.
+ */
+ DartType _bound;
+
+ /**
+ * Initialize a newly created method element to have the given [name] and
+ * [offset].
+ */
+ TypeParameterElementImpl(String name, int offset)
+ : _unlinkedTypeParam = null,
+ nestingLevel = null,
+ super(name, offset);
+
+ /**
+ * Initialize a newly created type parameter element to have the given [name].
+ */
+ TypeParameterElementImpl.forNode(Identifier name)
+ : _unlinkedTypeParam = null,
+ nestingLevel = null,
+ super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ TypeParameterElementImpl.forSerialized(this._unlinkedTypeParam,
+ TypeParameterizedElementMixin enclosingElement, this.nestingLevel)
+ : super.forSerialized(enclosingElement);
+
+ /**
+ * Initialize a newly created synthetic type parameter element to have the
+ * given [name], and with [synthetic] set to true.
+ */
+ TypeParameterElementImpl.synthetic(String name)
+ : _unlinkedTypeParam = null,
+ nestingLevel = null,
+ super(name, -1) {
+ synthetic = true;
+ }
+
+ DartType get bound {
+ if (_unlinkedTypeParam != null) {
+ if (_unlinkedTypeParam.bound == null) {
+ return null;
+ }
+ return _bound ??= enclosingUnit.resynthesizerContext.resolveTypeRef(
+ _unlinkedTypeParam.bound, enclosingElement,
+ instantiateToBoundsAllowed: false);
+ }
+ return _bound;
+ }
+
+ void set bound(DartType bound) {
+ assert(_unlinkedTypeParam == null);
+ _bound = bound;
+ }
+
+ @override
+ int get codeLength {
+ if (_unlinkedTypeParam != null) {
+ return _unlinkedTypeParam.codeRange?.length;
+ }
+ return super.codeLength;
+ }
+
+ @override
+ int get codeOffset {
+ if (_unlinkedTypeParam != null) {
+ return _unlinkedTypeParam.codeRange?.offset;
+ }
+ return super.codeOffset;
+ }
+
+ @override
+ String get displayName => name;
+
+ @override
+ ElementKind get kind => ElementKind.TYPE_PARAMETER;
+
+ @override
+ List<ElementAnnotation> get metadata {
+ if (_unlinkedTypeParam != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedTypeParam.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
+ String get name {
+ if (_unlinkedTypeParam != null) {
+ return _unlinkedTypeParam.name;
+ }
+ return super.name;
+ }
+
+ @override
+ int get nameOffset {
+ if (_unlinkedTypeParam != null) {
+ return _unlinkedTypeParam.nameOffset;
+ }
+ return super.nameOffset;
+ }
+
+ TypeParameterType get type {
+ if (_unlinkedTypeParam != null) {
+ _type ??= new TypeParameterTypeImpl(this);
+ }
+ return _type;
+ }
+
+ void set type(TypeParameterType type) {
+ _type = type;
+ }
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write(displayName);
+ if (bound != null) {
+ buffer.write(" extends ");
+ buffer.write(bound);
+ }
+ }
+}
+
+/**
+ * Mixin representing an element which can have type parameters.
+ */
+abstract class TypeParameterizedElementMixin
+ implements TypeParameterizedElement, ElementImpl {
+ int _nestingLevel;
+ List<TypeParameterElement> _typeParameterElements;
+ List<TypeParameterType> _typeParameterTypes;
+ List<TypeParameterType> _allTypeParameterTypes;
+
+ /**
+ * Return all type parameter types of the element that encloses element.
+ * Not `null`, but might be empty for top-level and static class members.
+ */
+ List<TypeParameterType> get allEnclosingTypeParameterTypes {
+ return enclosingTypeParameterContext?.allTypeParameterTypes ??
+ const <TypeParameterType>[];
+ }
+
+ /**
+ * Return all type parameter types of this element.
+ */
+ List<TypeParameterType> get allTypeParameterTypes {
+ if (_allTypeParameterTypes == null) {
+ _allTypeParameterTypes = <TypeParameterType>[];
+ // The most logical order would be (enclosing, this).
+ // But we have to have it like this to be consistent with (inconsistent
+ // by itself) element builder for generic functions.
+ _allTypeParameterTypes.addAll(typeParameterTypes);
+ _allTypeParameterTypes.addAll(allEnclosingTypeParameterTypes);
+ }
+ return _allTypeParameterTypes;
+ }
+
+ /**
+ * Get the type parameter context enclosing this one, if any.
+ */
+ TypeParameterizedElementMixin get enclosingTypeParameterContext;
+
+ /**
+ * The unit in which this element is resynthesized.
+ */
+ CompilationUnitElementImpl get enclosingUnit;
+
+ /**
+ * Find out how many type parameters are in scope in this context.
+ */
+ int get typeParameterNestingLevel =>
+ _nestingLevel ??= unlinkedTypeParams.length +
+ (enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0);
+
+ List<TypeParameterElement> get typeParameters {
+ if (_typeParameterElements == null) {
+ int enclosingNestingLevel =
+ enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0;
+ int numTypeParameters = unlinkedTypeParams.length;
+ _typeParameterElements =
+ new List<TypeParameterElement>(numTypeParameters);
+ for (int i = 0; i < numTypeParameters; i++) {
+ _typeParameterElements[i] = new TypeParameterElementImpl.forSerialized(
+ unlinkedTypeParams[i], this, enclosingNestingLevel + i);
+ }
+ }
+ return _typeParameterElements;
+ }
+
+ /**
+ * Get a list of [TypeParameterType] objects corresponding to the
+ * element's type parameters.
+ */
+ List<TypeParameterType> get typeParameterTypes {
+ return _typeParameterTypes ??= typeParameters
+ .map((TypeParameterElement e) => e.type)
+ .toList(growable: false);
+ }
+
+ /**
+ * Get the [UnlinkedTypeParam]s representing the type parameters declared by
+ * this element.
+ *
+ * TODO(scheglov) make private after switching linker to Impl
+ */
+ List<UnlinkedTypeParam> get unlinkedTypeParams;
+
+ /**
+ * Convert the given [index] into a type parameter type.
+ */
+ TypeParameterType getTypeParameterType(int index) {
+ List<TypeParameterType> types = typeParameterTypes;
+ if (index <= types.length) {
+ return types[types.length - index];
+ } else if (enclosingTypeParameterContext != null) {
+ return enclosingTypeParameterContext
+ .getTypeParameterType(index - types.length);
+ } else {
+ // If we get here, it means that a summary contained a type parameter index
+ // that was out of range.
+ throw new RangeError('Invalid type parameter index');
+ }
+ }
+
+ /**
+ * Find out if the given [typeParameter] is in scope in this context.
+ */
+ bool isTypeParameterInScope(TypeParameterElement typeParameter) {
+ if (typeParameter.enclosingElement == this) {
+ return true;
+ } else if (enclosingTypeParameterContext != null) {
+ return enclosingTypeParameterContext
+ .isTypeParameterInScope(typeParameter);
+ } else {
+ return false;
+ }
+ }
+}
+
+/**
+ * Container with information about explicit top-level property accessors and
+ * corresponding implicit top-level variables.
+ */
+class UnitExplicitTopLevelAccessors {
+ final List<PropertyAccessorElementImpl> accessors =
+ <PropertyAccessorElementImpl>[];
+ final List<TopLevelVariableElementImpl> implicitVariables =
+ <TopLevelVariableElementImpl>[];
+}
+
+/**
+ * Container with information about explicit top-level variables and
+ * corresponding implicit top-level property accessors.
+ */
+class UnitExplicitTopLevelVariables {
+ final List<TopLevelVariableElementImpl> variables;
+ final List<PropertyAccessorElementImpl> implicitAccessors =
+ <PropertyAccessorElementImpl>[];
+
+ UnitExplicitTopLevelVariables(int numberOfVariables)
+ : variables = numberOfVariables != 0
+ ? new List<TopLevelVariableElementImpl>(numberOfVariables)
+ : const <TopLevelVariableElementImpl>[];
+}
+
+/**
+ * A concrete implementation of a [UriReferencedElement].
+ */
+abstract class UriReferencedElementImpl extends ElementImpl
+ implements UriReferencedElement {
+ /**
+ * The offset of the URI in the file, or `-1` if this node is synthetic.
+ */
+ int _uriOffset = -1;
+
+ /**
+ * The offset of the character immediately following the last character of
+ * this node's URI, or `-1` if this node is synthetic.
+ */
+ int _uriEnd = -1;
+
+ /**
+ * The URI that is specified by this directive.
+ */
+ String _uri;
+
+ /**
+ * Initialize a newly created import element to have the given [name] and
+ * [offset]. The offset may be `-1` if the element is synthetic.
+ */
+ UriReferencedElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
+ : super.forSerialized(enclosingElement);
+
+ /**
+ * Return the URI that is specified by this directive.
+ */
+ String get uri => _uri;
+
+ /**
+ * Set the URI that is specified by this directive to be the given [uri].
+ */
+ void set uri(String uri) {
+ _uri = uri;
+ }
+
+ /**
+ * Return the offset of the character immediately following the last character
+ * of this node's URI, or `-1` if this node is synthetic.
+ */
+ int get uriEnd => _uriEnd;
+
+ /**
+ * Set the offset of the character immediately following the last character of
+ * this node's URI to the given [offset].
+ */
+ void set uriEnd(int offset) {
+ _uriEnd = offset;
+ }
+
+ /**
+ * Return the offset of the URI in the file, or `-1` if this node is synthetic.
+ */
+ int get uriOffset => _uriOffset;
+
+ /**
+ * Set the offset of the URI in the file to the given [offset].
+ */
+ void set uriOffset(int offset) {
+ _uriOffset = offset;
+ }
+
+ String _selectUri(
+ String defaultUri, List<UnlinkedConfiguration> configurations) {
+ for (UnlinkedConfiguration configuration in configurations) {
+ if (context.declaredVariables.get(configuration.name) ==
+ configuration.value) {
+ return configuration.uri;
+ }
+ }
+ return defaultUri;
+ }
+}
+
+/**
+ * A concrete implementation of a [VariableElement].
+ */
+abstract class VariableElementImpl extends ElementImpl
+ implements VariableElement {
+ /**
+ * The declared type of this variable.
+ */
+ DartType _type;
+
+ /**
+ * A synthetic function representing this variable's initializer, or `null` if
+ * this variable does not have an initializer.
+ */
+ FunctionElement _initializer;
+
+ /**
+ * Initialize a newly created variable element to have the given [name] and
+ * [offset].
+ */
+ VariableElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize a newly created variable element to have the given [name].
+ */
+ VariableElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ VariableElementImpl.forSerialized(ElementImpl enclosingElement)
+ : super.forSerialized(enclosingElement);
+
+ /**
+ * Set whether this variable is const.
+ */
+ void set const3(bool isConst) {
+ setModifier(Modifier.CONST, isConst);
+ }
+
+ /**
+ * 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.
+ */
+ Expression get constantInitializer => null;
+
+ @override
+ DartObject get constantValue => evaluationResult?.value;
+
+ @override
+ String get displayName => name;
+
+ /**
+ * Return the result of evaluating this variable's initializer as a
+ * compile-time constant expression, or `null` if this variable is not a
+ * 'const' variable, if it does not have an initializer, or if the compilation
+ * unit containing the variable has not been resolved.
+ */
+ EvaluationResultImpl get evaluationResult => null;
+
+ /**
+ * Set the result of evaluating this variable's initializer as a compile-time
+ * constant expression to the given [result].
+ */
+ void set evaluationResult(EvaluationResultImpl result) {
+ throw new StateError(
+ "Invalid attempt to set a compile-time constant result");
+ }
+
+ /**
+ * Set whether this variable is final.
+ */
+ void set final2(bool isFinal) {
+ setModifier(Modifier.FINAL, isFinal);
+ }
+
+ @override
+ bool get hasImplicitType {
+ return hasModifier(Modifier.IMPLICIT_TYPE);
+ }
+
+ /**
+ * Set whether this variable element has an implicit type.
+ */
+ void set hasImplicitType(bool hasImplicitType) {
+ setModifier(Modifier.IMPLICIT_TYPE, hasImplicitType);
+ }
+
+ @override
+ FunctionElement get initializer => _initializer;
+
+ /**
+ * Set the function representing this variable's initializer to the given
+ * [function].
+ */
+ void set initializer(FunctionElement function) {
+ if (function != null) {
+ (function as FunctionElementImpl).enclosingElement = this;
+ }
+ this._initializer = function;
+ }
+
+ @override
+ bool get isConst {
+ return hasModifier(Modifier.CONST);
+ }
+
+ @override
+ bool get isFinal {
+ return hasModifier(Modifier.FINAL);
+ }
+
+ @override
+ bool get isPotentiallyMutatedInClosure => false;
+
+ @override
+ bool get isPotentiallyMutatedInScope => false;
+
+ @override
+ bool get isStatic => hasModifier(Modifier.STATIC);
+
+ @override
+ DartType get type => _type;
+
+ void set type(DartType type) {
+ _type = type;
+ }
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write(type);
+ buffer.write(" ");
+ buffer.write(displayName);
+ }
+
+ @override
+ DartObject computeConstantValue() => null;
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ _initializer?.accept(visitor);
+ }
+}
+
+/**
+ * A visitor that visit all the elements recursively and fill the given [map].
+ */
+class _BuildOffsetToElementMap extends GeneralizingElementVisitor {
+ final Map<int, Element> map;
+
+ _BuildOffsetToElementMap(this.map);
+
+ @override
+ void visitElement(Element element) {
+ int offset = element.nameOffset;
+ if (offset != -1) {
+ map[offset] = element;
+ }
+ super.visitElement(element);
+ }
+}
« no previous file with comments | « packages/analyzer/lib/src/dart/element/builder.dart ('k') | packages/analyzer/lib/src/dart/element/handle.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698