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

Unified Diff: pkg/analyzer/lib/src/generated/element.dart

Issue 259773005: New analyzer snapshot. Sorted unit members. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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
« no previous file with comments | « pkg/analyzer/lib/src/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/error.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/element.dart
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 4365e97d0bef909cd126ed4f93ef0a133d5b1274..cab0aaed1ef8d6968fac0568de52c523b407d3bf 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -21,5099 +21,5668 @@ import 'constant.dart' show EvaluationResultImpl;
import 'utilities_dart.dart';
/**
- * The interface `ClassElement` defines the behavior of elements that represent a class.
+ * Information about Angular application.
*/
-abstract class ClassElement implements Element {
+class AngularApplication {
+ final Source entryPoint;
+
+ final Set<Source> _librarySources;
+
+ final List<AngularElement> elements;
+
+ final List<Source> elementSources;
+
+ AngularApplication(this.entryPoint, this._librarySources, this.elements, this.elementSources);
+
/**
- * Return an array containing all of the accessors (getters and setters) declared in this class.
- *
- * @return the accessors declared in this class
+ * Checks if this application depends on the library with the given [Source].
*/
- List<PropertyAccessorElement> get accessors;
+ bool dependsOn(Source librarySource) => _librarySources.contains(librarySource);
+}
+/**
+ * The interface `AngularControllerElement` defines the Angular component described by
+ * <code>Component</code> annotation.
+ */
+abstract class AngularComponentElement implements AngularHasSelectorElement, AngularHasTemplateElement {
/**
- * Return an array containing all the supertypes defined for this class and its supertypes. This
- * includes superclasses, mixins and interfaces.
- *
- * @return all the supertypes of this class, including mixins
+ * Return an array containing all of the properties declared by this component.
*/
- List<InterfaceType> get allSupertypes;
+ List<AngularPropertyElement> get properties;
/**
- * Return an array containing all of the constructors declared in this class.
- *
- * @return the constructors declared in this class
+ * Return an array containing all of the scope properties set in the implementation of this
+ * component.
*/
- List<ConstructorElement> get constructors;
+ List<AngularScopePropertyElement> get scopeProperties;
/**
- * Return the field (synthetic or explicit) defined in this class that has the given name, or
- * `null` if this class does not define a field with the given name.
- *
- * @param fieldName the name of the field to be returned
- * @return the field with the given name that is defined in this class
+ * Returns the CSS file URI.
*/
- FieldElement getField(String fieldName);
+ String get styleUri;
/**
- * Return an array containing all of the fields declared in this class.
+ * Return the offset of the [getStyleUri] in the [getSource].
*
- * @return the fields declared in this class
+ * @return the offset of the style URI
*/
- List<FieldElement> get fields;
+ int get styleUriOffset;
+}
+/**
+ * Implementation of `AngularComponentElement`.
+ */
+class AngularComponentElementImpl extends AngularHasSelectorElementImpl implements AngularComponentElement {
/**
- * Return the element representing the getter with the given name that is declared in this class,
- * or `null` if this class does not declare a getter with the given name.
- *
- * @param getterName the name of the getter to be returned
- * @return the getter declared in this class with the given name
+ * The offset of the defining <code>Component</code> annotation.
*/
- PropertyAccessorElement getGetter(String getterName);
+ final int _annotationOffset;
/**
- * Return an array containing all of the interfaces that are implemented by this class.
- *
- * <b>Note:</b> Because the element model represents the state of the code, it is possible for it
- * to be semantically invalid. In particular, it is not safe to assume that the inheritance
- * structure of a class does not contain a cycle. Clients that traverse the inheritance structure
- * must explicitly guard against infinite loops.
- *
- * @return the interfaces that are implemented by this class
+ * The array containing all of the properties declared by this component.
*/
- List<InterfaceType> get interfaces;
+ List<AngularPropertyElement> _properties = AngularPropertyElement.EMPTY_ARRAY;
/**
- * Return the element representing the method with the given name that is declared in this class,
- * or `null` if this class does not declare a method with the given name.
- *
- * @param methodName the name of the method to be returned
- * @return the method declared in this class with the given name
+ * The array containing all of the scope properties set by this component.
*/
- MethodElement getMethod(String methodName);
+ List<AngularScopePropertyElement> _scopeProperties = AngularScopePropertyElement.EMPTY_ARRAY;
/**
- * Return an array containing all of the methods declared in this class.
- *
- * @return the methods declared in this class
+ * The the CSS file URI.
*/
- List<MethodElement> get methods;
+ String styleUri;
/**
- * Return an array containing all of the mixins that are applied to the class being extended in
- * order to derive the superclass of this class.
- *
- * <b>Note:</b> Because the element model represents the state of the code, it is possible for it
- * to be semantically invalid. In particular, it is not safe to assume that the inheritance
- * structure of a class does not contain a cycle. Clients that traverse the inheritance structure
- * must explicitly guard against infinite loops.
- *
- * @return the mixins that are applied to derive the superclass of this class
+ * The offset of the [styleUri] in the [getSource].
*/
- List<InterfaceType> get mixins;
+ int styleUriOffset = 0;
/**
- * Return the named constructor declared in this class with the given name, or `null` if
- * this class does not declare a named constructor with the given name.
- *
- * @param name the name of the constructor to be returned
- * @return the element representing the specified constructor
+ * The HTML template URI.
*/
- ConstructorElement getNamedConstructor(String name);
+ String templateUri;
/**
- * Return the resolved [ClassDeclaration] node that declares this [ClassElement].
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * @return the resolved [ClassDeclaration], not `null`.
+ * The HTML template source.
*/
- @override
- ClassDeclaration get node;
+ Source templateSource;
/**
- * Return the element representing the setter with the given name that is declared in this class,
- * or `null` if this class does not declare a setter with the given name.
- *
- * @param setterName the name of the getter to be returned
- * @return the setter declared in this class with the given name
+ * The offset of the [templateUri] in the [getSource].
*/
- PropertyAccessorElement getSetter(String setterName);
+ int templateUriOffset = 0;
/**
- * Return the superclass of this class, or `null` if the class represents the class
- * 'Object'. All other classes will have a non-`null` superclass. If the superclass was not
- * explicitly declared then the implicit superclass 'Object' will be returned.
- *
- * <b>Note:</b> Because the element model represents the state of the code, it is possible for it
- * to be semantically invalid. In particular, it is not safe to assume that the inheritance
- * structure of a class does not contain a cycle. Clients that traverse the inheritance structure
- * must explicitly guard against infinite loops.
+ * Initialize a newly created Angular component to have the given name.
*
- * @return the superclass of this class
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- InterfaceType get supertype;
+ AngularComponentElementImpl(String name, int nameOffset, this._annotationOffset) : super(name, nameOffset);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularComponentElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_COMPONENT;
+
+ @override
+ List<AngularPropertyElement> get properties => _properties;
+
+ @override
+ List<AngularScopePropertyElement> get scopeProperties => _scopeProperties;
/**
- * Return an array containing all of the toolkit specific objects associated with this class. The
- * array will be empty if the class does not have any toolkit specific objects or if the
- * compilation unit containing the class has not yet had toolkit references resolved.
+ * Set an array containing all of the properties declared by this component.
*
- * @return the toolkit objects associated with this class
+ * @param properties the properties to set
*/
- List<ToolkitObjectElement> get toolkitObjects;
+ void set properties(List<AngularPropertyElement> properties) {
+ for (AngularPropertyElement property in properties) {
+ encloseElement(property as AngularPropertyElementImpl);
+ }
+ this._properties = properties;
+ }
/**
- * Return the type defined by the class.
+ * Set an array containing all of the scope properties declared by this component.
*
- * @return the type defined by the class
+ * @param properties the properties to set
*/
- InterfaceType get type;
+ void set scopeProperties(List<AngularScopePropertyElement> properties) {
+ for (AngularScopePropertyElement property in properties) {
+ encloseElement(property as AngularScopePropertyElementImpl);
+ }
+ this._scopeProperties = properties;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ safelyVisitChildren(_properties, visitor);
+ safelyVisitChildren(_scopeProperties, visitor);
+ super.visitChildren(visitor);
+ }
+
+ @override
+ String get identifier => "AngularComponent@${_annotationOffset}";
+}
+/**
+ * The interface `AngularControllerElement` defines the Angular controller described by
+ * <code>Controller</code> annotation.
+ */
+abstract class AngularControllerElement implements AngularHasSelectorElement {
+}
+
+/**
+ * Implementation of `AngularControllerElement`.
+ */
+class AngularControllerElementImpl extends AngularHasSelectorElementImpl implements AngularControllerElement {
/**
- * Return an array containing all of the type parameters declared for this class.
+ * Initialize a newly created Angular controller to have the given name.
*
- * @return the type parameters declared for this class
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- List<TypeParameterElement> get typeParameters;
+ AngularControllerElementImpl(String name, int nameOffset) : super(name, nameOffset);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularControllerElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_CONTROLLER;
+}
+/**
+ * The interface `AngularDirectiveElement` defines the Angular controller described by
+ * <code>Decorator</code> annotation.
+ */
+abstract class AngularDecoratorElement implements AngularHasSelectorElement {
/**
- * Return the unnamed constructor declared in this class, or `null` if this class does not
- * declare an unnamed constructor but does declare named constructors. The returned constructor
- * will be synthetic if this class does not declare any constructors, in which case it will
- * represent the default constructor for the class.
- *
- * @return the unnamed constructor defined in this class
+ * Return an array containing all of the properties declared by this directive.
*/
- ConstructorElement get unnamedConstructor;
+ List<AngularPropertyElement> get properties;
/**
- * Return `true` if this class or its superclass declares a non-final instance field.
- *
- * @return `true` if this class or its superclass declares a non-final instance field
+ * Checks if this directive is implemented by the class with given name.
*/
- bool get hasNonFinalField;
+ bool isClass(String name);
+}
+/**
+ * Implementation of `AngularDirectiveElement`.
+ */
+class AngularDecoratorElementImpl extends AngularHasSelectorElementImpl implements AngularDecoratorElement {
/**
- * Return `true` if this class has reference to super (so, for example, cannot be used as a
- * mixin).
- *
- * @return `true` if this class has reference to super
+ * The offset of the annotation that defines this directive.
*/
- bool get hasReferenceToSuper;
+ final int _offset;
/**
- * Return `true` if this class declares a static member.
- *
- * @return `true` if this class declares a static member
+ * The array containing all of the properties declared by this directive.
*/
- bool get hasStaticMember;
+ List<AngularPropertyElement> _properties = AngularPropertyElement.EMPTY_ARRAY;
/**
- * Return `true` if this class is abstract. A class is abstract if it has an explicit
- * `abstract` modifier. Note, that this definition of <i>abstract</i> is different from
- * <i>has unimplemented members</i>.
+ * Initialize a newly created Angular directive to have the given name.
*
- * @return `true` if this class is abstract
+ * @param offset the offset of the annotation that defines this directive
*/
- bool get isAbstract;
+ AngularDecoratorElementImpl(this._offset) : super(null, -1);
- /**
- * Return `true` if this class [isProxy], or if it inherits the proxy annotation
- * from a supertype.
- *
- * @return `true` if this class defines or inherits a proxy
- */
- bool get isOrInheritsProxy;
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularDirectiveElement(this);
+
+ @override
+ String get displayName => selector.displayName;
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_DIRECTIVE;
+
+ @override
+ List<AngularPropertyElement> get properties => _properties;
+
+ @override
+ bool isClass(String name) {
+ Element enclosing = enclosingElement;
+ return enclosing is ClassElement && enclosing.name == name;
+ }
/**
- * Return `true` if this element has an annotation of the form '@proxy'.
+ * Set an array containing all of the properties declared by this directive.
*
- * @return `true` if this element defines a proxy
+ * @param properties the properties to set
*/
- bool get isProxy;
+ void set properties(List<AngularPropertyElement> properties) {
+ for (AngularPropertyElement property in properties) {
+ encloseElement(property as AngularPropertyElementImpl);
+ }
+ this._properties = properties;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ safelyVisitChildren(_properties, visitor);
+ super.visitChildren(visitor);
+ }
+
+ @override
+ String get identifier => "Decorator@${_offset}";
+}
+/**
+ * The interface `AngularElement` defines the behavior of objects representing information
+ * about an Angular specific element.
+ */
+abstract class AngularElement implements ToolkitObjectElement {
/**
- * Return `true` if this class is defined by a typedef construct.
- *
- * @return `true` if this class is defined by a typedef construct
+ * An empty array of Angular elements.
*/
- bool get isTypedef;
+ static final List<AngularElement> EMPTY_ARRAY = new List<AngularElement>(0);
/**
- * Return `true` if this class can validly be used as a mixin when defining another class.
- * The behavior of this method is defined by the Dart Language Specification in section 9:
- * <blockquote>It is a compile-time error if a declared or derived mixin refers to super. It is a
- * compile-time error if a declared or derived mixin explicitly declares a constructor. It is a
- * compile-time error if a mixin is derived from a class whose superclass is not
- * Object.</blockquote>
+ * Returns the [AngularApplication] this element is used in.
*
- * @return `true` if this class can validly be used as a mixin
+ * @return the [AngularApplication] this element is used in
*/
- bool get isValidMixin;
+ AngularApplication get application;
+}
+/**
+ * Implementation of `AngularElement`.
+ */
+abstract class AngularElementImpl extends ToolkitObjectElementImpl implements AngularElement {
/**
- * Return the element representing the getter that results from looking up the given getter in
- * this class with respect to the given library, or `null` if the look up fails. The
- * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
- * <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
- * with respect to library <i>L</i> is:
- * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
- * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
- * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
- * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.
- * </blockquote>
- *
- * @param getterName the name of the getter being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given getter in this class with respect to the given
- * library
+ * The [AngularApplication] this element is used in.
*/
- PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library);
+ AngularApplication _application;
/**
- * Return the element representing the method that results from looking up the given method in
- * this class with respect to the given library, or `null` if the look up fails. The
- * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
- * <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect to library
- * <i>L</i> is:
- * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
- * that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
- * the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
- * to <i>L</i>. Otherwise, we say that the lookup has failed.
- * </blockquote>
+ * Initialize a newly created Angular element to have the given name.
*
- * @param methodName the name of the method being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given method in this class with respect to the given
- * library
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- MethodElement lookUpMethod(String methodName, LibraryElement library);
+ AngularElementImpl(String name, int nameOffset) : super(name, nameOffset);
+
+ @override
+ AngularApplication get application => _application;
/**
- * Return the element representing the setter that results from looking up the given setter in
- * this class with respect to the given library, or `null` if the look up fails. The
- * behavior of this method is defined by the Dart Language Specification in section 12.16:
- * <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
- * with respect to library <i>L</i> is:
- * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
- * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
- * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
- * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.
- * </blockquote>
- *
- * @param setterName the name of the setter being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given setter in this class with respect to the given
- * library
+ * Set the [AngularApplication] this element is used in.
*/
- PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library);
+ void set application(AngularApplication application) {
+ this._application = application;
+ }
}
/**
- * The interface `ClassMemberElement` defines the behavior of elements that are contained
- * within a [ClassElement].
+ * The interface `AngularFormatterElement` defines the Angular formatter described by
+ * <code>Formatter</code> annotation.
*/
-abstract class ClassMemberElement implements Element {
+abstract class AngularFormatterElement implements AngularElement {
+}
+
+/**
+ * Implementation of `AngularFormatterElement`.
+ */
+class AngularFormatterElementImpl extends AngularElementImpl implements AngularFormatterElement {
/**
- * Return the type in which this member is defined.
+ * Initialize a newly created Angular formatter to have the given name.
*
- * @return the type in which this member is defined
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
+ AngularFormatterElementImpl(String name, int nameOffset) : super(name, nameOffset);
+
@override
- ClassElement get enclosingElement;
+ accept(ElementVisitor visitor) => visitor.visitAngularFormatterElement(this);
- /**
- * Return `true` if this element is a static element. A static element is an element that is
- * not associated with a particular instance, but rather with an entire library or class.
- *
- * @return `true` if this executable element is a static element
- */
- bool get isStatic;
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_FORMATTER;
}
/**
- * The interface `CompilationUnitElement` defines the behavior of elements representing a
- * compilation unit.
+ * [AngularSelectorElement] based on presence of attribute.
*/
-abstract class CompilationUnitElement implements Element, UriReferencedElement {
+abstract class AngularHasAttributeSelectorElement implements AngularSelectorElement {
+}
+
+/**
+ * [AngularSelectorElement] based on presence of a class.
+ */
+abstract class AngularHasClassSelectorElement implements AngularSelectorElement {
+}
+
+/**
+ * Implementation of [AngularSelectorElement] based on presence of a class.
+ */
+class AngularHasClassSelectorElementImpl extends AngularSelectorElementImpl implements AngularHasClassSelectorElement {
+ AngularHasClassSelectorElementImpl(String name, int offset) : super(name, offset);
+
+ @override
+ bool apply(XmlTagNode node) {
+ XmlAttributeNode attribute = node.getAttribute("class");
+ if (attribute != null) {
+ String text = attribute.text;
+ if (text != null) {
+ String name = this.name;
+ for (String className in StringUtils.split(text)) {
+ if (className == name) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(".");
+ builder.append(name);
+ }
+}
+
+/**
+ * The interface `AngularElement` defines the behavior of objects representing information
+ * about an Angular element which is applied conditionally using some [AngularSelectorElement].
+ */
+abstract class AngularHasSelectorElement implements AngularElement {
/**
- * Return an array containing all of the top-level accessors (getters and setters) contained in
- * this compilation unit.
+ * Returns the selector specified for this element.
*
- * @return the top-level accessors contained in this compilation unit
+ * @return the [AngularSelectorElement] specified for this element
*/
- List<PropertyAccessorElement> get accessors;
+ AngularSelectorElement get selector;
+}
+/**
+ * Implementation of `AngularSelectorElement`.
+ */
+abstract class AngularHasSelectorElementImpl extends AngularElementImpl implements AngularHasSelectorElement {
/**
- * Return an array containing all of the Angular views defined in this compilation unit. The array
- * will be empty if the element does not have any Angular views or if the compilation unit has not
- * yet had toolkit references resolved.
- *
- * @return the Angular views defined in this compilation unit.
+ * The selector of this element.
*/
- List<AngularViewElement> get angularViews;
+ AngularSelectorElement _selector;
/**
- * Return the library in which this compilation unit is defined.
+ * Initialize a newly created Angular element to have the given name.
*
- * @return the library in which this compilation unit is defined
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
+ AngularHasSelectorElementImpl(String name, int nameOffset) : super(name, nameOffset);
+
@override
- LibraryElement get enclosingElement;
+ AngularSelectorElement get selector => _selector;
/**
- * Return an array containing all of the top-level functions contained in this compilation unit.
+ * Set the selector of this selector-based element.
*
- * @return the top-level functions contained in this compilation unit
+ * @param selector the selector to set
*/
- List<FunctionElement> get functions;
+ void set selector(AngularSelectorElement selector) {
+ encloseElement(selector as AngularSelectorElementImpl);
+ this._selector = selector;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ safelyVisitChild(_selector, visitor);
+ super.visitChildren(visitor);
+ }
+}
+/**
+ * The interface `AngularHasTemplateElement` defines common behavior for
+ * [AngularElement] that have template URI / [Source].
+ */
+abstract class AngularHasTemplateElement implements AngularElement {
/**
- * Return an array containing all of the function type aliases contained in this compilation unit.
- *
- * @return the function type aliases contained in this compilation unit
+ * Returns the HTML template [Source], `null` if not resolved.
*/
- List<FunctionTypeAliasElement> get functionTypeAliases;
+ Source get templateSource;
/**
- * Return the resolved [CompilationUnit] node that declares this element.
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * @return the resolved [CompilationUnit], not `null`.
+ * Returns the HTML template URI.
*/
- @override
- CompilationUnit get node;
+ String get templateUri;
/**
- * Return an array containing all of the top-level variables contained in this compilation unit.
+ * Return the offset of the [getTemplateUri] in the [getSource].
*
- * @return the top-level variables contained in this compilation unit
+ * @return the offset of the template URI
*/
- List<TopLevelVariableElement> get topLevelVariables;
+ int get templateUriOffset;
+}
+/**
+ * The interface `AngularPropertyElement` defines a single property in
+ * [AngularComponentElement].
+ */
+abstract class AngularPropertyElement implements AngularElement {
/**
- * Return the class defined in this compilation unit that has the given name, or `null` if
- * this compilation unit does not define a class with the given name.
+ * An empty array of property elements.
+ */
+ static final List<AngularPropertyElement> EMPTY_ARRAY = [];
+
+ /**
+ * Returns the field this property is mapped to.
*
- * @param className the name of the class to be returned
- * @return the class with the given name that is defined in this compilation unit
+ * @return the field this property is mapped to.
*/
- ClassElement getType(String className);
+ FieldElement get field;
/**
- * Return an array containing all of the classes contained in this compilation unit.
+ * Return the offset of the field name of this property in the property map, or `-1` if
+ * property was created using annotation on [FieldElement].
*
- * @return the classes contained in this compilation unit
+ * @return the offset of the field name of this property
*/
- List<ClassElement> get types;
+ int get fieldNameOffset;
/**
- * Return `true` if this compilation unit defines a top-level function named
- * `loadLibrary`.
+ * Returns the kind of this property.
*
- * @return `true` if this compilation unit defines a top-level function named
- * `loadLibrary`
+ * @return the kind of this property
*/
- bool get hasLoadLibraryFunction;
+ AngularPropertyKind get propertyKind;
}
/**
- * The interface `ConstructorElement` defines the behavior of elements representing a
- * constructor or a factory method defined within a type.
+ * Implementation of `AngularPropertyElement`.
*/
-abstract class ConstructorElement implements ClassMemberElement, ExecutableElement {
+class AngularPropertyElementImpl extends AngularElementImpl implements AngularPropertyElement {
/**
- * Return the resolved [ConstructorDeclaration] node that declares this
- * [ConstructorElement] .
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * @return the resolved [ConstructorDeclaration], not `null`.
+ * The [FieldElement] to which this property is bound.
*/
- @override
- ConstructorDeclaration get node;
+ FieldElement field;
/**
- * Return the constructor to which this constructor is redirecting, or `null` if this constructor
- * does not redirect to another constructor or if the library containing this constructor has
- * not yet been resolved.
- *
- * @return the constructor to which this constructor is redirecting
+ * The offset of the field name in the property map.
*/
- ConstructorElement get redirectedConstructor;
+ int fieldNameOffset = -1;
- /**
- * Return `true` if this constructor is a const constructor.
- *
- * @return `true` if this constructor is a const constructor
- */
- bool get isConst;
+ AngularPropertyKind propertyKind;
/**
- * Return `true` if this constructor can be used as a default constructor - unnamed and has
- * no required parameters.
+ * Initialize a newly created Angular property to have the given name.
*
- * @return `true` if this constructor can be used as a default constructor.
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- bool get isDefaultConstructor;
+ AngularPropertyElementImpl(String name, int nameOffset) : super(name, nameOffset);
- /**
- * Return `true` if this constructor represents a factory constructor.
- *
- * @return `true` if this constructor represents a factory constructor
- */
- bool get isFactory;
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularPropertyElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_PROPERTY;
}
/**
- * The interface `Element` defines the behavior common to all of the elements in the element
- * model. Generally speaking, the element model is a semantic model of the program that represents
- * things that are declared with a name and hence can be referenced elsewhere in the code.
- *
- * There are two exceptions to the general case. First, there are elements in the element model that
- * are created for the convenience of various kinds of analysis but that do not have any
- * corresponding declaration within the source code. Such elements are marked as being
- * <i>synthetic</i>. Examples of synthetic elements include
- * * default constructors in classes that do not define any explicit constructors,
- * * getters and setters that are induced by explicit field declarations,
- * * fields that are induced by explicit declarations of getters and setters, and
- * * functions representing the initialization expression for a variable.
- *
- * Second, there are elements in the element model that do not have a name. These correspond to
- * unnamed functions and exist in order to more accurately represent the semantic structure of the
- * program.
+ * The enumeration `AngularPropertyKind` defines the different kinds of property bindings.
*/
-abstract class Element {
+class AngularPropertyKind extends Enum<AngularPropertyKind> {
/**
- * An Unicode right arrow.
+ * `@` - Map the DOM attribute string. The attribute string will be taken literally or
+ * interpolated if it contains binding {{}} syntax and assigned to the expression. (cost: 0
+ * watches)
*/
- static final String RIGHT_ARROW = " \u2192 ";
+ static const AngularPropertyKind ATTR = const AngularPropertyKind('ATTR', 0);
/**
- * A comparator that can be used to sort elements by their name offset. Elements with a smaller
- * offset will be sorted to be before elements with a larger name offset.
+ * `&` - Treat the DOM attribute value as an expression. Assign a closure function into the field.
+ * This allows the component to control the invocation of the closure. This is useful for passing
+ * expressions into controllers which act like callbacks. (cost: 0 watches)
*/
- static final Comparator<Element> SORT_BY_OFFSET = (Element firstElement, Element secondElement) => firstElement.nameOffset - secondElement.nameOffset;
+ static const AngularPropertyKind CALLBACK = const AngularPropertyKind('CALLBACK', 1);
/**
- * Use the given visitor to visit this element.
- *
- * @param visitor the visitor that will visit this element
- * @return the value returned by the visitor as a result of visiting this element
+ * `=>` - Treat the DOM attribute value as an expression. Set up a watch, which will read the
+ * expression in the attribute and assign the value to destination expression. (cost: 1 watch)
*/
- accept(ElementVisitor visitor);
+ static const AngularPropertyKind ONE_WAY = const AngularPropertyKind('ONE_WAY', 2);
/**
- * Return the documentation comment for this element as it appears in the original source
- * (complete with the beginning and ending delimiters), or `null` if this element does not
- * have a documentation comment associated with it. This can be a long-running operation if the
- * information needed to access the comment is not cached.
- *
- * @return this element's documentation comment
- * @throws AnalysisException if the documentation comment could not be determined because the
- * analysis could not be performed
+ * `=>!` - Treat the DOM attribute value as an expression. Set up a one time watch on expression.
+ * Once the expression turns not null it will no longer update. (cost: 1 watches until not null,
+ * then 0 watches)
*/
- String computeDocumentationComment();
+ static const AngularPropertyKind ONE_WAY_ONE_TIME = const AngularPropertyKind('ONE_WAY_ONE_TIME', 3);
/**
- * Return the element of the given class that most immediately encloses this element, or
- * `null` if there is no enclosing element of the given class.
- *
- * @param elementClass the class of the element to be returned
- * @return the element that encloses this element
+ * `<=>` - Treat the DOM attribute value as an expression. Set up a watch on both outside as well
+ * as component scope to keep the source and destination in sync. (cost: 2 watches)
*/
- Element getAncestor(Predicate<Element> predicate);
+ static const AngularPropertyKind TWO_WAY = const AngularPropertyKind_TWO_WAY('TWO_WAY', 4);
+
+ static const List<AngularPropertyKind> values = const [ATTR, CALLBACK, ONE_WAY, ONE_WAY_ONE_TIME, TWO_WAY];
/**
- * Return the analysis context in which this element is defined.
- *
- * @return the analysis context in which this element is defined
+ * Returns `true` if property of this kind calls field getter.
*/
- AnalysisContext get context;
+ bool callsGetter() => false;
/**
- * Return the display name of this element, or `null` if this element does not have a name.
- *
- * In most cases the name and the display name are the same. Differences though are cases such as
- * setters where the name of some setter `set f(x)` is `f=`, instead of `f`.
- *
- * @return the display name of this element
+ * Returns `true` if property of this kind calls field setter.
*/
- String get displayName;
+ bool callsSetter() => true;
+
+ const AngularPropertyKind(String name, int ordinal) : super(name, ordinal);
+}
+
+class AngularPropertyKind_TWO_WAY extends AngularPropertyKind {
+ const AngularPropertyKind_TWO_WAY(String name, int ordinal) : super(name, ordinal);
+
+ @override
+ bool callsGetter() => true;
+}
+/**
+ * The interface `AngularScopeVariableElement` defines the Angular <code>Scope</code>
+ * property. They are created for every <code>scope['property'] = value;</code> code snippet.
+ */
+abstract class AngularScopePropertyElement implements AngularElement {
/**
- * Return the element that either physically or logically encloses this element. This will be
- * `null` if this element is a library because libraries are the top-level elements in the
- * model.
- *
- * @return the element that encloses this element
+ * An empty array of scope property elements.
*/
- Element get enclosingElement;
+ static final List<AngularScopePropertyElement> EMPTY_ARRAY = [];
/**
- * Return the kind of element that this is.
+ * Returns the type of this property, not `null`, maybe <code>dynamic</code>.
*
- * @return the kind of this element
+ * @return the type of this property.
*/
- ElementKind get kind;
+ DartType get type;
+}
+/**
+ * Implementation of `AngularScopePropertyElement`.
+ */
+class AngularScopePropertyElementImpl extends AngularElementImpl implements AngularScopePropertyElement {
/**
- * Return the library that contains this element. This will be the element itself if it is a
- * library element. This will be `null` if this element is an HTML file because HTML files
- * are not contained in libraries.
- *
- * @return the library that contains this element
+ * The type of the property
*/
- LibraryElement get library;
+ final DartType type;
/**
- * Return an object representing the location of this element in the element model. The object can
- * be used to locate this element at a later time.
+ * Initialize a newly created Angular scope property to have the given name.
*
- * @return the location of this element in the element model
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- ElementLocation get location;
+ AngularScopePropertyElementImpl(String name, int nameOffset, this.type) : super(name, nameOffset);
- /**
- * Return an array containing all of the metadata associated with this element. The array will be
- * empty if the element does not have any metadata or if the library containing this element has
- * not yet been resolved.
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularScopePropertyElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_SCOPE_PROPERTY;
+}
+
+/**
+ * [AngularSelectorElement] is used to decide when Angular object should be applied.
+ *
+ * This class is an [Element] to support renaming component tag names, which are identifiers
+ * in selectors.
+ */
+abstract class AngularSelectorElement implements AngularElement {
+ /**
+ * Checks if the given [XmlTagNode] matches this selector.
*
- * @return the metadata associated with this element
+ * @param node the [XmlTagNode] to check
+ * @return `true` if the given [XmlTagNode] matches, or `false` otherwise
*/
- List<ElementAnnotation> get metadata;
+ bool apply(XmlTagNode node);
+}
+/**
+ * Implementation of `AngularFormatterElement`.
+ */
+abstract class AngularSelectorElementImpl extends AngularElementImpl implements AngularSelectorElement {
/**
- * Return the name of this element, or `null` if this element does not have a name.
+ * Initialize a newly created Angular selector to have the given name.
*
- * @return the name of this element
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- String get name;
+ AngularSelectorElementImpl(String name, int nameOffset) : super(name, nameOffset);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularSelectorElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_SELECTOR;
+}
+
+/**
+ * [AngularSelectorElement] based on tag name.
+ */
+abstract class AngularTagSelectorElement implements AngularSelectorElement {
+}
+
+/**
+ * Implementation of [AngularSelectorElement] based on tag name.
+ */
+class AngularTagSelectorElementImpl extends AngularSelectorElementImpl implements AngularTagSelectorElement {
+ AngularTagSelectorElementImpl(String name, int offset) : super(name, offset);
+
+ @override
+ bool apply(XmlTagNode node) {
+ String tagName = name;
+ return node.tag == tagName;
+ }
+
+ @override
+ AngularApplication get application => (enclosingElement as AngularElementImpl).application;
+}
+/**
+ * The interface `AngularViewElement` defines the Angular view defined using invocation like
+ * <code>view('views/create.html')</code>.
+ */
+abstract class AngularViewElement implements AngularHasTemplateElement {
/**
- * Return the offset of the name of this element in the file that contains the declaration of this
- * element, or `-1` if this element is synthetic, does not have a name, or otherwise does
- * not have an offset.
- *
- * @return the offset of the name of this element
+ * An empty array of view elements.
*/
- int get nameOffset;
+ static final List<AngularViewElement> EMPTY_ARRAY = new List<AngularViewElement>(0);
+}
+/**
+ * Implementation of `AngularViewElement`.
+ */
+class AngularViewElementImpl extends AngularElementImpl implements AngularViewElement {
/**
- * Return the resolved [AstNode] node that declares this [Element].
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * <b>Note:</b> This method cannot be used in an async environment.
- *
- * @return the resolved [AstNode], maybe `null` if [Element] is synthetic or
- * isn't contained in a compilation unit, such as a [LibraryElement].
+ * The HTML template URI.
*/
- AstNode get node;
+ final String templateUri;
/**
- * Return the source that contains this element, or `null` if this element is not contained
- * in a source.
- *
- * @return the source that contains this element
+ * The offset of the [templateUri] in the [getSource].
*/
- Source get source;
+ final int templateUriOffset;
/**
- * Return the resolved [CompilationUnit] that declares this [Element].
- *
- * This method is expensive, because resolved AST might have been already evicted from cache, so
- * parsing and resolving will be performed.
- *
- * @return the resolved [CompilationUnit], maybe `null` if synthetic [Element].
+ * The HTML template source.
*/
- CompilationUnit get unit;
+ Source templateSource;
/**
- * Return `true` if this element, assuming that it is within scope, is accessible to code in
- * the given library. This is defined by the Dart Language Specification in section 3.2:
- * <blockquote> A declaration <i>m</i> is accessible to library <i>L</i> if <i>m</i> is declared
- * in <i>L</i> or if <i>m</i> is public. </blockquote>
- *
- * @param library the library in which a possible reference to this element would occur
- * @return `true` if this element is accessible to code in the given library
+ * Initialize a newly created Angular view.
*/
- bool isAccessibleIn(LibraryElement library);
+ AngularViewElementImpl(this.templateUri, this.templateUriOffset) : super(null, -1);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitAngularViewElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.ANGULAR_VIEW;
+
+ @override
+ String get identifier => "AngularView@${templateUriOffset}";
+}
+/**
+ * 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]. Since 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 {
/**
- * Return `true` if this element has an annotation of the form '@deprecated' or
- * '@Deprecated('..')'.
- *
- * @return `true` if this element is deprecated
+ * The element based on propagated type information, or `null` if the AST structure has not
+ * been resolved or if this identifier could not be resolved.
*/
- bool get isDeprecated;
+ final ExecutableElement propagatedElement;
/**
- * Return `true` if this element has an annotation of the form '@override'.
- *
- * @return `true` if this element is overridden
+ * The element associated with this identifier based on static type information, or `null`
+ * if the AST structure has not been resolved or if this identifier could not be resolved.
*/
- bool get isOverride;
+ final ExecutableElement staticElement;
/**
- * Return `true` if this element is private. Private elements are visible only within the
- * library in which they are declared.
+ * Create the [AuxiliaryElements] with a static and propagated [ExecutableElement].
*
- * @return `true` if this element is private
+ * @param staticElement the static element
+ * @param propagatedElement the propagated element
*/
- bool get isPrivate;
+ AuxiliaryElements(this.staticElement, this.propagatedElement);
+}
+/**
+ * The unique instance of the class `BottomTypeImpl` implements the type `bottom`.
+ */
+class BottomTypeImpl extends TypeImpl {
/**
- * Return `true` if this element is public. Public elements are visible within any library
- * that imports the library in which they are declared.
- *
- * @return `true` if this element is public
+ * The unique instance of this class.
*/
- bool get isPublic;
+ static BottomTypeImpl _INSTANCE = new BottomTypeImpl();
/**
- * Return `true` if this element is synthetic. A synthetic element is an element that is not
- * represented in the source code explicitly, but is implied by the source code, such as the
- * default constructor for a class that does not explicitly define any constructors.
+ * Return the unique instance of this class.
*
- * @return `true` if this element is synthetic
+ * @return the unique instance of this class
*/
- bool get isSynthetic;
+ static BottomTypeImpl get instance => _INSTANCE;
/**
- * Use the given visitor to visit all of the children of this element. There is no guarantee of
- * the order in which the children will be visited.
- *
- * @param visitor the visitor that will be used to visit the children of this element
+ * Prevent the creation of instances of this class.
*/
- void visitChildren(ElementVisitor visitor);
+ BottomTypeImpl() : super(null, "<bottom>");
+
+ @override
+ bool operator ==(Object object) => identical(object, this);
+
+ @override
+ int get hashCode => 0;
+
+ @override
+ bool get isBottom => true;
+
+ @override
+ bool isSupertypeOf(DartType type) => false;
+
+ @override
+ BottomTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) => this;
+
+ @override
+ bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
+
+ @override
+ bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) => true;
+
+ @override
+ bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
}
/**
- * The interface `ElementAnnotation` defines the behavior of objects representing a single
- * annotation associated with an element.
+ * The interface `ClassElement` defines the behavior of elements that represent a class.
*/
-abstract class ElementAnnotation {
+abstract class ClassElement implements Element {
/**
- * Return the element representing the field, variable, or const constructor being used as an
- * annotation.
+ * Return an array containing all of the accessors (getters and setters) declared in this class.
*
- * @return the field, variable, or constructor being used as an annotation
+ * @return the accessors declared in this class
*/
- Element get element;
+ List<PropertyAccessorElement> get accessors;
/**
- * Return `true` if this annotation marks the associated element as being deprecated.
+ * Return an array containing all the supertypes defined for this class and its supertypes. This
+ * includes superclasses, mixins and interfaces.
*
- * @return `true` if this annotation marks the associated element as being deprecated
+ * @return all the supertypes of this class, including mixins
*/
- bool get isDeprecated;
+ List<InterfaceType> get allSupertypes;
/**
- * Return `true` if this annotation marks the associated method as being expected to
- * override an inherited method.
+ * Return an array containing all of the constructors declared in this class.
*
- * @return `true` if this annotation marks the associated method as overriding another
- * method
+ * @return the constructors declared in this class
*/
- bool get isOverride;
+ List<ConstructorElement> get constructors;
/**
- * Return `true` if this annotation marks the associated class as implementing a proxy
- * object.
+ * Return the field (synthetic or explicit) defined in this class that has the given name, or
+ * `null` if this class does not define a field with the given name.
*
- * @return `true` if this annotation marks the associated class as implementing a proxy
- * object
+ * @param fieldName the name of the field to be returned
+ * @return the field with the given name that is defined in this class
*/
- bool get isProxy;
-}
+ FieldElement getField(String fieldName);
-/**
- * The enumeration `ElementKind` defines the various kinds of elements in the element model.
- */
-class ElementKind extends Enum<ElementKind> {
- static const ElementKind ANGULAR_FORMATTER = const ElementKind('ANGULAR_FORMATTER', 0, "Angular formatter");
-
- static const ElementKind ANGULAR_COMPONENT = const ElementKind('ANGULAR_COMPONENT', 1, "Angular component");
-
- static const ElementKind ANGULAR_CONTROLLER = const ElementKind('ANGULAR_CONTROLLER', 2, "Angular controller");
-
- static const ElementKind ANGULAR_DIRECTIVE = const ElementKind('ANGULAR_DIRECTIVE', 3, "Angular directive");
-
- static const ElementKind ANGULAR_PROPERTY = const ElementKind('ANGULAR_PROPERTY', 4, "Angular property");
-
- static const ElementKind ANGULAR_SCOPE_PROPERTY = const ElementKind('ANGULAR_SCOPE_PROPERTY', 5, "Angular scope property");
-
- static const ElementKind ANGULAR_SELECTOR = const ElementKind('ANGULAR_SELECTOR', 6, "Angular selector");
-
- static const ElementKind ANGULAR_VIEW = const ElementKind('ANGULAR_VIEW', 7, "Angular view");
-
- static const ElementKind CLASS = const ElementKind('CLASS', 8, "class");
-
- static const ElementKind COMPILATION_UNIT = const ElementKind('COMPILATION_UNIT', 9, "compilation unit");
-
- static const ElementKind CONSTRUCTOR = const ElementKind('CONSTRUCTOR', 10, "constructor");
-
- static const ElementKind DYNAMIC = const ElementKind('DYNAMIC', 11, "<dynamic>");
-
- static const ElementKind EMBEDDED_HTML_SCRIPT = const ElementKind('EMBEDDED_HTML_SCRIPT', 12, "embedded html script");
-
- static const ElementKind ERROR = const ElementKind('ERROR', 13, "<error>");
-
- static const ElementKind EXPORT = const ElementKind('EXPORT', 14, "export directive");
-
- static const ElementKind EXTERNAL_HTML_SCRIPT = const ElementKind('EXTERNAL_HTML_SCRIPT', 15, "external html script");
-
- static const ElementKind FIELD = const ElementKind('FIELD', 16, "field");
-
- static const ElementKind FUNCTION = const ElementKind('FUNCTION', 17, "function");
-
- static const ElementKind GETTER = const ElementKind('GETTER', 18, "getter");
-
- static const ElementKind HTML = const ElementKind('HTML', 19, "html");
-
- static const ElementKind IMPORT = const ElementKind('IMPORT', 20, "import directive");
-
- static const ElementKind LABEL = const ElementKind('LABEL', 21, "label");
-
- static const ElementKind LIBRARY = const ElementKind('LIBRARY', 22, "library");
-
- static const ElementKind LOCAL_VARIABLE = const ElementKind('LOCAL_VARIABLE', 23, "local variable");
+ /**
+ * Return an array containing all of the fields declared in this class.
+ *
+ * @return the fields declared in this class
+ */
+ List<FieldElement> get fields;
- static const ElementKind METHOD = const ElementKind('METHOD', 24, "method");
+ /**
+ * Return the element representing the getter with the given name that is declared in this class,
+ * or `null` if this class does not declare a getter with the given name.
+ *
+ * @param getterName the name of the getter to be returned
+ * @return the getter declared in this class with the given name
+ */
+ PropertyAccessorElement getGetter(String getterName);
- static const ElementKind NAME = const ElementKind('NAME', 25, "<name>");
+ /**
+ * Return an array containing all of the interfaces that are implemented by this class.
+ *
+ * <b>Note:</b> Because the element model represents the state of the code, it is possible for it
+ * to be semantically invalid. In particular, it is not safe to assume that the inheritance
+ * structure of a class does not contain a cycle. Clients that traverse the inheritance structure
+ * must explicitly guard against infinite loops.
+ *
+ * @return the interfaces that are implemented by this class
+ */
+ List<InterfaceType> get interfaces;
- static const ElementKind PARAMETER = const ElementKind('PARAMETER', 26, "parameter");
+ /**
+ * Return the element representing the method with the given name that is declared in this class,
+ * or `null` if this class does not declare a method with the given name.
+ *
+ * @param methodName the name of the method to be returned
+ * @return the method declared in this class with the given name
+ */
+ MethodElement getMethod(String methodName);
- static const ElementKind POLYMER_ATTRIBUTE = const ElementKind('POLYMER_ATTRIBUTE', 27, "Polymer attribute");
+ /**
+ * Return an array containing all of the methods declared in this class.
+ *
+ * @return the methods declared in this class
+ */
+ List<MethodElement> get methods;
- static const ElementKind POLYMER_TAG_DART = const ElementKind('POLYMER_TAG_DART', 28, "Polymer Dart tag");
+ /**
+ * Return an array containing all of the mixins that are applied to the class being extended in
+ * order to derive the superclass of this class.
+ *
+ * <b>Note:</b> Because the element model represents the state of the code, it is possible for it
+ * to be semantically invalid. In particular, it is not safe to assume that the inheritance
+ * structure of a class does not contain a cycle. Clients that traverse the inheritance structure
+ * must explicitly guard against infinite loops.
+ *
+ * @return the mixins that are applied to derive the superclass of this class
+ */
+ List<InterfaceType> get mixins;
- static const ElementKind POLYMER_TAG_HTML = const ElementKind('POLYMER_TAG_HTML', 29, "Polymer HTML tag");
+ /**
+ * Return the named constructor declared in this class with the given name, or `null` if
+ * this class does not declare a named constructor with the given name.
+ *
+ * @param name the name of the constructor to be returned
+ * @return the element representing the specified constructor
+ */
+ ConstructorElement getNamedConstructor(String name);
- static const ElementKind PREFIX = const ElementKind('PREFIX', 30, "import prefix");
+ /**
+ * Return the resolved [ClassDeclaration] node that declares this [ClassElement].
+ *
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
+ *
+ * @return the resolved [ClassDeclaration], not `null`.
+ */
+ @override
+ ClassDeclaration get node;
- static const ElementKind SETTER = const ElementKind('SETTER', 31, "setter");
+ /**
+ * Return the element representing the setter with the given name that is declared in this class,
+ * or `null` if this class does not declare a setter with the given name.
+ *
+ * @param setterName the name of the getter to be returned
+ * @return the setter declared in this class with the given name
+ */
+ PropertyAccessorElement getSetter(String setterName);
- static const ElementKind TOP_LEVEL_VARIABLE = const ElementKind('TOP_LEVEL_VARIABLE', 32, "top level variable");
+ /**
+ * Return the superclass of this class, or `null` if the class represents the class
+ * 'Object'. All other classes will have a non-`null` superclass. If the superclass was not
+ * explicitly declared then the implicit superclass 'Object' will be returned.
+ *
+ * <b>Note:</b> Because the element model represents the state of the code, it is possible for it
+ * to be semantically invalid. In particular, it is not safe to assume that the inheritance
+ * structure of a class does not contain a cycle. Clients that traverse the inheritance structure
+ * must explicitly guard against infinite loops.
+ *
+ * @return the superclass of this class
+ */
+ InterfaceType get supertype;
- static const ElementKind FUNCTION_TYPE_ALIAS = const ElementKind('FUNCTION_TYPE_ALIAS', 33, "function type alias");
+ /**
+ * Return an array containing all of the toolkit specific objects associated with this class. The
+ * array will be empty if the class does not have any toolkit specific objects or if the
+ * compilation unit containing the class has not yet had toolkit references resolved.
+ *
+ * @return the toolkit objects associated with this class
+ */
+ List<ToolkitObjectElement> get toolkitObjects;
- static const ElementKind TYPE_PARAMETER = const ElementKind('TYPE_PARAMETER', 34, "type parameter");
+ /**
+ * Return the type defined by the class.
+ *
+ * @return the type defined by the class
+ */
+ InterfaceType get type;
- static const ElementKind UNIVERSE = const ElementKind('UNIVERSE', 35, "<universe>");
+ /**
+ * Return an array containing all of the type parameters declared for this class.
+ *
+ * @return the type parameters declared for this class
+ */
+ List<TypeParameterElement> get typeParameters;
- static const List<ElementKind> values = const [
- ANGULAR_FORMATTER,
- ANGULAR_COMPONENT,
- ANGULAR_CONTROLLER,
- ANGULAR_DIRECTIVE,
- ANGULAR_PROPERTY,
- ANGULAR_SCOPE_PROPERTY,
- ANGULAR_SELECTOR,
- ANGULAR_VIEW,
- CLASS,
- COMPILATION_UNIT,
- CONSTRUCTOR,
- DYNAMIC,
- EMBEDDED_HTML_SCRIPT,
- ERROR,
- EXPORT,
- EXTERNAL_HTML_SCRIPT,
- FIELD,
- FUNCTION,
- GETTER,
- HTML,
- IMPORT,
- LABEL,
- LIBRARY,
- LOCAL_VARIABLE,
- METHOD,
- NAME,
- PARAMETER,
- POLYMER_ATTRIBUTE,
- POLYMER_TAG_DART,
- POLYMER_TAG_HTML,
- PREFIX,
- SETTER,
- TOP_LEVEL_VARIABLE,
- FUNCTION_TYPE_ALIAS,
- TYPE_PARAMETER,
- UNIVERSE];
+ /**
+ * Return the unnamed constructor declared in this class, or `null` if this class does not
+ * declare an unnamed constructor but does declare named constructors. The returned constructor
+ * will be synthetic if this class does not declare any constructors, in which case it will
+ * represent the default constructor for the class.
+ *
+ * @return the unnamed constructor defined in this class
+ */
+ ConstructorElement get unnamedConstructor;
/**
- * Return the kind of the given element, or [ERROR] if the element is `null`. This is
- * a utility method that can reduce the need for null checks in other places.
+ * Return `true` if this class or its superclass declares a non-final instance field.
*
- * @param element the element whose kind is to be returned
- * @return the kind of the given element
+ * @return `true` if this class or its superclass declares a non-final instance field
*/
- static ElementKind of(Element element) {
- if (element == null) {
- return ERROR;
- }
- return element.kind;
- }
+ bool get hasNonFinalField;
/**
- * The name displayed in the UI for this kind of element.
+ * Return `true` if this class has reference to super (so, for example, cannot be used as a
+ * mixin).
+ *
+ * @return `true` if this class has reference to super
*/
- final String displayName;
+ bool get hasReferenceToSuper;
/**
- * Initialize a newly created element kind to have the given display name.
+ * Return `true` if this class declares a static member.
*
- * @param displayName the name displayed in the UI for this kind of element
+ * @return `true` if this class declares a static member
*/
- const ElementKind(String name, int ordinal, this.displayName) : super(name, ordinal);
-}
+ bool get hasStaticMember;
-/**
- * The interface `ElementLocation` defines the behavior of objects that represent the location
- * of an element within the element model.
- */
-abstract class ElementLocation {
/**
- * Return an encoded representation of this location that can be used to create a location that is
- * equal to this location.
+ * Return `true` if this class is abstract. A class is abstract if it has an explicit
+ * `abstract` modifier. Note, that this definition of <i>abstract</i> is different from
+ * <i>has unimplemented members</i>.
*
- * @return an encoded representation of this location
+ * @return `true` if this class is abstract
*/
- String get encoding;
-}
+ bool get isAbstract;
-/**
- * The interface `ElementVisitor` defines the behavior of objects that can be used to visit an
- * element structure.
- */
-abstract class ElementVisitor<R> {
- R visitAngularComponentElement(AngularComponentElement element);
-
- R visitAngularControllerElement(AngularControllerElement element);
-
- R visitAngularDirectiveElement(AngularDecoratorElement element);
-
- R visitAngularFormatterElement(AngularFormatterElement element);
-
- R visitAngularPropertyElement(AngularPropertyElement element);
-
- R visitAngularScopePropertyElement(AngularScopePropertyElement element);
-
- R visitAngularSelectorElement(AngularSelectorElement element);
-
- R visitAngularViewElement(AngularViewElement element);
-
- R visitClassElement(ClassElement element);
-
- R visitCompilationUnitElement(CompilationUnitElement element);
-
- R visitConstructorElement(ConstructorElement element);
-
- R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element);
-
- R visitExportElement(ExportElement element);
-
- R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element);
-
- R visitFieldElement(FieldElement element);
-
- R visitFieldFormalParameterElement(FieldFormalParameterElement element);
-
- R visitFunctionElement(FunctionElement element);
-
- R visitFunctionTypeAliasElement(FunctionTypeAliasElement element);
-
- R visitHtmlElement(HtmlElement element);
-
- R visitImportElement(ImportElement element);
-
- R visitLabelElement(LabelElement element);
-
- R visitLibraryElement(LibraryElement element);
-
- R visitLocalVariableElement(LocalVariableElement element);
-
- R visitMethodElement(MethodElement element);
-
- R visitMultiplyDefinedElement(MultiplyDefinedElement element);
-
- R visitParameterElement(ParameterElement element);
-
- R visitPolymerAttributeElement(PolymerAttributeElement element);
-
- R visitPolymerTagDartElement(PolymerTagDartElement element);
-
- R visitPolymerTagHtmlElement(PolymerTagHtmlElement element);
-
- R visitPrefixElement(PrefixElement element);
-
- R visitPropertyAccessorElement(PropertyAccessorElement element);
-
- R visitTopLevelVariableElement(TopLevelVariableElement element);
-
- R visitTypeParameterElement(TypeParameterElement element);
-}
-
-/**
- * The interface `EmbeddedHtmlScriptElement` defines the behavior of elements representing a
- * script tag in an HTML file having content that defines a Dart library.
- */
-abstract class EmbeddedHtmlScriptElement implements HtmlScriptElement {
/**
- * Return the library element defined by the content of the script tag.
+ * Return `true` if this class [isProxy], or if it inherits the proxy annotation
+ * from a supertype.
*
- * @return the library element (not `null`)
+ * @return `true` if this class defines or inherits a proxy
*/
- LibraryElement get scriptLibrary;
-}
+ bool get isOrInheritsProxy;
-/**
- * The interface `ExecutableElement` defines the behavior of elements representing an
- * executable object, including functions, methods, constructors, getters, and setters.
- */
-abstract class ExecutableElement implements Element {
/**
- * Return an array containing all of the functions defined within this executable element.
+ * Return `true` if this element has an annotation of the form '@proxy'.
*
- * @return the functions defined within this executable element
+ * @return `true` if this element defines a proxy
*/
- List<FunctionElement> get functions;
+ bool get isProxy;
/**
- * Return an array containing all of the labels defined within this executable element.
+ * Return `true` if this class is defined by a typedef construct.
*
- * @return the labels defined within this executable element
+ * @return `true` if this class is defined by a typedef construct
*/
- List<LabelElement> get labels;
+ bool get isTypedef;
/**
- * Return an array containing all of the local variables defined within this executable element.
+ * Return `true` if this class can validly be used as a mixin when defining another class.
+ * The behavior of this method is defined by the Dart Language Specification in section 9:
+ * <blockquote>It is a compile-time error if a declared or derived mixin refers to super. It is a
+ * compile-time error if a declared or derived mixin explicitly declares a constructor. It is a
+ * compile-time error if a mixin is derived from a class whose superclass is not
+ * Object.</blockquote>
*
- * @return the local variables defined within this executable element
+ * @return `true` if this class can validly be used as a mixin
*/
- List<LocalVariableElement> get localVariables;
+ bool get isValidMixin;
/**
- * Return an array containing all of the parameters defined by this executable element.
+ * Return the element representing the getter that results from looking up the given getter in
+ * this class with respect to the given library, or `null` if the look up fails. The
+ * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
+ * <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
+ * with respect to library <i>L</i> is:
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
+ * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
+ * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
+ * Otherwise, we say that the lookup has failed.
+ * </blockquote>
*
- * @return the parameters defined by this executable element
+ * @param getterName the name of the getter being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given getter in this class with respect to the given
+ * library
*/
- List<ParameterElement> get parameters;
+ PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library);
/**
- * Return the return type defined by this executable element.
+ * Return the element representing the method that results from looking up the given method in
+ * this class with respect to the given library, or `null` if the look up fails. The
+ * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
+ * <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect to library
+ * <i>L</i> is:
+ * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
+ * that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
+ * the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
+ * to <i>L</i>. Otherwise, we say that the lookup has failed.
+ * </blockquote>
*
- * @return the return type defined by this executable element
+ * @param methodName the name of the method being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given method in this class with respect to the given
+ * library
*/
- DartType get returnType;
+ MethodElement lookUpMethod(String methodName, LibraryElement library);
/**
- * Return the type of function defined by this executable element.
+ * Return the element representing the setter that results from looking up the given setter in
+ * this class with respect to the given library, or `null` if the look up fails. The
+ * behavior of this method is defined by the Dart Language Specification in section 12.16:
+ * <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
+ * with respect to library <i>L</i> is:
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
+ * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
+ * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
+ * Otherwise, we say that the lookup has failed.
+ * </blockquote>
*
- * @return the type of function defined by this executable element
+ * @param setterName the name of the setter being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given setter in this class with respect to the given
+ * library
*/
- FunctionType get type;
+ PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library);
+}
+/**
+ * Instances of the class `ClassElementImpl` implement a `ClassElement`.
+ */
+class ClassElementImpl extends ElementImpl implements ClassElement {
/**
- * Return `true` if this executable element is an operator. The test may be based on the
- * name of the executable element, in which case the result will be correct when the name is
- * legal.
- *
- * @return `true` if this executable element is an operator
+ * An array containing all of the accessors (getters and setters) contained in this class.
*/
- bool get isOperator;
+ List<PropertyAccessorElement> _accessors = PropertyAccessorElementImpl.EMPTY_ARRAY;
/**
- * Return `true` if this element is a static element. A static element is an element that is
- * not associated with a particular instance, but rather with an entire library or class.
- *
- * @return `true` if this executable element is a static element
+ * An array containing all of the constructors contained in this class.
*/
- bool get isStatic;
-}
+ List<ConstructorElement> _constructors = ConstructorElementImpl.EMPTY_ARRAY;
-/**
- * The interface `ExportElement` defines the behavior of objects representing information
- * about a single export directive within a library.
- */
-abstract class ExportElement implements Element, UriReferencedElement {
/**
- * An empty array of export elements.
+ * An array containing all of the fields contained in this class.
*/
- static final List<ExportElement> EMPTY_ARRAY = new List<ExportElement>(0);
+ List<FieldElement> _fields = FieldElementImpl.EMPTY_ARRAY;
/**
- * Return an array containing the combinators that were specified as part of the export directive
- * in the order in which they were specified.
- *
- * @return the combinators specified in the export directive
+ * An array containing all of the mixins that are applied to the class being extended in order to
+ * derive the superclass of this class.
*/
- List<NamespaceCombinator> get combinators;
+ List<InterfaceType> mixins = InterfaceTypeImpl.EMPTY_ARRAY;
/**
- * Return the library that is exported from this library by this export directive.
- *
- * @return the library that is exported from this library
+ * An array containing all of the interfaces that are implemented by this class.
*/
- LibraryElement get exportedLibrary;
-}
+ List<InterfaceType> interfaces = InterfaceTypeImpl.EMPTY_ARRAY;
-/**
- * The interface `ExternalHtmlScriptElement` defines the behavior of elements representing a
- * script tag in an HTML file having a `source` attribute that references a Dart library
- * source file.
- */
-abstract class ExternalHtmlScriptElement implements HtmlScriptElement {
/**
- * Return the source referenced by this element, or `null` if this element does not
- * reference a Dart library source file.
- *
- * @return the source for the external Dart library
+ * An array containing all of the methods contained in this class.
*/
- Source get scriptSource;
-}
-
-/**
- * The interface `FieldElement` defines the behavior of elements representing a field defined
- * within a type.
- */
-abstract class FieldElement implements ClassMemberElement, PropertyInducingElement {
-}
+ List<MethodElement> _methods = MethodElementImpl.EMPTY_ARRAY;
-/**
- * The interface `FieldFormalParameterElement` defines the behavior of elements representing a
- * field formal parameter defined within a constructor element.
- */
-abstract class FieldFormalParameterElement implements ParameterElement {
/**
- * Return the field element associated with this field formal parameter, or `null` if the
- * parameter references a field that doesn't exist.
- *
- * @return the field element associated with this field formal parameter
+ * The superclass of the class, or `null` if the class does not have an explicit superclass.
*/
- FieldElement get field;
-}
+ InterfaceType supertype;
-/**
- * The interface `FunctionElement` defines the behavior of elements representing a function.
- */
-abstract class FunctionElement implements ExecutableElement, LocalElement {
/**
- * The name of the synthetic function defined for libraries that are deferred.
+ * An array containing all of the toolkit objects attached to this class.
*/
- static final String LOAD_LIBRARY_NAME = "loadLibrary";
+ List<ToolkitObjectElement> _toolkitObjects = ToolkitObjectElement.EMPTY_ARRAY;
/**
- * Return the resolved [FunctionDeclaration] node that declares this [FunctionElement]
- * .
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * @return the resolved [FunctionDeclaration], not `null`.
- */
- @override
- FunctionDeclaration get node;
-}
-
-/**
- * The interface `FunctionTypeAliasElement` defines the behavior of elements representing a
- * function type alias (`typedef`).
- */
-abstract class FunctionTypeAliasElement implements Element {
- /**
- * Return the compilation unit in which this type alias is defined.
- *
- * @return the compilation unit in which this type alias is defined
+ * The type defined by the class.
*/
- @override
- CompilationUnitElement get enclosingElement;
+ InterfaceType type;
/**
- * Return the resolved [FunctionTypeAlias] node that declares this
- * [FunctionTypeAliasElement] .
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * @return the resolved [FunctionTypeAlias], not `null`.
+ * An array containing all of the type parameters defined for this class.
*/
- @override
- FunctionTypeAlias get node;
+ List<TypeParameterElement> _typeParameters = TypeParameterElementImpl.EMPTY_ARRAY;
/**
- * Return an array containing all of the parameters defined by this type alias.
- *
- * @return the parameters defined by this type alias
+ * An empty array of class elements.
*/
- List<ParameterElement> get parameters;
+ static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>(0);
/**
- * Return the return type defined by this type alias.
+ * Initialize a newly created class element to have the given name.
*
- * @return the return type defined by this type alias
+ * @param name the name of this element
*/
- DartType get returnType;
+ ClassElementImpl(Identifier name) : super.forNode(name);
- /**
- * Return the type of function defined by this type alias.
- *
- * @return the type of function defined by this type alias
- */
- FunctionType get type;
+ @override
+ accept(ElementVisitor visitor) => visitor.visitClassElement(this);
/**
- * Return an array containing all of the type parameters defined for this type.
+ * Set the toolkit specific information objects attached to this class.
*
- * @return the type parameters defined for this type
+ * @param toolkitObjects the toolkit objects attached to this class
*/
- List<TypeParameterElement> get typeParameters;
-}
+ void addToolkitObjects(ToolkitObjectElement toolkitObject) {
+ (toolkitObject as ToolkitObjectElementImpl).enclosingElement = this;
+ _toolkitObjects = ArrayUtils.add(_toolkitObjects, toolkitObject);
+ }
-/**
- * The interface `HideElementCombinator` defines the behavior of combinators that cause some
- * of the names in a namespace to be hidden when being imported.
- */
-abstract class HideElementCombinator implements NamespaceCombinator {
- /**
- * Return an array containing the names that are not to be made visible in the importing library
- * even if they are defined in the imported library.
- *
- * @return the names from the imported library that are hidden from the importing library
- */
- List<String> get hiddenNames;
-}
+ @override
+ List<PropertyAccessorElement> get accessors => _accessors;
-/**
- * The interface `HtmlElement` defines the behavior of elements representing an HTML file.
- */
-abstract class HtmlElement implements Element {
- /**
- * Return the [CompilationUnitElement] associated with this Angular HTML file, maybe
- * `null` if not an Angular file.
- */
- CompilationUnitElement get angularCompilationUnit;
+ @override
+ List<InterfaceType> get allSupertypes {
+ List<InterfaceType> list = new List<InterfaceType>();
+ _collectAllSupertypes(list);
+ return new List.from(list);
+ }
- /**
- * Return an array containing all of the [PolymerTagHtmlElement]s defined in the HTML file.
- *
- * @return the [PolymerTagHtmlElement]s elements in the HTML file (not `null`,
- * contains no `null`s)
- */
- List<PolymerTagHtmlElement> get polymerTags;
+ @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) {
+ if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
+ return accessor as PropertyAccessorElementImpl;
+ }
+ }
+ for (ConstructorElement constructor in _constructors) {
+ if ((constructor as ConstructorElementImpl).identifier == identifier) {
+ return constructor as ConstructorElementImpl;
+ }
+ }
+ for (FieldElement field in _fields) {
+ if ((field as FieldElementImpl).identifier == identifier) {
+ return field as FieldElementImpl;
+ }
+ }
+ for (MethodElement method in _methods) {
+ if ((method as MethodElementImpl).identifier == identifier) {
+ return method as MethodElementImpl;
+ }
+ }
+ for (TypeParameterElement typeParameter in _typeParameters) {
+ if ((typeParameter as TypeParameterElementImpl).identifier == identifier) {
+ return typeParameter as TypeParameterElementImpl;
+ }
+ }
+ return null;
+ }
- /**
- * Return an array containing all of the script elements contained in the HTML file. This includes
- * scripts with libraries that are defined by the content of a script tag as well as libraries
- * that are referenced in the {@core source} attribute of a script tag.
- *
- * @return the script elements in the HTML file (not `null`, contains no `null`s)
- */
- List<HtmlScriptElement> get scripts;
-}
+ @override
+ List<ConstructorElement> get constructors => _constructors;
-/**
- * The interface `HtmlScriptElement` defines the behavior of elements representing a script
- * tag in an HTML file.
- *
- * @see EmbeddedHtmlScriptElement
- * @see ExternalHtmlScriptElement
- */
-abstract class HtmlScriptElement implements Element {
-}
+ @override
+ FieldElement getField(String name) {
+ for (FieldElement fieldElement in _fields) {
+ if (name == fieldElement.name) {
+ return fieldElement;
+ }
+ }
+ return null;
+ }
-/**
- * The interface `ImportElement` defines the behavior of objects representing information
- * about a single import directive within a library.
- */
-abstract class ImportElement implements Element, UriReferencedElement {
- /**
- * An empty array of import elements.
- */
- static final List<ImportElement> EMPTY_ARRAY = new List<ImportElement>(0);
+ @override
+ List<FieldElement> get fields => _fields;
- /**
- * Return an array containing the combinators that were specified as part of the import directive
- * in the order in which they were specified.
- *
- * @return the combinators specified in the import directive
- */
- List<NamespaceCombinator> get combinators;
+ @override
+ PropertyAccessorElement getGetter(String getterName) {
+ for (PropertyAccessorElement accessor in _accessors) {
+ if (accessor.isGetter && accessor.name == getterName) {
+ return accessor;
+ }
+ }
+ return null;
+ }
- /**
- * Return the library that is imported into this library by this import directive.
- *
- * @return the library that is imported into this library
- */
- LibraryElement get importedLibrary;
+ @override
+ ElementKind get kind => ElementKind.CLASS;
- /**
- * Return the prefix that was specified as part of the import directive, or `null` if there
- * was no prefix specified.
- *
- * @return the prefix that was specified as part of the import directive
- */
- PrefixElement get prefix;
+ @override
+ MethodElement getMethod(String methodName) {
+ for (MethodElement method in _methods) {
+ if (method.name == methodName) {
+ return method;
+ }
+ }
+ return null;
+ }
- /**
- * Return the offset of the prefix of this import in the file that contains this import directive,
- * or `-1` if this import is synthetic, does not have a prefix, or otherwise does not have
- * an offset.
- *
- * @return the offset of the prefix of this import
- */
- int get prefixOffset;
+ @override
+ List<MethodElement> get methods => _methods;
- /**
- * Return `true` if this import is for a deferred library.
- *
- * @return `true` if this import is for a deferred library
- */
- bool get isDeferred;
-}
+ @override
+ ConstructorElement getNamedConstructor(String name) {
+ for (ConstructorElement element in constructors) {
+ String elementName = element.name;
+ if (elementName != null && elementName == name) {
+ return element;
+ }
+ }
+ return null;
+ }
-/**
- * The interface `LabelElement` defines the behavior of elements representing a label
- * associated with a statement.
- */
-abstract class LabelElement implements Element {
- /**
- * Return the executable element in which this label is defined.
- *
- * @return the executable element in which this label is defined
- */
@override
- ExecutableElement get enclosingElement;
-}
+ ClassDeclaration get node => getNodeMatching((node) => node is ClassDeclaration);
-/**
- * The interface `LibraryElement` defines the behavior of elements representing a library.
- */
-abstract class LibraryElement implements Element {
- /**
- * Return the compilation unit that defines this library.
- *
- * @return the compilation unit that defines this library
- */
- CompilationUnitElement get definingCompilationUnit;
+ @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
+ List<ToolkitObjectElement> get toolkitObjects => _toolkitObjects;
+
+ @override
+ List<TypeParameterElement> get typeParameters => _typeParameters;
+
+ @override
+ ConstructorElement get unnamedConstructor {
+ for (ConstructorElement element in constructors) {
+ String name = element.displayName;
+ if (name == null || name.isEmpty) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ @override
+ bool get hasNonFinalField {
+ List<ClassElement> classesToVisit = new List<ClassElement>();
+ Set<ClassElement> visitedClasses = new Set<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;
+ }
+
+ @override
+ bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER);
+
+ @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
+ bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+
+ @override
+ bool get isOrInheritsProxy => _safeIsOrInheritsProxy(this, new Set<ClassElement>());
+
+ @override
+ bool get isProxy {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isProxy) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isTypedef => hasModifier(Modifier.TYPEDEF);
+
+ @override
+ bool get isValidMixin => hasModifier(Modifier.MIXIN);
+
+ @override
+ PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library) {
+ Set<ClassElement> visitedClasses = new Set<ClassElement>();
+ ClassElement currentElement = this;
+ while (currentElement != null && !visitedClasses.contains(currentElement)) {
+ visitedClasses.add(currentElement);
+ PropertyAccessorElement element = currentElement.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ for (InterfaceType mixin in currentElement.mixins) {
+ ClassElement mixinElement = mixin.element;
+ if (mixinElement != null) {
+ element = mixinElement.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ }
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype == null) {
+ return null;
+ }
+ currentElement = supertype.element;
+ }
+ return null;
+ }
+
+ @override
+ MethodElement lookUpMethod(String methodName, LibraryElement library) {
+ Set<ClassElement> visitedClasses = new Set<ClassElement>();
+ ClassElement currentElement = this;
+ while (currentElement != null && !visitedClasses.contains(currentElement)) {
+ visitedClasses.add(currentElement);
+ MethodElement element = currentElement.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ for (InterfaceType mixin in currentElement.mixins) {
+ ClassElement mixinElement = mixin.element;
+ if (mixinElement != null) {
+ element = mixinElement.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ }
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype == null) {
+ return null;
+ }
+ currentElement = supertype.element;
+ }
+ return null;
+ }
+
+ @override
+ PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library) {
+ Set<ClassElement> visitedClasses = new Set<ClassElement>();
+ ClassElement currentElement = this;
+ while (currentElement != null && !visitedClasses.contains(currentElement)) {
+ visitedClasses.add(currentElement);
+ PropertyAccessorElement element = currentElement.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ for (InterfaceType mixin in currentElement.mixins) {
+ ClassElement mixinElement = mixin.element;
+ if (mixinElement != null) {
+ element = mixinElement.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ }
+ InterfaceType supertype = currentElement.supertype;
+ if (supertype == null) {
+ return null;
+ }
+ currentElement = supertype.element;
+ }
+ return null;
+ }
/**
- * Return the entry point for this library, or `null` if this library does not have an entry
- * point. The entry point is defined to be a zero argument top-level function whose name is
- * `main`.
+ * Set whether this class is abstract to correspond to the given value.
*
- * @return the entry point for this library
+ * @param isAbstract `true` if the class is abstract
*/
- FunctionElement get entryPoint;
+ void set abstract(bool isAbstract) {
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
/**
- * Return an array containing all of the libraries that are exported from this library.
+ * Set the accessors contained in this class to the given accessors.
*
- * @return an array containing all of the libraries that are exported from this library
+ * @param accessors the accessors contained in this class
*/
- List<LibraryElement> get exportedLibraries;
+ void set accessors(List<PropertyAccessorElement> accessors) {
+ for (PropertyAccessorElement accessor in accessors) {
+ (accessor as PropertyAccessorElementImpl).enclosingElement = this;
+ }
+ this._accessors = accessors;
+ }
/**
- * Return an array containing all of the exports defined in this library.
+ * Set the constructors contained in this class to the given constructors.
*
- * @return the exports defined in this library
+ * @param constructors the constructors contained in this class
*/
- List<ExportElement> get exports;
+ void set constructors(List<ConstructorElement> constructors) {
+ for (ConstructorElement constructor in constructors) {
+ (constructor as ConstructorElementImpl).enclosingElement = this;
+ }
+ this._constructors = constructors;
+ }
/**
- * Return an array containing all of the libraries that are imported into this library. This
- * includes all of the libraries that are imported using a prefix (also available through the
- * prefixes returned by [getPrefixes]) and those that are imported without a prefix.
+ * Set the fields contained in this class to the given fields.
*
- * @return an array containing all of the libraries that are imported into this library
+ * @param fields the fields contained in this class
*/
- List<LibraryElement> get importedLibraries;
+ void set fields(List<FieldElement> fields) {
+ for (FieldElement field in fields) {
+ (field as FieldElementImpl).enclosingElement = this;
+ }
+ this._fields = fields;
+ }
/**
- * Return an array containing all of the imports defined in this library.
+ * Set whether this class references 'super' to the given value.
*
- * @return the imports defined in this library
+ * @param isReferencedSuper `true` references 'super'
*/
- List<ImportElement> get imports;
+ void set hasReferenceToSuper(bool isReferencedSuper) {
+ setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper);
+ }
/**
- * Return an array containing all of the imports that share the given prefix, or an empty array if
- * there are no such imports.
+ * Set the methods contained in this class to the given methods.
*
- * @param prefixElement the prefix element shared by the returned imports
+ * @param methods the methods contained in this class
*/
- List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement);
+ void set methods(List<MethodElement> methods) {
+ for (MethodElement method in methods) {
+ (method as MethodElementImpl).enclosingElement = this;
+ }
+ this._methods = methods;
+ }
/**
- * Return the element representing the synthetic function `loadLibrary` that is implicitly
- * defined for this library if the library is imported using a deferred import.
+ * Set whether this class is defined by a typedef construct to correspond to the given value.
+ *
+ * @param isTypedef `true` if the class is defined by a typedef construct
*/
- FunctionElement get loadLibraryFunction;
+ void set typedef(bool isTypedef) {
+ setModifier(Modifier.TYPEDEF, isTypedef);
+ }
/**
- * Return an array containing all of the compilation units that are included in this library using
- * a `part` directive. This does not include the defining compilation unit that contains the
- * `part` directives.
+ * Set the type parameters defined for this class to the given type parameters.
*
- * @return the compilation units that are included in this library
+ * @param typeParameters the type parameters defined for this class
*/
- List<CompilationUnitElement> get parts;
+ void set typeParameters(List<TypeParameterElement> typeParameters) {
+ for (TypeParameterElement typeParameter in typeParameters) {
+ (typeParameter as TypeParameterElementImpl).enclosingElement = this;
+ }
+ this._typeParameters = typeParameters;
+ }
/**
- * Return an array containing elements for each of the prefixes used to `import` libraries
- * into this library. Each prefix can be used in more than one `import` directive.
+ * Set whether this class is a valid mixin to correspond to the given value.
*
- * @return the prefixes used to `import` libraries into this library
+ * @param isValidMixin `true` if this class can be used as a mixin
*/
- List<PrefixElement> get prefixes;
+ void set validMixin(bool isValidMixin) {
+ setModifier(Modifier.MIXIN, isValidMixin);
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(_accessors, visitor);
+ safelyVisitChildren(_constructors, visitor);
+ safelyVisitChildren(_fields, visitor);
+ safelyVisitChildren(_methods, visitor);
+ safelyVisitChildren(_toolkitObjects, visitor);
+ safelyVisitChildren(_typeParameters, visitor);
+ }
+
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ String name = displayName;
+ if (name == null) {
+ builder.append("{unnamed class}");
+ } else {
+ builder.append(name);
+ }
+ int variableCount = _typeParameters.length;
+ if (variableCount > 0) {
+ builder.append("<");
+ for (int i = 0; i < variableCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ (_typeParameters[i] as TypeParameterElementImpl).appendTo(builder);
+ }
+ builder.append(">");
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+ }
+
+ bool _safeIsOrInheritsProxy(ClassElement classElt, Set<ClassElement> visitedClassElts) {
+ if (visitedClassElts.contains(classElt)) {
+ return false;
+ }
+ visitedClassElts.add(classElt);
+ if (classElt.isProxy) {
+ return true;
+ } else if (classElt.supertype != null && _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) {
+ return true;
+ }
+ List<InterfaceType> supertypes = classElt.interfaces;
+ for (int i = 0; i < supertypes.length; i++) {
+ if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) {
+ return true;
+ }
+ }
+ supertypes = classElt.mixins;
+ for (int i = 0; i < supertypes.length; i++) {
+ if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+/**
+ * The interface `ClassMemberElement` defines the behavior of elements that are contained
+ * within a [ClassElement].
+ */
+abstract class ClassMemberElement implements Element {
/**
- * Return the class defined in this library that has the given name, or `null` if this
- * library does not define a class with the given name.
+ * Return the type in which this member is defined.
*
- * @param className the name of the class to be returned
- * @return the class with the given name that is defined in this library
+ * @return the type in which this member is defined
*/
- ClassElement getType(String className);
+ @override
+ ClassElement get enclosingElement;
/**
- * Return an array containing all of the compilation units this library consists of. This includes
- * the defining compilation unit and units included using the `part` directive.
+ * Return `true` if this element is a static element. A static element is an element that is
+ * not associated with a particular instance, but rather with an entire library or class.
*
- * @return the compilation units this library consists of
+ * @return `true` if this executable element is a static element
*/
- List<CompilationUnitElement> get units;
+ bool get isStatic;
+}
+/**
+ * The interface `CompilationUnitElement` defines the behavior of elements representing a
+ * compilation unit.
+ */
+abstract class CompilationUnitElement implements Element, UriReferencedElement {
/**
- * Return an array containing all directly and indirectly imported libraries.
+ * Return an array containing all of the top-level accessors (getters and setters) contained in
+ * this compilation unit.
*
- * @return all directly and indirectly imported libraries
+ * @return the top-level accessors contained in this compilation unit
*/
- List<LibraryElement> get visibleLibraries;
+ List<PropertyAccessorElement> get accessors;
/**
- * Return `true` if the defining compilation unit of this library contains at least one
- * import directive whose URI uses the "dart-ext" scheme.
+ * Return an array containing all of the Angular views defined in this compilation unit. The array
+ * will be empty if the element does not have any Angular views or if the compilation unit has not
+ * yet had toolkit references resolved.
+ *
+ * @return the Angular views defined in this compilation unit.
*/
- bool get hasExtUri;
+ List<AngularViewElement> get angularViews;
/**
- * Return `true` if this library defines a top-level function named `loadLibrary`.
+ * Return the library in which this compilation unit is defined.
*
- * @return `true` if this library defines a top-level function named `loadLibrary`
+ * @return the library in which this compilation unit is defined
*/
- bool get hasLoadLibraryFunction;
+ @override
+ LibraryElement get enclosingElement;
/**
- * Return `true` if this library is created for Angular analysis. If this library has not
- * yet had toolkit references resolved, then `false` will be returned.
+ * Return an array containing all of the top-level functions contained in this compilation unit.
*
- * @return `true` if this library is created for Angular analysis
+ * @return the top-level functions contained in this compilation unit
*/
- bool get isAngularHtml;
+ List<FunctionElement> get functions;
/**
- * Return `true` if this library is an application that can be run in the browser.
+ * Return an array containing all of the function type aliases contained in this compilation unit.
*
- * @return `true` if this library is an application that can be run in the browser
+ * @return the function type aliases contained in this compilation unit
*/
- bool get isBrowserApplication;
+ List<FunctionTypeAliasElement> get functionTypeAliases;
/**
- * Return `true` if this library is the dart:core library.
+ * Return the resolved [CompilationUnit] node that declares this element.
*
- * @return `true` if this library is the dart:core library
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
+ *
+ * @return the resolved [CompilationUnit], not `null`.
*/
- bool get isDartCore;
+ @override
+ CompilationUnit get node;
/**
- * Return `true` if this library is the dart:core library.
+ * Return an array containing all of the top-level variables contained in this compilation unit.
*
- * @return `true` if this library is the dart:core library
+ * @return the top-level variables contained in this compilation unit
*/
- bool get isInSdk;
+ List<TopLevelVariableElement> get topLevelVariables;
/**
- * Return `true` if this library is up to date with respect to the given time stamp. If any
- * transitively referenced Source is newer than the time stamp, this method returns false.
+ * Return the class defined in this compilation unit that has the given name, or `null` if
+ * this compilation unit does not define a class with the given name.
*
- * @param timeStamp the time stamp to compare against
- * @return `true` if this library is up to date with respect to the given time stamp
+ * @param className the name of the class to be returned
+ * @return the class with the given name that is defined in this compilation unit
*/
- bool isUpToDate(int timeStamp);
-}
+ ClassElement getType(String className);
-/**
- * The interface `LocalElement` defines the behavior of elements that can be (but are not
- * required to be) defined within a method or function (an [ExecutableElement]).
- */
-abstract class LocalElement implements Element {
/**
- * Return a source range that covers the approximate portion of the source in which the name of
- * this element is visible, or `null` if there is no single range of characters within which
- * the element name is visible.
- * * For a local variable, this includes everything from the end of the variable's initializer
- * to the end of the block that encloses the variable declaration.
- * * For a parameter, this includes the body of the method or function that declares the
- * parameter.
- * * For a local function, this includes everything from the beginning of the function's body to
- * the end of the block that encloses the function declaration.
- * * For top-level functions, `null` will be returned because they are potentially visible
- * in multiple sources.
+ * Return an array containing all of the classes contained in this compilation unit.
*
- * @return the range of characters in which the name of this element is visible
+ * @return the classes contained in this compilation unit
*/
- SourceRange get visibleRange;
-}
+ List<ClassElement> get types;
-/**
- * The interface `LocalVariableElement` defines the behavior common to elements that represent
- * a local variable.
- */
-abstract class LocalVariableElement implements LocalElement, VariableElement {
/**
- * Return an array containing all of the toolkit specific objects attached to this variable.
+ * Return `true` if this compilation unit defines a top-level function named
+ * `loadLibrary`.
*
- * @return the toolkit objects attached to this variable
+ * @return `true` if this compilation unit defines a top-level function named
+ * `loadLibrary`
*/
- List<ToolkitObjectElement> get toolkitObjects;
+ bool get hasLoadLibraryFunction;
}
/**
- * The interface `MethodElement` defines the behavior of elements that represent a method
- * defined within a type.
+ * Instances of the class `CompilationUnitElementImpl` implement a
+ * [CompilationUnitElement].
*/
-abstract class MethodElement implements ClassMemberElement, ExecutableElement {
+class CompilationUnitElementImpl extends UriReferencedElementImpl implements CompilationUnitElement {
/**
- * Return the resolved [MethodDeclaration] node that declares this [MethodElement].
- *
- * This method is expensive, because resolved AST might be evicted from cache, so parsing and
- * resolving will be performed.
- *
- * @return the resolved [MethodDeclaration], not `null`.
+ * An empty array of compilation unit elements.
*/
- @override
- MethodDeclaration get node;
+ static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElement>(0);
/**
- * Return `true` if this method is abstract. Methods are abstract if they are not external
- * and have no body.
- *
- * @return `true` if this method is abstract
+ * The source that corresponds to this compilation unit.
*/
- bool get isAbstract;
-}
+ Source source;
-/**
- * The interface `MultiplyDefinedElement` defines the behavior of pseudo-elements that
- * represent multiple elements defined within a single scope that have the same name. This situation
- * is not allowed by the language, so objects implementing this interface always represent an error.
- * As a result, most of the normal operations on elements do not make sense and will return useless
- * results.
- */
-abstract class MultiplyDefinedElement implements Element {
/**
- * Return an array containing all of the elements that were defined within the scope to have the
- * same name.
- *
- * @return the elements that were defined with the same name
+ * An array containing all of the top-level accessors (getters and setters) contained in this
+ * compilation unit.
*/
- List<Element> get conflictingElements;
+ List<PropertyAccessorElement> _accessors = PropertyAccessorElementImpl.EMPTY_ARRAY;
/**
- * Return the type of this element as the dynamic type.
- *
- * @return the type of this element as the dynamic type
+ * An array containing all of the top-level functions contained in this compilation unit.
*/
- DartType get type;
-}
+ List<FunctionElement> _functions = FunctionElementImpl.EMPTY_ARRAY;
-/**
- * The interface [MultiplyInheritedExecutableElement] defines all of the behavior of an
- * [ExecutableElement], with the additional information of an array of
- * [ExecutableElement]s from which this element was composed.
- */
-abstract class MultiplyInheritedExecutableElement implements ExecutableElement {
/**
- * Return an array containing all of the executable elements defined within this executable
- * element.
- *
- * @return the elements defined within this executable element
+ * A table mapping elements to associated toolkit objects.
*/
- List<ExecutableElement> get inheritedElements;
-}
+ Map<Element, List<ToolkitObjectElement>> _toolkitObjects = {};
-/**
- * The interface `NamespaceCombinator` defines the behavior common to objects that control how
- * namespaces are combined.
- */
-abstract class NamespaceCombinator {
/**
- * An empty array of namespace combinators.
+ * An array containing all of the function type aliases contained in this compilation unit.
*/
- static final List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>(0);
-}
+ List<FunctionTypeAliasElement> _typeAliases = FunctionTypeAliasElementImpl.EMPTY_ARRAY;
-/**
- * The interface `ParameterElement` defines the behavior of elements representing a parameter
- * defined within an executable element.
- */
-abstract class ParameterElement implements LocalElement, VariableElement {
/**
- * Return a source range that covers the portion of the source in which the default value for this
- * parameter is specified, or `null` if there is no default value.
- *
- * @return the range of characters in which the default value of this parameter is specified
+ * An array containing all of the types contained in this compilation unit.
*/
- SourceRange get defaultValueRange;
+ List<ClassElement> _types = ClassElementImpl.EMPTY_ARRAY;
/**
- * Return the kind of this parameter.
- *
- * @return the kind of this parameter
+ * An array containing all of the variables contained in this compilation unit.
*/
- ParameterKind get parameterKind;
+ List<TopLevelVariableElement> _variables = TopLevelVariableElementImpl.EMPTY_ARRAY;
/**
- * Return an array containing all of the parameters defined by this parameter. A parameter will
- * only define other parameters if it is a function typed parameter.
- *
- * @return the parameters defined by this parameter element
+ * An array containing all of the Angular views contained in this compilation unit.
*/
- List<ParameterElement> get parameters;
+ List<AngularViewElement> _angularViews = AngularViewElement.EMPTY_ARRAY;
/**
- * Return `true` if this parameter is an initializing formal parameter.
+ * Initialize a newly created compilation unit element to have the given name.
*
- * @return `true` if this parameter is an initializing formal parameter
+ * @param name the name of this element
*/
- bool get isInitializingFormal;
-}
+ CompilationUnitElementImpl(String name) : super(name, -1);
-/**
- * The interface `PrefixElement` defines the behavior common to elements that represent a
- * prefix used to import one or more libraries into another library.
- */
-abstract class PrefixElement implements Element {
- /**
- * Return the library into which other libraries are imported using this prefix.
- *
- * @return the library into which other libraries are imported using this prefix
- */
@override
- LibraryElement get enclosingElement;
+ accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this);
+
+ @override
+ bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && source == (object as CompilationUnitElementImpl).source;
+
+ @override
+ List<PropertyAccessorElement> get accessors => _accessors;
+
+ @override
+ List<AngularViewElement> get angularViews => _angularViews;
+
+ @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) {
+ if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
+ return accessor as PropertyAccessorElementImpl;
+ }
+ }
+ for (VariableElement variable in _variables) {
+ if ((variable as VariableElementImpl).identifier == identifier) {
+ return variable as VariableElementImpl;
+ }
+ }
+ for (ExecutableElement function in _functions) {
+ if ((function as ExecutableElementImpl).identifier == identifier) {
+ return function as ExecutableElementImpl;
+ }
+ }
+ for (FunctionTypeAliasElement typeAlias in _typeAliases) {
+ if ((typeAlias as FunctionTypeAliasElementImpl).identifier == identifier) {
+ return typeAlias as FunctionTypeAliasElementImpl;
+ }
+ }
+ for (ClassElement type in _types) {
+ if ((type as ClassElementImpl).identifier == identifier) {
+ return type as ClassElementImpl;
+ }
+ }
+ return null;
+ }
+
+ @override
+ LibraryElement get enclosingElement => super.enclosingElement as LibraryElement;
+
+ @override
+ List<FunctionElement> get functions => _functions;
+
+ @override
+ List<FunctionTypeAliasElement> get functionTypeAliases => _typeAliases;
+
+ @override
+ ElementKind get kind => ElementKind.COMPILATION_UNIT;
+
+ @override
+ CompilationUnit get node => unit;
+
+ @override
+ List<TopLevelVariableElement> get topLevelVariables => _variables;
+
+ @override
+ ClassElement getType(String className) {
+ for (ClassElement type in _types) {
+ if (type.name == className) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ @override
+ List<ClassElement> get types => _types;
+
+ @override
+ int get hashCode => source.hashCode;
+
+ @override
+ bool get hasLoadLibraryFunction {
+ for (int i = 0; i < _functions.length; i++) {
+ if (_functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) {
+ return true;
+ }
+ }
+ return false;
+ }
/**
- * Return an array containing all of the libraries that are imported using this prefix.
+ * Set the top-level accessors (getters and setters) contained in this compilation unit to the
+ * given accessors.
*
- * @return the libraries that are imported using this prefix
+ * @param the top-level accessors (getters and setters) contained in this compilation unit
*/
- List<LibraryElement> get importedLibraries;
-}
+ void set accessors(List<PropertyAccessorElement> accessors) {
+ for (PropertyAccessorElement accessor in accessors) {
+ (accessor as PropertyAccessorElementImpl).enclosingElement = this;
+ }
+ this._accessors = accessors;
+ }
-/**
- * The interface `PropertyAccessorElement` defines the behavior of elements representing a
- * getter or a setter. Note that explicitly defined property accessors implicitly define a synthetic
- * field. Symmetrically, synthetic accessors are implicitly created for explicitly defined fields.
- * The following rules apply:
- * * Every explicit field is represented by a non-synthetic [FieldElement].
- * * Every explicit field induces a getter and possibly a setter, both of which are represented by
- * synthetic [PropertyAccessorElement]s.
- * * Every explicit getter or setter is represented by a non-synthetic
- * [PropertyAccessorElement].
- * * Every explicit getter or setter (or pair thereof if they have the same name) induces a field
- * that is represented by a synthetic [FieldElement].
- */
-abstract class PropertyAccessorElement implements ExecutableElement {
/**
- * Return the accessor representing the getter that corresponds to (has the same name as) this
- * setter, or `null` if this accessor is not a setter or if there is no corresponding
- * getter.
+ * Set the Angular views defined in this compilation unit.
*
- * @return the getter that corresponds to this setter
+ * @param angularViews the Angular views defined in this compilation unit
*/
- PropertyAccessorElement get correspondingGetter;
+ void set angularViews(List<AngularViewElement> angularViews) {
+ for (AngularViewElement view in angularViews) {
+ (view as AngularViewElementImpl).enclosingElement = this;
+ }
+ this._angularViews = angularViews;
+ }
/**
- * Return the accessor representing the setter that corresponds to (has the same name as) this
- * getter, or `null` if this accessor is not a getter or if there is no corresponding
- * setter.
+ * Set the top-level functions contained in this compilation unit to the given functions.
*
- * @return the setter that corresponds to this getter
+ * @param functions the top-level functions contained in this compilation unit
*/
- PropertyAccessorElement get correspondingSetter;
+ void set functions(List<FunctionElement> functions) {
+ for (FunctionElement function in functions) {
+ (function as FunctionElementImpl).enclosingElement = this;
+ }
+ this._functions = functions;
+ }
/**
- * Return the field or top-level variable associated with this accessor. If this accessor was
- * explicitly defined (is not synthetic) then the variable associated with it will be synthetic.
+ * Set the top-level variables contained in this compilation unit to the given variables.
*
- * @return the variable associated with this accessor
+ * @param variables the top-level variables contained in this compilation unit
*/
- PropertyInducingElement get variable;
+ void set topLevelVariables(List<TopLevelVariableElement> variables) {
+ for (TopLevelVariableElement field in variables) {
+ (field as TopLevelVariableElementImpl).enclosingElement = this;
+ }
+ this._variables = variables;
+ }
/**
- * Return `true` if this accessor is abstract. Accessors are abstract if they are not
- * external and have no body.
+ * Set the function type aliases contained in this compilation unit to the given type aliases.
*
- * @return `true` if this accessor is abstract
+ * @param typeAliases the function type aliases contained in this compilation unit
*/
- bool get isAbstract;
+ void set typeAliases(List<FunctionTypeAliasElement> typeAliases) {
+ for (FunctionTypeAliasElement typeAlias in typeAliases) {
+ (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this;
+ }
+ this._typeAliases = typeAliases;
+ }
/**
- * Return `true` if this accessor represents a getter.
+ * Set the types contained in this compilation unit to the given types.
*
- * @return `true` if this accessor represents a getter
+ * @param types types contained in this compilation unit
*/
- bool get isGetter;
+ void set types(List<ClassElement> types) {
+ for (ClassElement type in types) {
+ (type as ClassElementImpl).enclosingElement = this;
+ }
+ this._types = types;
+ }
- /**
- * Return `true` if this accessor represents a setter.
- *
- * @return `true` if this accessor represents a setter
- */
- bool get isSetter;
-}
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(_accessors, visitor);
+ safelyVisitChildren(_functions, visitor);
+ safelyVisitChildren(_typeAliases, visitor);
+ safelyVisitChildren(_types, visitor);
+ safelyVisitChildren(_variables, visitor);
+ safelyVisitChildren(_angularViews, visitor);
+ }
-/**
- * The interface `PropertyInducingElement` defines the behavior of elements representing a
- * variable that has an associated getter and possibly a setter. Note that explicitly defined
- * variables implicitly define a synthetic getter and that non-`final` explicitly defined
- * variables implicitly define a synthetic setter. Symmetrically, synthetic fields are implicitly
- * created for explicitly defined getters and setters. The following rules apply:
- * * Every explicit variable is represented by a non-synthetic [PropertyInducingElement].
- * * Every explicit variable induces a getter and possibly a setter, both of which are represented
- * by synthetic [PropertyAccessorElement]s.
- * * Every explicit getter or setter is represented by a non-synthetic
- * [PropertyAccessorElement].
- * * Every explicit getter or setter (or pair thereof if they have the same name) induces a
- * variable that is represented by a synthetic [PropertyInducingElement].
- */
-abstract class PropertyInducingElement implements VariableElement {
- /**
- * Return the getter associated with this variable. If this variable was explicitly defined (is
- * not synthetic) then the getter associated with it will be synthetic.
- *
- * @return the getter associated with this variable
- */
- PropertyAccessorElement get getter;
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ if (source == null) {
+ builder.append("{compilation unit}");
+ } else {
+ builder.append(source.fullName);
+ }
+ }
+
+ @override
+ String get identifier => source.encoding;
/**
- * Return the setter associated with this variable, or `null` if the variable is effectively
- * `final` and therefore does not have a setter associated with it. (This can happen either
- * because the variable is explicitly defined as being `final` or because the variable is
- * induced by an explicit getter that does not have a corresponding setter.) If this variable was
- * explicitly defined (is not synthetic) then the setter associated with it will be synthetic.
+ * Returns the associated toolkit objects.
*
- * @return the setter associated with this variable
+ * @param element the [Element] to get toolkit objects for
+ * @return the associated toolkit objects, may be empty, but not `null`
*/
- PropertyAccessorElement get setter;
+ List<ToolkitObjectElement> _getToolkitObjects(Element element) {
+ List<ToolkitObjectElement> objects = _toolkitObjects[element];
+ if (objects != null) {
+ return objects;
+ }
+ return ToolkitObjectElement.EMPTY_ARRAY;
+ }
/**
- * Return `true` if this element is a static element. A static element is an element that is
- * not associated with a particular instance, but rather with an entire library or class.
+ * Sets the toolkit objects that are associated with the given [Element].
*
- * @return `true` if this executable element is a static element
+ * @param element the [Element] to associate toolkit objects with
+ * @param objects the toolkit objects to associate
*/
- bool get isStatic;
+ void _setToolkitObjects(Element element, List<ToolkitObjectElement> objects) {
+ _toolkitObjects[element] = objects;
+ }
}
/**
- * The interface `ShowElementCombinator` defines the behavior of combinators that cause some
- * of the names in a namespace to be visible (and the rest hidden) when being imported.
+ * Instances of the class `ConstFieldElementImpl` implement a `FieldElement` for a
+ * 'const' field that has an initializer.
*/
-abstract class ShowElementCombinator implements NamespaceCombinator {
- /**
- * Return the offset of the character immediately following the last character of this node.
- *
- * @return the offset of the character just past this node
- */
- int get end;
-
+class ConstFieldElementImpl extends FieldElementImpl {
/**
- * Return the offset of the 'show' keyword of this element.
- *
- * @return the offset of the 'show' keyword of this element
+ * The result of evaluating this variable's initializer.
*/
- int get offset;
+ EvaluationResultImpl _result;
/**
- * Return an array containing the names that are to be made visible in the importing library if
- * they are defined in the imported library.
+ * Initialize a newly created field element to have the given name.
*
- * @return the names from the imported library that are visible in the importing library
+ * @param name the name of this element
*/
- List<String> get shownNames;
-}
+ ConstFieldElementImpl(Identifier name) : super.con1(name);
-/**
- * The interface `ToolkitObjectElement` defines the behavior of elements that represent a
- * toolkit specific object, such as Angular controller or component. These elements are not based on
- * the Dart syntax, but on some semantic agreement, such as a special annotation.
- */
-abstract class ToolkitObjectElement implements Element {
- /**
- * An empty array of toolkit object elements.
- */
- static final List<ToolkitObjectElement> EMPTY_ARRAY = new List<ToolkitObjectElement>(0);
-}
+ @override
+ EvaluationResultImpl get evaluationResult => _result;
-/**
- * The interface `TopLevelVariableElement` defines the behavior of elements representing a
- * top-level variable.
- */
-abstract class TopLevelVariableElement implements PropertyInducingElement {
+ @override
+ void set evaluationResult(EvaluationResultImpl result) {
+ this._result = result;
+ }
}
/**
- * The interface `TypeParameterElement` defines the behavior of elements representing a type
- * parameter.
+ * Instances of the class `ConstLocalVariableElementImpl` implement a
+ * `LocalVariableElement` for a local 'const' variable that has an initializer.
*/
-abstract class TypeParameterElement implements Element {
+class ConstLocalVariableElementImpl extends LocalVariableElementImpl {
/**
- * Return the type representing the bound associated with this parameter, or `null` if this
- * parameter does not have an explicit bound.
- *
- * @return the type representing the bound associated with this parameter
+ * The result of evaluating this variable's initializer.
*/
- DartType get bound;
+ EvaluationResultImpl _result;
/**
- * Return the type defined by this type parameter.
+ * Initialize a newly created local variable element to have the given name.
*
- * @return the type defined by this type parameter
+ * @param name the name of this element
*/
- TypeParameterType get type;
-}
+ ConstLocalVariableElementImpl(Identifier name) : super(name);
-/**
- * The interface `UndefinedElement` defines the behavior of pseudo-elements that represent
- * names that are undefined. This situation is not allowed by the language, so objects implementing
- * this interface always represent an error. As a result, most of the normal operations on elements
- * do not make sense and will return useless results.
- */
-abstract class UndefinedElement implements Element {
+ @override
+ EvaluationResultImpl get evaluationResult => _result;
+
+ @override
+ void set evaluationResult(EvaluationResultImpl result) {
+ this._result = result;
+ }
}
/**
- * The interface `UriReferencedElement` defines the behavior of objects included into a
- * library using some URI.
+ * Instances of the class `ConstTopLevelVariableElementImpl` implement a
+ * `TopLevelVariableElement` for a top-level 'const' variable that has an initializer.
*/
-abstract class UriReferencedElement implements Element {
+class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl {
/**
- * Return the offset of the character immediately following the last character of this node's URI,
- * or `-1` for synthetic import.
- *
- * @return the offset of the character just past the node's URI
+ * The result of evaluating this variable's initializer.
*/
- int get uriEnd;
+ EvaluationResultImpl _result;
/**
- * Return the offset of the URI in the file, or `-1` if this element is synthetic.
+ * Initialize a newly created top-level variable element to have the given name.
*
- * @return the offset of the URI
+ * @param name the name of this element
*/
- int get uriOffset;
+ ConstTopLevelVariableElementImpl(Identifier name) : super.con1(name);
- /**
- * Return the URI that is used to include this element into the enclosing library, or `null`
- * if this is the defining compilation unit of a library.
- *
- * @return the URI that is used to include this element into the enclosing library
- */
- String get uri;
+ @override
+ EvaluationResultImpl get evaluationResult => _result;
+
+ @override
+ void set evaluationResult(EvaluationResultImpl result) {
+ this._result = result;
+ }
}
/**
- * The interface `VariableElement` defines the behavior common to elements that represent a
- * variable.
+ * The interface `ConstructorElement` defines the behavior of elements representing a
+ * constructor or a factory method defined within a type.
*/
-abstract class VariableElement implements Element {
- /**
- * Return a synthetic function representing this variable's initializer, or `null` if this
- * variable does not have an initializer. The function will have no parameters. The return type of
- * the function will be the compile-time type of the initialization expression.
- *
- * @return a synthetic function representing this variable's initializer
- */
- FunctionElement get initializer;
-
+abstract class ConstructorElement implements ClassMemberElement, ExecutableElement {
/**
- * Return the resolved [VariableDeclaration] node that declares this [VariableElement]
- * .
+ * Return the resolved [ConstructorDeclaration] node that declares this
+ * [ConstructorElement] .
*
* This method is expensive, because resolved AST might be evicted from cache, so parsing and
* resolving will be performed.
*
- * @return the resolved [VariableDeclaration], not `null`.
+ * @return the resolved [ConstructorDeclaration], not `null`.
*/
@override
- VariableDeclaration get node;
+ ConstructorDeclaration get node;
/**
- * Return the declared type of this variable, or `null` if the variable did not have a
- * declared type (such as if it was declared using the keyword 'var').
+ * Return the constructor to which this constructor is redirecting, or `null` if this constructor
+ * does not redirect to another constructor or if the library containing this constructor has
+ * not yet been resolved.
*
- * @return the declared type of this variable
+ * @return the constructor to which this constructor is redirecting
*/
- DartType get type;
+ ConstructorElement get redirectedConstructor;
/**
- * Return `true` if this variable was declared with the 'const' modifier.
+ * Return `true` if this constructor is a const constructor.
*
- * @return `true` if this variable was declared with the 'const' modifier
+ * @return `true` if this constructor is a const constructor
*/
bool get isConst;
/**
- * Return `true` if this variable was declared with the 'final' modifier. Variables that are
- * declared with the 'const' modifier will return `false` even though they are implicitly
- * final.
+ * Return `true` if this constructor can be used as a default constructor - unnamed and has
+ * no required parameters.
*
- * @return `true` if this variable was declared with the 'final' modifier
- */
- bool get isFinal;
-}
-
-/**
- * The interface `AngularControllerElement` defines the Angular component described by
- * <code>Component</code> annotation.
- */
-abstract class AngularComponentElement implements AngularHasSelectorElement, AngularHasTemplateElement {
- /**
- * Return an array containing all of the properties declared by this component.
- */
- List<AngularPropertyElement> get properties;
-
- /**
- * Return an array containing all of the scope properties set in the implementation of this
- * component.
- */
- List<AngularScopePropertyElement> get scopeProperties;
-
- /**
- * Returns the CSS file URI.
+ * @return `true` if this constructor can be used as a default constructor.
*/
- String get styleUri;
+ bool get isDefaultConstructor;
/**
- * Return the offset of the [getStyleUri] in the [getSource].
+ * Return `true` if this constructor represents a factory constructor.
*
- * @return the offset of the style URI
+ * @return `true` if this constructor represents a factory constructor
*/
- int get styleUriOffset;
-}
-
-/**
- * The interface `AngularControllerElement` defines the Angular controller described by
- * <code>Controller</code> annotation.
- */
-abstract class AngularControllerElement implements AngularHasSelectorElement {
+ bool get isFactory;
}
/**
- * The interface `AngularDirectiveElement` defines the Angular controller described by
- * <code>Decorator</code> annotation.
+ * Instances of the class `ConstructorElementImpl` implement a `ConstructorElement`.
*/
-abstract class AngularDecoratorElement implements AngularHasSelectorElement {
+class ConstructorElementImpl extends ExecutableElementImpl implements ConstructorElement {
/**
- * Return an array containing all of the properties declared by this directive.
+ * An empty array of constructor elements.
*/
- List<AngularPropertyElement> get properties;
+ static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>(0);
/**
- * Checks if this directive is implemented by the class with given name.
+ * The constructor to which this constructor is redirecting.
*/
- bool isClass(String name);
-}
+ ConstructorElement redirectedConstructor;
-/**
- * The interface `AngularElement` defines the behavior of objects representing information
- * about an Angular specific element.
- */
-abstract class AngularElement implements ToolkitObjectElement {
/**
- * An empty array of Angular elements.
+ * Initialize a newly created constructor element to have the given name.
+ *
+ * @param name the name of this element
*/
- static final List<AngularElement> EMPTY_ARRAY = new List<AngularElement>(0);
+ ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
/**
- * Returns the [AngularApplication] this element is used in.
+ * Initialize a newly created constructor element to have the given name.
*
- * @return the [AngularApplication] this element is used in
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- AngularApplication get application;
-}
+ ConstructorElementImpl(String name, int nameOffset) : super(name, nameOffset);
-/**
- * The interface `AngularFormatterElement` defines the Angular formatter described by
- * <code>Formatter</code> annotation.
- */
-abstract class AngularFormatterElement implements AngularElement {
-}
+ @override
+ accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
-/**
- * [AngularSelectorElement] based on presence of attribute.
- */
-abstract class AngularHasAttributeSelectorElement implements AngularSelectorElement {
-}
+ @override
+ ClassElement get enclosingElement => super.enclosingElement as ClassElement;
-/**
- * [AngularSelectorElement] based on presence of a class.
- */
-abstract class AngularHasClassSelectorElement implements AngularSelectorElement {
-}
+ @override
+ ElementKind get kind => ElementKind.CONSTRUCTOR;
-/**
- * The interface `AngularElement` defines the behavior of objects representing information
- * about an Angular element which is applied conditionally using some [AngularSelectorElement].
- */
-abstract class AngularHasSelectorElement implements AngularElement {
- /**
- * Returns the selector specified for this element.
- *
- * @return the [AngularSelectorElement] specified for this element
- */
- AngularSelectorElement get selector;
-}
+ @override
+ ConstructorDeclaration get node => getNodeMatching((node) => node is ConstructorDeclaration);
-/**
- * The interface `AngularHasTemplateElement` defines common behavior for
- * [AngularElement] that have template URI / [Source].
- */
-abstract class AngularHasTemplateElement implements AngularElement {
- /**
- * Returns the HTML template [Source], `null` if not resolved.
- */
- Source get templateSource;
+ @override
+ bool get isConst => hasModifier(Modifier.CONST);
- /**
- * Returns the HTML template URI.
- */
- String get templateUri;
+ @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;
+ }
- /**
- * Return the offset of the [getTemplateUri] in the [getSource].
- *
- * @return the offset of the template URI
- */
- int get templateUriOffset;
-}
+ @override
+ bool get isFactory => hasModifier(Modifier.FACTORY);
-/**
- * The interface `AngularPropertyElement` defines a single property in
- * [AngularComponentElement].
- */
-abstract class AngularPropertyElement implements AngularElement {
- /**
- * An empty array of property elements.
- */
- static final List<AngularPropertyElement> EMPTY_ARRAY = [];
+ @override
+ bool get isStatic => false;
/**
- * Returns the field this property is mapped to.
+ * Set whether this constructor represents a 'const' constructor to the given value.
*
- * @return the field this property is mapped to.
+ * @param isConst `true` if this constructor represents a 'const' constructor
*/
- FieldElement get field;
+ void set const2(bool isConst) {
+ setModifier(Modifier.CONST, isConst);
+ }
/**
- * Return the offset of the field name of this property in the property map, or `-1` if
- * property was created using annotation on [FieldElement].
+ * Set whether this constructor represents a factory method to the given value.
*
- * @return the offset of the field name of this property
+ * @param isFactory `true` if this constructor represents a factory method
*/
- int get fieldNameOffset;
+ void set factory(bool isFactory) {
+ setModifier(Modifier.FACTORY, isFactory);
+ }
- /**
- * Returns the kind of this property.
- *
- * @return the kind of this property
- */
- AngularPropertyKind get propertyKind;
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(enclosingElement.displayName);
+ String name = displayName;
+ if (name != null && !name.isEmpty) {
+ builder.append(".");
+ builder.append(name);
+ }
+ super.appendTo(builder);
+ }
}
/**
- * The enumeration `AngularPropertyKind` defines the different kinds of property bindings.
+ * Instances of the class `ConstructorMember` represent a constructor element defined in a
+ * parameterized type where the values of the type parameters are known.
*/
-class AngularPropertyKind extends Enum<AngularPropertyKind> {
+class ConstructorMember extends ExecutableMember implements ConstructorElement {
/**
- * `@` - Map the DOM attribute string. The attribute string will be taken literally or
- * interpolated if it contains binding {{}} syntax and assigned to the expression. (cost: 0
- * watches)
+ * If the given constructor's type is different when any type parameters from the defining type's
+ * declaration are replaced with the actual type arguments from the defining type, create a
+ * constructor member representing the given constructor. Return the member that was created, or
+ * the base constructor if no member was created.
+ *
+ * @param baseConstructor the base constructor for which a member might be created
+ * @param definingType the type defining the parameters and arguments to be used in the
+ * substitution
+ * @return the constructor element that will return the correctly substituted types
*/
- static const AngularPropertyKind ATTR = const AngularPropertyKind('ATTR', 0);
+ static ConstructorElement from(ConstructorElement baseConstructor, InterfaceType definingType) {
+ if (baseConstructor == null || definingType.typeArguments.length == 0) {
+ return baseConstructor;
+ }
+ FunctionType baseType = baseConstructor.type;
+ if (baseType == null) {
+ // TODO(brianwilkerson) We need to understand when this can happen.
+ return baseConstructor;
+ }
+ List<DartType> argumentTypes = definingType.typeArguments;
+ List<DartType> parameterTypes = definingType.element.type.typeArguments;
+ FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
+ if (baseType == substitutedType) {
+ return baseConstructor;
+ }
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
+ return new ConstructorMember(baseConstructor, definingType);
+ }
/**
- * `&` - Treat the DOM attribute value as an expression. Assign a closure function into the field.
- * This allows the component to control the invocation of the closure. This is useful for passing
- * expressions into controllers which act like callbacks. (cost: 0 watches)
+ * Initialize a newly created element to represent a constructor of the given parameterized type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
*/
- static const AngularPropertyKind CALLBACK = const AngularPropertyKind('CALLBACK', 1);
+ ConstructorMember(ConstructorElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
- /**
- * `=>` - Treat the DOM attribute value as an expression. Set up a watch, which will read the
- * expression in the attribute and assign the value to destination expression. (cost: 1 watch)
- */
- static const AngularPropertyKind ONE_WAY = const AngularPropertyKind('ONE_WAY', 2);
+ @override
+ accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
- /**
- * `=>!` - Treat the DOM attribute value as an expression. Set up a one time watch on expression.
- * Once the expression turns not null it will no longer update. (cost: 1 watches until not null,
- * then 0 watches)
- */
- static const AngularPropertyKind ONE_WAY_ONE_TIME = const AngularPropertyKind('ONE_WAY_ONE_TIME', 3);
+ @override
+ ConstructorElement get baseElement => super.baseElement as ConstructorElement;
- /**
- * `<=>` - Treat the DOM attribute value as an expression. Set up a watch on both outside as well
- * as component scope to keep the source and destination in sync. (cost: 2 watches)
- */
- static const AngularPropertyKind TWO_WAY = const AngularPropertyKind_TWO_WAY('TWO_WAY', 4);
+ @override
+ ClassElement get enclosingElement => baseElement.enclosingElement;
- static const List<AngularPropertyKind> values = const [ATTR, CALLBACK, ONE_WAY, ONE_WAY_ONE_TIME, TWO_WAY];
+ @override
+ ConstructorDeclaration get node => baseElement.node;
- /**
- * Returns `true` if property of this kind calls field getter.
- */
- bool callsGetter() => false;
+ @override
+ ConstructorElement get redirectedConstructor => from(baseElement.redirectedConstructor, definingType);
- /**
- * Returns `true` if property of this kind calls field setter.
- */
- bool callsSetter() => true;
+ @override
+ bool get isConst => baseElement.isConst;
- const AngularPropertyKind(String name, int ordinal) : super(name, ordinal);
-}
+ @override
+ bool get isDefaultConstructor => baseElement.isDefaultConstructor;
-class AngularPropertyKind_TWO_WAY extends AngularPropertyKind {
- const AngularPropertyKind_TWO_WAY(String name, int ordinal) : super(name, ordinal);
+ @override
+ bool get isFactory => baseElement.isFactory;
@override
- bool callsGetter() => true;
+ String toString() {
+ ConstructorElement baseElement = this.baseElement;
+ List<ParameterElement> parameters = this.parameters;
+ FunctionType type = this.type;
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append(baseElement.enclosingElement.displayName);
+ String name = displayName;
+ if (name != null && !name.isEmpty) {
+ builder.append(".");
+ builder.append(name);
+ }
+ builder.append("(");
+ int parameterCount = parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(parameters[i]).toString();
+ }
+ builder.append(")");
+ if (type != null) {
+ builder.append(Element.RIGHT_ARROW);
+ builder.append(type.returnType);
+ }
+ return builder.toString();
+ }
+
+ @override
+ InterfaceType get definingType => super.definingType as InterfaceType;
}
/**
- * The interface `AngularScopeVariableElement` defines the Angular <code>Scope</code>
- * property. They are created for every <code>scope['property'] = value;</code> code snippet.
+ * The interface `Type` defines the behavior of objects representing the declared type of
+ * elements in the element model.
*/
-abstract class AngularScopePropertyElement implements AngularElement {
+abstract class DartType {
/**
- * An empty array of scope property elements.
+ * Return the name of this type as it should appear when presented to users in contexts such as
+ * error messages.
+ *
+ * @return the name of this type
*/
- static final List<AngularScopePropertyElement> EMPTY_ARRAY = [];
+ String get displayName;
/**
- * Returns the type of this property, not `null`, maybe <code>dynamic</code>.
+ * Return the element representing the declaration of this type, or `null` if the type has
+ * not, or cannot, be associated with an element. The former case will occur if the element model
+ * is not yet complete; the latter case will occur if this object represents an undefined type.
*
- * @return the type of this property.
+ * @return the element representing the declaration of this type
*/
- DartType get type;
-}
+ Element get element;
-/**
- * [AngularSelectorElement] is used to decide when Angular object should be applied.
- *
- * This class is an [Element] to support renaming component tag names, which are identifiers
- * in selectors.
- */
-abstract class AngularSelectorElement implements AngularElement {
/**
- * Checks if the given [XmlTagNode] matches this selector.
+ * Return the least upper bound of this type and the given type, or `null` if there is no
+ * least upper bound.
*
- * @param node the [XmlTagNode] to check
- * @return `true` if the given [XmlTagNode] matches, or `false` otherwise
+ * @param type the other type used to compute the least upper bound
+ * @return the least upper bound of this type and the given type
*/
- bool apply(XmlTagNode node);
-}
+ DartType getLeastUpperBound(DartType type);
-/**
- * [AngularSelectorElement] based on tag name.
- */
-abstract class AngularTagSelectorElement implements AngularSelectorElement {
-}
+ /**
+ * Return the name of this type, or `null` if the type does not have a name, such as when
+ * the type represents the type of an unnamed function.
+ *
+ * @return the name of this type
+ */
+ String get name;
-/**
- * The interface `AngularViewElement` defines the Angular view defined using invocation like
- * <code>view('views/create.html')</code>.
- */
-abstract class AngularViewElement implements AngularHasTemplateElement {
/**
- * An empty array of view elements.
+ * Return `true` if this type is assignable to the given type. A type <i>T</i> may be
+ * assigned to a type <i>S</i>, written <i>T</i> &hArr; <i>S</i>, iff either <i>T</i> <: <i>S</i>
+ * or <i>S</i> <: <i>T</i>.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is assignable to the given type
*/
- static final List<AngularViewElement> EMPTY_ARRAY = new List<AngularViewElement>(0);
-}
+ bool isAssignableTo(DartType type);
-/**
- * The interface `PolymerAttributeElement` defines an attribute in
- * [PolymerTagHtmlElement].
- *
- * <pre>
- * <polymer-element name="my-example" attributes='attrA attrB'>
- * </polymer-element>
- * </pre>
- */
-abstract class PolymerAttributeElement implements PolymerElement {
/**
- * An empty array of Polymer custom tag attributes.
+ * Return `true` if this type represents the bottom type.
+ *
+ * @return `true` if this type represents the bottom type
*/
- static final List<PolymerAttributeElement> EMPTY_ARRAY = new List<PolymerAttributeElement>(0);
+ bool get isBottom;
/**
- * Return the [FieldElement] associated with this attribute. Maybe `null` if
- * [PolymerTagDartElement] does not have a field associated with it.
+ * Return `true` if this type represents the type 'Function' defined in the dart:core
+ * library.
+ *
+ * @return `true` if this type represents the type 'Function' defined in the dart:core
+ * library
*/
- FieldElement get field;
-}
+ bool get isDartCoreFunction;
-/**
- * The interface `PolymerElement` defines the behavior of objects representing information
- * about a Polymer specific element.
- */
-abstract class PolymerElement implements ToolkitObjectElement {
/**
- * An empty array of Polymer elements.
+ * Return `true` if this type represents the type 'dynamic'.
+ *
+ * @return `true` if this type represents the type 'dynamic'
*/
- static final List<PolymerElement> EMPTY_ARRAY = new List<PolymerElement>(0);
-}
+ bool get isDynamic;
-/**
- * The interface `PolymerTagDartElement` defines a Polymer custom tag in Dart.
- *
- * <pre>
- * @CustomTag('my-example')
- * </pre>
- */
-abstract class PolymerTagDartElement implements PolymerElement {
/**
- * Return the [ClassElement] that is associated with this Polymer custom tag. Not
- * `null`, because [PolymerTagDartElement]s are created for [ClassElement]s
- * marked with the `@CustomTag` annotation.
+ * Return `true` if this type is more specific than the given type.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is more specific than the given type
*/
- ClassElement get classElement;
+ bool isMoreSpecificThan(DartType type);
/**
- * Return the [PolymerTagHtmlElement] part of this Polymer custom tag. Maybe `null` if
- * it has not been resolved yet or there are no corresponding Dart part defined.
+ * Return `true` if this type represents the type 'Object'.
+ *
+ * @return `true` if this type represents the type 'Object'
*/
- PolymerTagHtmlElement get htmlElement;
-}
+ bool get isObject;
-/**
- * The interface `PolymerTagHtmlElement` defines a Polymer custom tag in HTML.
- *
- * <pre>
- * <polymer-element name="my-example" attributes='attrA attrB'>
- * </polymer-element>
- * </pre>
- */
-abstract class PolymerTagHtmlElement implements PolymerElement {
/**
- * An empty array of [PolymerTagHtmlElement]s.
+ * Return `true` if this type is a subtype of the given type.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is a subtype of the given type
*/
- static final List<PolymerTagHtmlElement> EMPTY_ARRAY = new List<PolymerTagHtmlElement>(0);
+ bool isSubtypeOf(DartType type);
/**
- * Return an array containing all of the attributes declared by this tag.
+ * Return `true` if this type is a supertype of the given type. A type <i>S</i> is a
+ * supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff <i>T</i> is a subtype of <i>S</i>.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is a supertype of the given type
*/
- List<PolymerAttributeElement> get attributes;
+ bool isSupertypeOf(DartType type);
/**
- * Return the [PolymerTagDartElement] part on this Polymer custom tag. Maybe `null` if
- * it has not been resolved yet or there are no corresponding Dart part defined.
+ * Return `true` if this type represents the type 'void'.
+ *
+ * @return `true` if this type represents the type 'void'
*/
- PolymerTagDartElement get dartElement;
+ bool get isVoid;
+
+ /**
+ * Return the type resulting from substituting the given arguments for the given parameters in
+ * this type. The specification defines this operation in section 2: <blockquote> The notation
+ * <i>[x<sub>1</sub>, ..., x<sub>n</sub>/y<sub>1</sub>, ..., y<sub>n</sub>]E</i> denotes a copy of
+ * <i>E</i> in which all occurrences of <i>y<sub>i</sub>, 1 <= i <= n</i> have been replaced with
+ * <i>x<sub>i</sub></i>.</blockquote> Note that, contrary to the specification, this method will
+ * not create a copy of this type if no substitutions were required, but will return this type
+ * directly.
+ *
+ * @param argumentTypes the actual type arguments being substituted for the parameters
+ * @param parameterTypes the parameters to be replaced
+ * @return the result of performing the substitution
+ */
+ DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
}
/**
- * Instances of the class `GeneralizingElementVisitor` implement an element visitor that will
- * recursively visit all of the elements in an element model (like instances of the class
- * [RecursiveElementVisitor]). In addition, when an element of a specific type is visited not
- * only will the visit method for that specific type of element be invoked, but additional methods
- * for the supertypes of that element will also be invoked. For example, using an instance of this
- * class to visit a [MethodElement] will cause the method
- * [visitMethodElement] to be invoked but will also cause the methods
- * [visitExecutableElement] and [visitElement] to be
- * subsequently invoked. This allows visitors to be written that visit all executable elements
- * without needing to override the visit method for each of the specific subclasses of
- * [ExecutableElement].
- *
- * Note, however, that unlike many visitors, element visitors visit objects based on the interfaces
- * implemented by those elements. Because interfaces form a graph structure rather than a tree
- * structure the way classes do, and because it is generally undesirable for an object to be visited
- * more than once, this class flattens the interface graph into a pseudo-tree. In particular, this
- * class treats elements as if the element types were structured in the following way:
- *
- *
- * <pre>
- * Element
- * ClassElement
- * CompilationUnitElement
- * ExecutableElement
- * ConstructorElement
- * LocalElement
- * FunctionElement
- * MethodElement
- * PropertyAccessorElement
- * ExportElement
- * HtmlElement
- * ImportElement
- * LabelElement
- * LibraryElement
- * MultiplyDefinedElement
- * PrefixElement
- * TypeAliasElement
- * TypeParameterElement
- * UndefinedElement
- * VariableElement
- * PropertyInducingElement
- * FieldElement
- * TopLevelVariableElement
- * LocalElement
- * LocalVariableElement
- * ParameterElement
- * FieldFormalParameterElement
- * </pre>
- *
- * Subclasses that override a visit method must either invoke the overridden visit method or
- * explicitly invoke the more general visit method. Failure to do so will cause the visit methods
- * for superclasses of the element to not be invoked and will cause the children of the visited node
- * to not be visited.
+ * Instances of the class `DefaultFieldFormalParameterElementImpl` implement a
+ * `FieldFormalParameterElementImpl` for parameters that have an initializer.
*/
-class GeneralizingElementVisitor<R> implements ElementVisitor<R> {
- @override
- R visitAngularComponentElement(AngularComponentElement element) => visitAngularHasSelectorElement(element);
-
- @override
- R visitAngularControllerElement(AngularControllerElement element) => visitAngularHasSelectorElement(element);
-
- @override
- R visitAngularDirectiveElement(AngularDecoratorElement element) => visitAngularHasSelectorElement(element);
+class DefaultFieldFormalParameterElementImpl extends FieldFormalParameterElementImpl {
+ /**
+ * The result of evaluating this variable's initializer.
+ */
+ EvaluationResultImpl _result;
- R visitAngularElement(AngularElement element) => visitToolkitObjectElement(element);
+ /**
+ * Initialize a newly created parameter element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ DefaultFieldFormalParameterElementImpl(Identifier name) : super(name);
@override
- R visitAngularFormatterElement(AngularFormatterElement element) => visitAngularElement(element);
-
- R visitAngularHasSelectorElement(AngularHasSelectorElement element) => visitAngularElement(element);
+ EvaluationResultImpl get evaluationResult => _result;
@override
- R visitAngularPropertyElement(AngularPropertyElement element) => visitAngularElement(element);
+ void set evaluationResult(EvaluationResultImpl result) {
+ this._result = result;
+ }
+}
- @override
- R visitAngularScopePropertyElement(AngularScopePropertyElement element) => visitAngularElement(element);
+/**
+ * Instances of the class `DefaultParameterElementImpl` implement a `ParameterElement`
+ * for parameters that have an initializer.
+ */
+class DefaultParameterElementImpl extends ParameterElementImpl {
+ /**
+ * The result of evaluating this variable's initializer.
+ */
+ EvaluationResultImpl _result;
- @override
- R visitAngularSelectorElement(AngularSelectorElement element) => visitAngularElement(element);
+ /**
+ * Initialize a newly created parameter element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ DefaultParameterElementImpl(Identifier name) : super.con1(name);
@override
- R visitAngularViewElement(AngularViewElement element) => visitAngularElement(element);
+ EvaluationResultImpl get evaluationResult => _result;
@override
- R visitClassElement(ClassElement element) => visitElement(element);
+ void set evaluationResult(EvaluationResultImpl result) {
+ this._result = result;
+ }
+}
- @override
- R visitCompilationUnitElement(CompilationUnitElement element) => visitElement(element);
+/**
+ * Instances of the class `DynamicElementImpl` represent the synthetic element representing
+ * the declaration of the type `dynamic`.
+ */
+class DynamicElementImpl extends ElementImpl {
+ /**
+ * Return the unique instance of this class.
+ *
+ * @return the unique instance of this class
+ */
+ static DynamicElementImpl get instance => DynamicTypeImpl.instance.element as DynamicElementImpl;
- @override
- R visitConstructorElement(ConstructorElement element) => visitExecutableElement(element);
+ /**
+ * The type defined by this element.
+ */
+ DynamicTypeImpl type;
- R visitElement(Element element) {
- element.visitChildren(this);
- return null;
+ /**
+ * 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 [getInstance].
+ */
+ DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) {
+ setModifier(Modifier.SYNTHETIC, true);
}
@override
- R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => visitHtmlScriptElement(element);
-
- R visitExecutableElement(ExecutableElement element) => visitElement(element);
-
- @override
- R visitExportElement(ExportElement element) => visitElement(element);
+ accept(ElementVisitor visitor) => null;
@override
- R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => visitHtmlScriptElement(element);
+ ElementKind get kind => ElementKind.DYNAMIC;
+}
- @override
- R visitFieldElement(FieldElement element) => visitPropertyInducingElement(element);
+/**
+ * The unique instance of the class `DynamicTypeImpl` implements the type `dynamic`.
+ */
+class DynamicTypeImpl extends TypeImpl {
+ /**
+ * The unique instance of this class.
+ */
+ static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl();
- @override
- R visitFieldFormalParameterElement(FieldFormalParameterElement element) => visitParameterElement(element);
+ /**
+ * Return the unique instance of this class.
+ *
+ * @return the unique instance of this class
+ */
+ static DynamicTypeImpl get instance => _INSTANCE;
- @override
- R visitFunctionElement(FunctionElement element) => visitLocalElement(element);
+ /**
+ * Prevent the creation of instances of this class.
+ */
+ DynamicTypeImpl() : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) {
+ (element as DynamicElementImpl).type = this;
+ }
@override
- R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => visitElement(element);
+ bool operator ==(Object object) => identical(object, this);
@override
- R visitHtmlElement(HtmlElement element) => visitElement(element);
-
- R visitHtmlScriptElement(HtmlScriptElement element) => visitElement(element);
+ int get hashCode => 1;
@override
- R visitImportElement(ImportElement element) => visitElement(element);
+ bool get isDynamic => true;
@override
- R visitLabelElement(LabelElement element) => visitElement(element);
+ bool isSupertypeOf(DartType type) => true;
@override
- R visitLibraryElement(LibraryElement element) => visitElement(element);
-
- R visitLocalElement(LocalElement element) {
- if (element is LocalVariableElement) {
- return visitVariableElement(element);
- } else if (element is ParameterElement) {
- return visitVariableElement(element);
- } else if (element is FunctionElement) {
- return visitExecutableElement(element);
+ DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
+ int length = parameterTypes.length;
+ for (int i = 0; i < length; i++) {
+ if (parameterTypes[i] == this) {
+ return argumentTypes[i];
+ }
}
- return null;
+ return this;
}
@override
- R visitLocalVariableElement(LocalVariableElement element) => visitLocalElement(element);
-
- @override
- R visitMethodElement(MethodElement element) => visitExecutableElement(element);
-
- @override
- R visitMultiplyDefinedElement(MultiplyDefinedElement element) => visitElement(element);
-
- @override
- R visitParameterElement(ParameterElement element) => visitLocalElement(element);
-
- @override
- R visitPolymerAttributeElement(PolymerAttributeElement element) => visitPolymerElement(element);
-
- R visitPolymerElement(PolymerElement element) => visitToolkitObjectElement(element);
-
- @override
- R visitPolymerTagDartElement(PolymerTagDartElement element) => visitPolymerElement(element);
-
- @override
- R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) => visitPolymerElement(element);
-
- @override
- R visitPrefixElement(PrefixElement element) => visitElement(element);
-
- @override
- R visitPropertyAccessorElement(PropertyAccessorElement element) => visitExecutableElement(element);
-
- R visitPropertyInducingElement(PropertyInducingElement element) => visitVariableElement(element);
-
- R visitToolkitObjectElement(ToolkitObjectElement element) => visitElement(element);
+ bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
@override
- R visitTopLevelVariableElement(TopLevelVariableElement element) => visitPropertyInducingElement(element);
+ bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // T is S
+ if (identical(this, type)) {
+ return true;
+ }
+ // else
+ return withDynamic;
+ }
@override
- R visitTypeParameterElement(TypeParameterElement element) => visitElement(element);
-
- R visitVariableElement(VariableElement element) => visitElement(element);
+ bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
}
/**
- * Instances of the class `RecursiveElementVisitor` implement an element visitor that will
- * recursively visit all of the element in an element model. For example, using an instance of this
- * class to visit a [CompilationUnitElement] will also cause all of the types in the
- * compilation unit to be visited.
+ * The interface `Element` defines the behavior common to all of the elements in the element
+ * model. Generally speaking, the element model is a semantic model of the program that represents
+ * things that are declared with a name and hence can be referenced elsewhere in the code.
*
- * Subclasses that override a visit method must either invoke the overridden visit method or must
- * explicitly ask the visited element to visit its children. Failure to do so will cause the
- * children of the visited element to not be visited.
+ * There are two exceptions to the general case. First, there are elements in the element model that
+ * are created for the convenience of various kinds of analysis but that do not have any
+ * corresponding declaration within the source code. Such elements are marked as being
+ * <i>synthetic</i>. Examples of synthetic elements include
+ * * default constructors in classes that do not define any explicit constructors,
+ * * getters and setters that are induced by explicit field declarations,
+ * * fields that are induced by explicit declarations of getters and setters, and
+ * * functions representing the initialization expression for a variable.
+ *
+ * Second, there are elements in the element model that do not have a name. These correspond to
+ * unnamed functions and exist in order to more accurately represent the semantic structure of the
+ * program.
*/
-class RecursiveElementVisitor<R> implements ElementVisitor<R> {
- @override
- R visitAngularComponentElement(AngularComponentElement element) {
- element.visitChildren(this);
- return null;
- }
+abstract class Element {
+ /**
+ * An Unicode right arrow.
+ */
+ static final String RIGHT_ARROW = " \u2192 ";
- @override
- R visitAngularControllerElement(AngularControllerElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * A comparator that can be used to sort elements by their name offset. Elements with a smaller
+ * offset will be sorted to be before elements with a larger name offset.
+ */
+ static final Comparator<Element> SORT_BY_OFFSET = (Element firstElement, Element secondElement) => firstElement.nameOffset - secondElement.nameOffset;
- @override
- R visitAngularDirectiveElement(AngularDecoratorElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Use the given visitor to visit this element.
+ *
+ * @param visitor the visitor that will visit this element
+ * @return the value returned by the visitor as a result of visiting this element
+ */
+ accept(ElementVisitor visitor);
- @override
- R visitAngularFormatterElement(AngularFormatterElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the documentation comment for this element as it appears in the original source
+ * (complete with the beginning and ending delimiters), or `null` if this element does not
+ * have a documentation comment associated with it. This can be a long-running operation if the
+ * information needed to access the comment is not cached.
+ *
+ * @return this element's documentation comment
+ * @throws AnalysisException if the documentation comment could not be determined because the
+ * analysis could not be performed
+ */
+ String computeDocumentationComment();
- @override
- R visitAngularPropertyElement(AngularPropertyElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the element of the given class that most immediately encloses this element, or
+ * `null` if there is no enclosing element of the given class.
+ *
+ * @param elementClass the class of the element to be returned
+ * @return the element that encloses this element
+ */
+ Element getAncestor(Predicate<Element> predicate);
- @override
- R visitAngularScopePropertyElement(AngularScopePropertyElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the analysis context in which this element is defined.
+ *
+ * @return the analysis context in which this element is defined
+ */
+ AnalysisContext get context;
- @override
- R visitAngularSelectorElement(AngularSelectorElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the display name of this element, or `null` if this element does not have a name.
+ *
+ * In most cases the name and the display name are the same. Differences though are cases such as
+ * setters where the name of some setter `set f(x)` is `f=`, instead of `f`.
+ *
+ * @return the display name of this element
+ */
+ String get displayName;
- @override
- R visitAngularViewElement(AngularViewElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the element that either physically or logically encloses this element. This will be
+ * `null` if this element is a library because libraries are the top-level elements in the
+ * model.
+ *
+ * @return the element that encloses this element
+ */
+ Element get enclosingElement;
- @override
- R visitClassElement(ClassElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the kind of element that this is.
+ *
+ * @return the kind of this element
+ */
+ ElementKind get kind;
- @override
- R visitCompilationUnitElement(CompilationUnitElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the library that contains this element. This will be the element itself if it is a
+ * library element. This will be `null` if this element is an HTML file because HTML files
+ * are not contained in libraries.
+ *
+ * @return the library that contains this element
+ */
+ LibraryElement get library;
- @override
- R visitConstructorElement(ConstructorElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return an object representing the location of this element in the element model. The object can
+ * be used to locate this element at a later time.
+ *
+ * @return the location of this element in the element model
+ */
+ ElementLocation get location;
- @override
- R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return an array containing all of the metadata associated with this element. The array will be
+ * empty if the element does not have any metadata or if the library containing this element has
+ * not yet been resolved.
+ *
+ * @return the metadata associated with this element
+ */
+ List<ElementAnnotation> get metadata;
- @override
- R visitExportElement(ExportElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the name of this element, or `null` if this element does not have a name.
+ *
+ * @return the name of this element
+ */
+ String get name;
- @override
- R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the offset of the name of this element in the file that contains the declaration of this
+ * element, or `-1` if this element is synthetic, does not have a name, or otherwise does
+ * not have an offset.
+ *
+ * @return the offset of the name of this element
+ */
+ int get nameOffset;
- @override
- R visitFieldElement(FieldElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the resolved [AstNode] node that declares this [Element].
+ *
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
+ *
+ * <b>Note:</b> This method cannot be used in an async environment.
+ *
+ * @return the resolved [AstNode], maybe `null` if [Element] is synthetic or
+ * isn't contained in a compilation unit, such as a [LibraryElement].
+ */
+ AstNode get node;
- @override
- R visitFieldFormalParameterElement(FieldFormalParameterElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the source that contains this element, or `null` if this element is not contained
+ * in a source.
+ *
+ * @return the source that contains this element
+ */
+ Source get source;
- @override
- R visitFunctionElement(FunctionElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return the resolved [CompilationUnit] that declares this [Element].
+ *
+ * This method is expensive, because resolved AST might have been already evicted from cache, so
+ * parsing and resolving will be performed.
+ *
+ * @return the resolved [CompilationUnit], maybe `null` if synthetic [Element].
+ */
+ CompilationUnit get unit;
- @override
- R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this element, assuming that it is within scope, is accessible to code in
+ * the given library. This is defined by the Dart Language Specification in section 3.2:
+ * <blockquote> A declaration <i>m</i> is accessible to library <i>L</i> if <i>m</i> is declared
+ * in <i>L</i> or if <i>m</i> is public. </blockquote>
+ *
+ * @param library the library in which a possible reference to this element would occur
+ * @return `true` if this element is accessible to code in the given library
+ */
+ bool isAccessibleIn(LibraryElement library);
- @override
- R visitHtmlElement(HtmlElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this element has an annotation of the form '@deprecated' or
+ * '@Deprecated('..')'.
+ *
+ * @return `true` if this element is deprecated
+ */
+ bool get isDeprecated;
- @override
- R visitImportElement(ImportElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this element has an annotation of the form '@override'.
+ *
+ * @return `true` if this element is overridden
+ */
+ bool get isOverride;
- @override
- R visitLabelElement(LabelElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this element is private. Private elements are visible only within the
+ * library in which they are declared.
+ *
+ * @return `true` if this element is private
+ */
+ bool get isPrivate;
- @override
- R visitLibraryElement(LibraryElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this element is public. Public elements are visible within any library
+ * that imports the library in which they are declared.
+ *
+ * @return `true` if this element is public
+ */
+ bool get isPublic;
- @override
- R visitLocalVariableElement(LocalVariableElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this element is synthetic. A synthetic element is an element that is not
+ * represented in the source code explicitly, but is implied by the source code, such as the
+ * default constructor for a class that does not explicitly define any constructors.
+ *
+ * @return `true` if this element is synthetic
+ */
+ bool get isSynthetic;
- @override
- R visitMethodElement(MethodElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Use the given visitor to visit all of the children of this element. There is no guarantee of
+ * the order in which the children will be visited.
+ *
+ * @param visitor the visitor that will be used to visit the children of this element
+ */
+ void visitChildren(ElementVisitor visitor);
+}
- @override
- R visitMultiplyDefinedElement(MultiplyDefinedElement element) {
- element.visitChildren(this);
- return null;
- }
+/**
+ * The interface `ElementAnnotation` defines the behavior of objects representing a single
+ * annotation associated with an element.
+ */
+abstract class ElementAnnotation {
+ /**
+ * Return the element representing the field, variable, or const constructor being used as an
+ * annotation.
+ *
+ * @return the field, variable, or constructor being used as an annotation
+ */
+ Element get element;
- @override
- R visitParameterElement(ParameterElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this annotation marks the associated element as being deprecated.
+ *
+ * @return `true` if this annotation marks the associated element as being deprecated
+ */
+ bool get isDeprecated;
- @override
- R visitPolymerAttributeElement(PolymerAttributeElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this annotation marks the associated method as being expected to
+ * override an inherited method.
+ *
+ * @return `true` if this annotation marks the associated method as overriding another
+ * method
+ */
+ bool get isOverride;
- @override
- R visitPolymerTagDartElement(PolymerTagDartElement element) {
- element.visitChildren(this);
- return null;
- }
+ /**
+ * Return `true` if this annotation marks the associated class as implementing a proxy
+ * object.
+ *
+ * @return `true` if this annotation marks the associated class as implementing a proxy
+ * object
+ */
+ bool get isProxy;
+}
- @override
- R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) {
- element.visitChildren(this);
- return null;
- }
+/**
+ * Instances of the class `ElementAnnotationImpl` implement an [ElementAnnotation].
+ */
+class ElementAnnotationImpl implements ElementAnnotation {
+ /**
+ * The element representing the field, variable, or constructor being used as an annotation.
+ */
+ final Element element;
+
+ /**
+ * An empty array of annotations.
+ */
+ static List<ElementAnnotationImpl> EMPTY_ARRAY = new List<ElementAnnotationImpl>(0);
+
+ /**
+ * 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 expected to override an
+ * inherited method.
+ */
+ static String _OVERRIDE_VARIABLE_NAME = "override";
+
+ /**
+ * The name of the top-level variable used to mark a class as implementing a proxy object.
+ */
+ static String PROXY_VARIABLE_NAME = "proxy";
+
+ /**
+ * Initialize a newly created annotation.
+ *
+ * @param element the element representing the field, variable, or constructor being used as an
+ * annotation
+ */
+ ElementAnnotationImpl(this.element);
@override
- R visitPrefixElement(PrefixElement element) {
- element.visitChildren(this);
- return null;
+ bool get isDeprecated {
+ if (element != null) {
+ LibraryElement library = element.library;
+ if (library != null && library.isDartCore) {
+ if (element is ConstructorElement) {
+ ConstructorElement constructorElement = element as ConstructorElement;
+ if (constructorElement.enclosingElement.name == _DEPRECATED_CLASS_NAME) {
+ return true;
+ }
+ } else if (element is PropertyAccessorElement && element.name == _DEPRECATED_VARIABLE_NAME) {
+ return true;
+ }
+ }
+ }
+ return false;
}
@override
- R visitPropertyAccessorElement(PropertyAccessorElement element) {
- element.visitChildren(this);
- return null;
+ bool get isOverride {
+ if (element != null) {
+ LibraryElement library = element.library;
+ if (library != null && library.isDartCore) {
+ if (element is PropertyAccessorElement && element.name == _OVERRIDE_VARIABLE_NAME) {
+ return true;
+ }
+ }
+ }
+ return false;
}
@override
- R visitTopLevelVariableElement(TopLevelVariableElement element) {
- element.visitChildren(this);
- return null;
+ bool get isProxy {
+ if (element != null) {
+ LibraryElement library = element.library;
+ if (library != null && library.isDartCore) {
+ if (element is PropertyAccessorElement && element.name == PROXY_VARIABLE_NAME) {
+ return true;
+ }
+ }
+ }
+ return false;
}
@override
- R visitTypeParameterElement(TypeParameterElement element) {
- element.visitChildren(this);
- return null;
- }
+ String toString() => "@${element.toString()}";
}
/**
- * Instances of the class `SimpleElementVisitor` implement an element visitor that will do
- * nothing when visiting an element. It is intended to be a superclass for classes that use the
- * visitor pattern primarily as a dispatch mechanism (and hence don't need to recursively visit a
- * whole structure) and that only need to visit a small number of element types.
+ * The abstract class `ElementImpl` implements the behavior common to objects that implement
+ * an [Element].
*/
-class SimpleElementVisitor<R> implements ElementVisitor<R> {
- @override
- R visitAngularComponentElement(AngularComponentElement element) => null;
-
- @override
- R visitAngularControllerElement(AngularControllerElement element) => null;
+abstract class ElementImpl implements Element {
+ /**
+ * The enclosing element of this element, or `null` if this element is at the root of the
+ * element structure.
+ */
+ ElementImpl _enclosingElement;
- @override
- R visitAngularDirectiveElement(AngularDecoratorElement element) => null;
+ /**
+ * The name of this element.
+ */
+ String _name;
- @override
- R visitAngularFormatterElement(AngularFormatterElement element) => null;
+ /**
+ * The offset of the name of this element in the file that contains the declaration of this
+ * element.
+ */
+ int nameOffset = 0;
- @override
- R visitAngularPropertyElement(AngularPropertyElement element) => null;
+ /**
+ * A bit-encoded form of the modifiers associated with this element.
+ */
+ int _modifiers = 0;
- @override
- R visitAngularScopePropertyElement(AngularScopePropertyElement element) => null;
+ /**
+ * An array containing all of the metadata associated with this element.
+ */
+ List<ElementAnnotation> metadata = ElementAnnotationImpl.EMPTY_ARRAY;
- @override
- R visitAngularSelectorElement(AngularSelectorElement element) => null;
+ /**
+ * A cached copy of the calculated hashCode for this element.
+ */
+ int _cachedHashCode = 0;
- @override
- R visitAngularViewElement(AngularViewElement element) => null;
+ /**
+ * Initialize a newly created element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ ElementImpl.forNode(Identifier name) : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
- @override
- R visitClassElement(ClassElement element) => null;
-
- @override
- R visitCompilationUnitElement(CompilationUnitElement element) => null;
+ /**
+ * Initialize a newly created element to have the given name.
+ *
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
+ */
+ ElementImpl(String name, this.nameOffset) {
+ this._name = StringUtilities.intern(name);
+ }
@override
- R visitConstructorElement(ConstructorElement element) => null;
+ String computeDocumentationComment() {
+ AnalysisContext context = this.context;
+ if (context == null) {
+ return null;
+ }
+ return context.computeDocumentationComment(this);
+ }
@override
- R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => null;
+ bool operator ==(Object object) {
+ if (identical(this, object)) {
+ return true;
+ }
+ if (object == null || hashCode != object.hashCode) {
+ return false;
+ }
+ return object.runtimeType == runtimeType && (object as Element).location == location;
+ }
@override
- R visitExportElement(ExportElement element) => null;
+ Element getAncestor(Predicate<Element> predicate) {
+ Element ancestor = _enclosingElement;
+ while (ancestor != null && !predicate(ancestor)) {
+ ancestor = ancestor.enclosingElement;
+ }
+ return ancestor;
+ }
- @override
- R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => null;
+ /**
+ * Return the child of this element that is uniquely identified by the given identifier, or
+ * `null` if there is no such child.
+ *
+ * @param identifier the identifier used to select a child
+ * @return the child of this element with the given identifier
+ */
+ ElementImpl getChild(String identifier) => null;
@override
- R visitFieldElement(FieldElement element) => null;
+ AnalysisContext get context {
+ if (_enclosingElement == null) {
+ return null;
+ }
+ return _enclosingElement.context;
+ }
@override
- R visitFieldFormalParameterElement(FieldFormalParameterElement element) => null;
+ String get displayName => _name;
@override
- R visitFunctionElement(FunctionElement element) => null;
+ Element get enclosingElement => _enclosingElement;
@override
- R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null;
+ LibraryElement get library => getAncestor((element) => element is LibraryElement);
@override
- R visitHtmlElement(HtmlElement element) => null;
+ ElementLocation get location => new ElementLocationImpl.con1(this);
@override
- R visitImportElement(ImportElement element) => null;
+ String get name => _name;
@override
- R visitLabelElement(LabelElement element) => null;
+ AstNode get node => getNodeMatching((node) => node is AstNode);
@override
- R visitLibraryElement(LibraryElement element) => null;
+ Source get source {
+ if (_enclosingElement == null) {
+ return null;
+ }
+ return _enclosingElement.source;
+ }
@override
- R visitLocalVariableElement(LocalVariableElement element) => null;
+ CompilationUnit get unit => context.resolveCompilationUnit(source, library);
@override
- R visitMethodElement(MethodElement element) => null;
+ 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 == 0) {
+ int hashIdentifier = identifier.hashCode;
+ Element enclosing = enclosingElement;
+ if (enclosing != null) {
+ _cachedHashCode = hashIdentifier + enclosing.hashCode;
+ } else {
+ _cachedHashCode = hashIdentifier;
+ }
+ }
+ return _cachedHashCode;
+ }
@override
- R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null;
+ bool isAccessibleIn(LibraryElement library) {
+ if (Identifier.isPrivateName(_name)) {
+ return library == this.library;
+ }
+ return true;
+ }
@override
- R visitParameterElement(ParameterElement element) => null;
+ bool get isDeprecated {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isDeprecated) {
+ return true;
+ }
+ }
+ return false;
+ }
@override
- R visitPolymerAttributeElement(PolymerAttributeElement element) => null;
+ bool get isOverride {
+ for (ElementAnnotation annotation in metadata) {
+ if (annotation.isOverride) {
+ return true;
+ }
+ }
+ return false;
+ }
@override
- R visitPolymerTagDartElement(PolymerTagDartElement element) => null;
+ bool get isPrivate {
+ String name = displayName;
+ if (name == null) {
+ return true;
+ }
+ return Identifier.isPrivateName(name);
+ }
@override
- R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) => null;
+ bool get isPublic => !isPrivate;
@override
- R visitPrefixElement(PrefixElement element) => null;
+ bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
- @override
- R visitPropertyAccessorElement(PropertyAccessorElement element) => null;
+ /**
+ * Set whether this element is synthetic to correspond to the given value.
+ *
+ * @param isSynthetic `true` if the element is synthetic
+ */
+ void set synthetic(bool isSynthetic) {
+ setModifier(Modifier.SYNTHETIC, isSynthetic);
+ }
@override
- R visitTopLevelVariableElement(TopLevelVariableElement element) => null;
+ String toString() {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ appendTo(builder);
+ return builder.toString();
+ }
@override
- R visitTypeParameterElement(TypeParameterElement element) => null;
-}
+ void visitChildren(ElementVisitor visitor) {
+ }
-/**
- * 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]. Since 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 this identifier could not be resolved.
+ * Append a textual representation of this type to the given builder.
+ *
+ * @param builder the builder to which the text is to be appended
*/
- final ExecutableElement propagatedElement;
+ void appendTo(JavaStringBuilder builder) {
+ if (_name == null) {
+ builder.append("<unnamed ");
+ builder.append(runtimeType.toString());
+ builder.append(">");
+ } else {
+ builder.append(_name);
+ }
+ }
/**
- * The element associated with this identifier based on static type information, or `null`
- * if the AST structure has not been resolved or if this identifier could not be resolved.
+ * Set this [Element] as an enclosing for given.
+ *
+ * @param element the element to enclose, must be [ElementImpl]
*/
- final ExecutableElement staticElement;
+ void encloseElement(ElementImpl element) {
+ element.enclosingElement = this;
+ }
/**
- * Create the [AuxiliaryElements] with a static and propagated [ExecutableElement].
+ * Return an identifier that uniquely identifies this element among the children of this element's
+ * parent.
*
- * @param staticElement the static element
- * @param propagatedElement the propagated element
+ * @return an identifier that uniquely identifies this element relative to its parent
*/
- AuxiliaryElements(this.staticElement, this.propagatedElement);
-}
+ String get identifier => name;
-/**
- * Instances of the class `ClassElementImpl` implement a `ClassElement`.
- */
-class ClassElementImpl extends ElementImpl implements ClassElement {
/**
- * An array containing all of the accessors (getters and setters) contained in this class.
+ * Return the resolved [AstNode] of the given type enclosing [getNameOffset].
*/
- List<PropertyAccessorElement> _accessors = PropertyAccessorElementImpl.EMPTY_ARRAY;
+ AstNode getNodeMatching(Predicate<AstNode> predicate) {
+ CompilationUnit unit = this.unit;
+ if (unit == null) {
+ return null;
+ }
+ int offset = nameOffset;
+ AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
+ if (node == null) {
+ return null;
+ }
+ return node.getAncestor(predicate);
+ }
/**
- * An array containing all of the constructors contained in this class.
+ * Return `true` if this element has the given modifier associated with it.
+ *
+ * @param modifier the modifier being tested for
+ * @return `true` if this element has the given modifier associated with it
*/
- List<ConstructorElement> _constructors = ConstructorElementImpl.EMPTY_ARRAY;
+ bool hasModifier(Modifier modifier) => BooleanArray.getEnum(_modifiers, modifier);
/**
- * An array containing all of the fields contained in this class.
+ * If the given child is not `null`, use the given visitor to visit it.
+ *
+ * @param child the child to be visited
+ * @param visitor the visitor to be used to visit the child
*/
- List<FieldElement> _fields = FieldElementImpl.EMPTY_ARRAY;
+ void safelyVisitChild(Element child, ElementVisitor visitor) {
+ if (child != null) {
+ child.accept(visitor);
+ }
+ }
/**
- * An array containing all of the mixins that are applied to the class being extended in order to
- * derive the superclass of this class.
+ * Use the given visitor to visit all of the children in the given array.
+ *
+ * @param children the children to be visited
+ * @param visitor the visitor being used to visit the children
*/
- List<InterfaceType> mixins = InterfaceTypeImpl.EMPTY_ARRAY;
+ void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
+ if (children != null) {
+ for (Element child in children) {
+ child.accept(visitor);
+ }
+ }
+ }
/**
- * An array containing all of the interfaces that are implemented by this class.
+ * Set the enclosing element of this element to the given element.
+ *
+ * @param element the enclosing element of this element
*/
- List<InterfaceType> interfaces = InterfaceTypeImpl.EMPTY_ARRAY;
+ void set enclosingElement(Element element) {
+ _enclosingElement = element as ElementImpl;
+ }
/**
- * An array containing all of the methods contained in this class.
+ * Set whether the given modifier is associated with this element to correspond to the given
+ * value.
+ *
+ * @param modifier the modifier to be set
+ * @param value `true` if the modifier is to be associated with this element
*/
- List<MethodElement> _methods = MethodElementImpl.EMPTY_ARRAY;
+ void setModifier(Modifier modifier, bool value) {
+ _modifiers = BooleanArray.setEnum(_modifiers, modifier, value);
+ }
+}
+
+/**
+ * The enumeration `ElementKind` defines the various kinds of elements in the element model.
+ */
+class ElementKind extends Enum<ElementKind> {
+ static const ElementKind ANGULAR_FORMATTER = const ElementKind('ANGULAR_FORMATTER', 0, "Angular formatter");
+
+ static const ElementKind ANGULAR_COMPONENT = const ElementKind('ANGULAR_COMPONENT', 1, "Angular component");
+
+ static const ElementKind ANGULAR_CONTROLLER = const ElementKind('ANGULAR_CONTROLLER', 2, "Angular controller");
+
+ static const ElementKind ANGULAR_DIRECTIVE = const ElementKind('ANGULAR_DIRECTIVE', 3, "Angular directive");
+
+ static const ElementKind ANGULAR_PROPERTY = const ElementKind('ANGULAR_PROPERTY', 4, "Angular property");
+
+ static const ElementKind ANGULAR_SCOPE_PROPERTY = const ElementKind('ANGULAR_SCOPE_PROPERTY', 5, "Angular scope property");
+
+ static const ElementKind ANGULAR_SELECTOR = const ElementKind('ANGULAR_SELECTOR', 6, "Angular selector");
+
+ static const ElementKind ANGULAR_VIEW = const ElementKind('ANGULAR_VIEW', 7, "Angular view");
+
+ static const ElementKind CLASS = const ElementKind('CLASS', 8, "class");
+
+ static const ElementKind COMPILATION_UNIT = const ElementKind('COMPILATION_UNIT', 9, "compilation unit");
+
+ static const ElementKind CONSTRUCTOR = const ElementKind('CONSTRUCTOR', 10, "constructor");
+
+ static const ElementKind DYNAMIC = const ElementKind('DYNAMIC', 11, "<dynamic>");
+
+ static const ElementKind EMBEDDED_HTML_SCRIPT = const ElementKind('EMBEDDED_HTML_SCRIPT', 12, "embedded html script");
+
+ static const ElementKind ERROR = const ElementKind('ERROR', 13, "<error>");
+
+ static const ElementKind EXPORT = const ElementKind('EXPORT', 14, "export directive");
+
+ static const ElementKind EXTERNAL_HTML_SCRIPT = const ElementKind('EXTERNAL_HTML_SCRIPT', 15, "external html script");
+
+ static const ElementKind FIELD = const ElementKind('FIELD', 16, "field");
+
+ static const ElementKind FUNCTION = const ElementKind('FUNCTION', 17, "function");
+
+ static const ElementKind GETTER = const ElementKind('GETTER', 18, "getter");
+
+ static const ElementKind HTML = const ElementKind('HTML', 19, "html");
+
+ static const ElementKind IMPORT = const ElementKind('IMPORT', 20, "import directive");
+
+ static const ElementKind LABEL = const ElementKind('LABEL', 21, "label");
+
+ static const ElementKind LIBRARY = const ElementKind('LIBRARY', 22, "library");
+
+ static const ElementKind LOCAL_VARIABLE = const ElementKind('LOCAL_VARIABLE', 23, "local variable");
+
+ static const ElementKind METHOD = const ElementKind('METHOD', 24, "method");
+
+ static const ElementKind NAME = const ElementKind('NAME', 25, "<name>");
+
+ static const ElementKind PARAMETER = const ElementKind('PARAMETER', 26, "parameter");
+
+ static const ElementKind POLYMER_ATTRIBUTE = const ElementKind('POLYMER_ATTRIBUTE', 27, "Polymer attribute");
+
+ static const ElementKind POLYMER_TAG_DART = const ElementKind('POLYMER_TAG_DART', 28, "Polymer Dart tag");
+
+ static const ElementKind POLYMER_TAG_HTML = const ElementKind('POLYMER_TAG_HTML', 29, "Polymer HTML tag");
+
+ static const ElementKind PREFIX = const ElementKind('PREFIX', 30, "import prefix");
+
+ static const ElementKind SETTER = const ElementKind('SETTER', 31, "setter");
+
+ static const ElementKind TOP_LEVEL_VARIABLE = const ElementKind('TOP_LEVEL_VARIABLE', 32, "top level variable");
+
+ static const ElementKind FUNCTION_TYPE_ALIAS = const ElementKind('FUNCTION_TYPE_ALIAS', 33, "function type alias");
+
+ static const ElementKind TYPE_PARAMETER = const ElementKind('TYPE_PARAMETER', 34, "type parameter");
+
+ static const ElementKind UNIVERSE = const ElementKind('UNIVERSE', 35, "<universe>");
+
+ static const List<ElementKind> values = const [
+ ANGULAR_FORMATTER,
+ ANGULAR_COMPONENT,
+ ANGULAR_CONTROLLER,
+ ANGULAR_DIRECTIVE,
+ ANGULAR_PROPERTY,
+ ANGULAR_SCOPE_PROPERTY,
+ ANGULAR_SELECTOR,
+ ANGULAR_VIEW,
+ CLASS,
+ COMPILATION_UNIT,
+ CONSTRUCTOR,
+ DYNAMIC,
+ EMBEDDED_HTML_SCRIPT,
+ ERROR,
+ EXPORT,
+ EXTERNAL_HTML_SCRIPT,
+ FIELD,
+ FUNCTION,
+ GETTER,
+ HTML,
+ IMPORT,
+ LABEL,
+ LIBRARY,
+ LOCAL_VARIABLE,
+ METHOD,
+ NAME,
+ PARAMETER,
+ POLYMER_ATTRIBUTE,
+ POLYMER_TAG_DART,
+ POLYMER_TAG_HTML,
+ PREFIX,
+ SETTER,
+ TOP_LEVEL_VARIABLE,
+ FUNCTION_TYPE_ALIAS,
+ TYPE_PARAMETER,
+ UNIVERSE];
/**
- * The superclass of the class, or `null` if the class does not have an explicit superclass.
+ * Return the kind of the given element, or [ERROR] if the element is `null`. This is
+ * a utility method that can reduce the need for null checks in other places.
+ *
+ * @param element the element whose kind is to be returned
+ * @return the kind of the given element
*/
- InterfaceType supertype;
+ static ElementKind of(Element element) {
+ if (element == null) {
+ return ERROR;
+ }
+ return element.kind;
+ }
/**
- * An array containing all of the toolkit objects attached to this class.
+ * The name displayed in the UI for this kind of element.
*/
- List<ToolkitObjectElement> _toolkitObjects = ToolkitObjectElement.EMPTY_ARRAY;
+ final String displayName;
/**
- * The type defined by the class.
+ * Initialize a newly created element kind to have the given display name.
+ *
+ * @param displayName the name displayed in the UI for this kind of element
*/
- InterfaceType type;
+ const ElementKind(String name, int ordinal, this.displayName) : super(name, ordinal);
+}
+/**
+ * The interface `ElementLocation` defines the behavior of objects that represent the location
+ * of an element within the element model.
+ */
+abstract class ElementLocation {
/**
- * An array containing all of the type parameters defined for this class.
+ * Return an encoded representation of this location that can be used to create a location that is
+ * equal to this location.
+ *
+ * @return an encoded representation of this location
*/
- List<TypeParameterElement> _typeParameters = TypeParameterElementImpl.EMPTY_ARRAY;
+ String get encoding;
+}
+/**
+ * Instances of the class `ElementLocationImpl` implement an [ElementLocation].
+ */
+class ElementLocationImpl implements ElementLocation {
/**
- * An empty array of class elements.
+ * The path to the element whose location is represented by this object.
*/
- static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>(0);
+ List<String> _components;
/**
- * Initialize a newly created class element to have the given name.
- *
- * @param name the name of this element
+ * The character used to separate components in the encoded form.
*/
- ClassElementImpl(Identifier name) : super.forNode(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitClassElement(this);
+ static int _SEPARATOR_CHAR = 0x3B;
/**
- * Set the toolkit specific information objects attached to this class.
+ * Initialize a newly created location to represent the given element.
*
- * @param toolkitObjects the toolkit objects attached to this class
+ * @param element the element whose location is being represented
*/
- void addToolkitObjects(ToolkitObjectElement toolkitObject) {
- (toolkitObject as ToolkitObjectElementImpl).enclosingElement = this;
- _toolkitObjects = ArrayUtils.add(_toolkitObjects, toolkitObject);
+ 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 = new List.from(components);
}
- @override
- List<PropertyAccessorElement> get accessors => _accessors;
-
- @override
- List<InterfaceType> get allSupertypes {
- List<InterfaceType> list = new List<InterfaceType>();
- _collectAllSupertypes(list);
- return new List.from(list);
+ /**
+ * Initialize a newly created location from the given encoded form.
+ *
+ * @param encoding the encoded form of a location
+ */
+ ElementLocationImpl.con2(String encoding) {
+ this._components = _decode(encoding);
}
@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) {
- if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
- return accessor as PropertyAccessorElementImpl;
- }
+ bool operator ==(Object object) {
+ if (identical(this, object)) {
+ return true;
}
- for (ConstructorElement constructor in _constructors) {
- if ((constructor as ConstructorElementImpl).identifier == identifier) {
- return constructor as ConstructorElementImpl;
- }
+ if (object is! ElementLocationImpl) {
+ return false;
}
- for (FieldElement field in _fields) {
- if ((field as FieldElementImpl).identifier == identifier) {
- return field as FieldElementImpl;
- }
+ ElementLocationImpl location = object as ElementLocationImpl;
+ List<String> otherComponents = location._components;
+ int length = _components.length;
+ if (otherComponents.length != length) {
+ return false;
}
- for (MethodElement method in _methods) {
- if ((method as MethodElementImpl).identifier == identifier) {
- return method as MethodElementImpl;
+ for (int i = length - 1; i >= 2; i--) {
+ if (_components[i] != otherComponents[i]) {
+ return false;
}
}
- for (TypeParameterElement typeParameter in _typeParameters) {
- if ((typeParameter as TypeParameterElementImpl).identifier == identifier) {
- return typeParameter as TypeParameterElementImpl;
- }
+ if (length > 1 && !_equalSourceComponents(_components[1], otherComponents[1])) {
+ return false;
}
- return null;
+ if (length > 0 && !_equalSourceComponents(_components[0], otherComponents[0])) {
+ return false;
+ }
+ return true;
}
- @override
- List<ConstructorElement> get constructors => _constructors;
+ /**
+ * Return the path to the element whose location is represented by this object.
+ *
+ * @return the path to the element whose location is represented by this object
+ */
+ List<String> get components => _components;
@override
- FieldElement getField(String name) {
- for (FieldElement fieldElement in _fields) {
- if (name == fieldElement.name) {
- return fieldElement;
+ String get encoding {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ int length = _components.length;
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ builder.appendChar(_SEPARATOR_CHAR);
}
+ _encode(builder, _components[i]);
}
- return null;
+ return builder.toString();
}
@override
- List<FieldElement> get fields => _fields;
-
- @override
- PropertyAccessorElement getGetter(String getterName) {
- for (PropertyAccessorElement accessor in _accessors) {
- if (accessor.isGetter && accessor.name == getterName) {
- return accessor;
+ int get hashCode {
+ int result = 1;
+ for (int i = 0; i < _components.length; i++) {
+ String component = _components[i];
+ int componentHash;
+ if (i <= 1) {
+ componentHash = _hashSourceComponent(component);
+ } else {
+ componentHash = component.hashCode;
}
+ result = 31 * result + componentHash;
}
- return null;
+ return result;
}
@override
- ElementKind get kind => ElementKind.CLASS;
+ String toString() => encoding;
- @override
- MethodElement getMethod(String methodName) {
- for (MethodElement method in _methods) {
- if (method.name == methodName) {
- return method;
+ /**
+ * Decode the encoded form of a location into an array of components.
+ *
+ * @param encoding the encoded form of a location
+ * @return the components that were encoded
+ */
+ List<String> _decode(String encoding) {
+ List<String> components = new List<String>();
+ JavaStringBuilder builder = new JavaStringBuilder();
+ 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) {
+ builder.appendChar(_SEPARATOR_CHAR);
+ index += 2;
+ } else {
+ components.add(builder.toString());
+ builder.length = 0;
+ index++;
+ }
+ } else {
+ builder.appendChar(currentChar);
+ index++;
}
}
- return null;
+ if (builder.length > 0) {
+ components.add(builder.toString());
+ }
+ return new List.from(components);
}
- @override
- List<MethodElement> get methods => _methods;
-
- @override
- ConstructorElement getNamedConstructor(String name) {
- for (ConstructorElement element in constructors) {
- String elementName = element.name;
- if (elementName != null && elementName == name) {
- return element;
+ /**
+ * Append an encoded form of the given component to the given builder.
+ *
+ * @param builder the builder to which the encoded component is to be appended
+ * @param component the component to be appended to the builder
+ */
+ void _encode(JavaStringBuilder builder, String component) {
+ int length = component.length;
+ for (int i = 0; i < length; i++) {
+ int currentChar = component.codeUnitAt(i);
+ if (currentChar == _SEPARATOR_CHAR) {
+ builder.appendChar(_SEPARATOR_CHAR);
}
+ builder.appendChar(currentChar);
}
- return null;
}
- @override
- ClassDeclaration get node => getNodeMatching((node) => node is ClassDeclaration);
-
- @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 += '=';
+ /**
+ * Return `true` if the given components, when interpreted to be encoded sources with a
+ * leading source type indicator, are equal when the source type's are ignored.
+ *
+ * @param left the left component being compared
+ * @param right the right component being compared
+ * @return `true` if the given components are equal when the source type's are ignored
+ */
+ bool _equalSourceComponents(String left, String right) {
+ // TODO(brianwilkerson) This method can go away when sources no longer have a URI kind.
+ if (left == null) {
+ return right == null;
+ } else if (right == null) {
+ return false;
}
- for (PropertyAccessorElement accessor in _accessors) {
- if (accessor.isSetter && accessor.name == setterName) {
- return accessor;
- }
+ int leftLength = left.length;
+ int rightLength = right.length;
+ if (leftLength != rightLength) {
+ return false;
+ } else if (leftLength <= 1 || rightLength <= 1) {
+ return left == right;
}
- return null;
+ return javaStringRegionMatches(left, 1, right, 1, leftLength - 1);
}
- @override
- List<ToolkitObjectElement> get toolkitObjects => _toolkitObjects;
-
- @override
- List<TypeParameterElement> get typeParameters => _typeParameters;
-
- @override
- ConstructorElement get unnamedConstructor {
- for (ConstructorElement element in constructors) {
- String name = element.displayName;
- if (name == null || name.isEmpty) {
- return element;
- }
+ /**
+ * Return the hash code of the given encoded source component, ignoring the source type indicator.
+ *
+ * @param sourceComponent the component to compute a hash code
+ * @return the hash code of the given encoded source component
+ */
+ int _hashSourceComponent(String sourceComponent) {
+ // TODO(brianwilkerson) This method can go away when sources no longer have a URI kind.
+ if (sourceComponent.length <= 1) {
+ return sourceComponent.hashCode;
}
- return null;
+ return sourceComponent.substring(1).hashCode;
}
+}
- @override
- bool get hasNonFinalField {
- List<ClassElement> classesToVisit = new List<ClassElement>();
- Set<ClassElement> visitedClasses = new Set<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;
- }
+/**
+ * The class `ElementPair` is a pair of [Element]s. [Object#equals] and
+ * [Object#hashCode] so this class can be used in hashed data structures.
+ */
+class ElementPair {
+ /**
+ * The first [Element]
+ */
+ final Element _first;
- @override
- bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER);
+ /**
+ * The second [Element]
+ */
+ final Element _second;
+
+ /**
+ * The sole constructor for this class, taking two [Element]s.
+ *
+ * @param first the first element
+ * @param second the second element
+ */
+ ElementPair(this._first, this._second);
@override
- bool get hasStaticMember {
- for (MethodElement method in _methods) {
- if (method.isStatic) {
- return true;
- }
+ bool operator ==(Object object) {
+ if (identical(object, this)) {
+ return true;
}
- for (PropertyAccessorElement accessor in _accessors) {
- if (accessor.isStatic) {
- return true;
- }
+ if (object is ElementPair) {
+ ElementPair elementPair = object;
+ return (_first == elementPair._first) && (_second == elementPair._second);
}
return false;
}
- @override
- bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+ /**
+ * Return the first element.
+ *
+ * @return the first element
+ */
+ Element get firstElt => _first;
- @override
- bool get isOrInheritsProxy => _safeIsOrInheritsProxy(this, new Set<ClassElement>());
+ /**
+ * Return the second element
+ *
+ * @return the second element
+ */
+ Element get secondElt => _second;
@override
- bool get isProxy {
- for (ElementAnnotation annotation in metadata) {
- if (annotation.isProxy) {
- return true;
- }
- }
- return false;
- }
+ int get hashCode => ObjectUtilities.combineHashCodes(_first.hashCode, _second.hashCode);
+}
- @override
- bool get isTypedef => hasModifier(Modifier.TYPEDEF);
+/**
+ * The interface `ElementVisitor` defines the behavior of objects that can be used to visit an
+ * element structure.
+ */
+abstract class ElementVisitor<R> {
+ R visitAngularComponentElement(AngularComponentElement element);
- @override
- bool get isValidMixin => hasModifier(Modifier.MIXIN);
+ R visitAngularControllerElement(AngularControllerElement element);
- @override
- PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library) {
- Set<ClassElement> visitedClasses = new Set<ClassElement>();
- ClassElement currentElement = this;
- while (currentElement != null && !visitedClasses.contains(currentElement)) {
- visitedClasses.add(currentElement);
- PropertyAccessorElement element = currentElement.getGetter(getterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- for (InterfaceType mixin in currentElement.mixins) {
- ClassElement mixinElement = mixin.element;
- if (mixinElement != null) {
- element = mixinElement.getGetter(getterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- }
- InterfaceType supertype = currentElement.supertype;
- if (supertype == null) {
- return null;
- }
- currentElement = supertype.element;
- }
- return null;
- }
+ R visitAngularDirectiveElement(AngularDecoratorElement element);
- @override
- MethodElement lookUpMethod(String methodName, LibraryElement library) {
- Set<ClassElement> visitedClasses = new Set<ClassElement>();
- ClassElement currentElement = this;
- while (currentElement != null && !visitedClasses.contains(currentElement)) {
- visitedClasses.add(currentElement);
- MethodElement element = currentElement.getMethod(methodName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- for (InterfaceType mixin in currentElement.mixins) {
- ClassElement mixinElement = mixin.element;
- if (mixinElement != null) {
- element = mixinElement.getMethod(methodName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- }
- InterfaceType supertype = currentElement.supertype;
- if (supertype == null) {
- return null;
- }
- currentElement = supertype.element;
- }
- return null;
- }
+ R visitAngularFormatterElement(AngularFormatterElement element);
- @override
- PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library) {
- Set<ClassElement> visitedClasses = new Set<ClassElement>();
- ClassElement currentElement = this;
- while (currentElement != null && !visitedClasses.contains(currentElement)) {
- visitedClasses.add(currentElement);
- PropertyAccessorElement element = currentElement.getSetter(setterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- for (InterfaceType mixin in currentElement.mixins) {
- ClassElement mixinElement = mixin.element;
- if (mixinElement != null) {
- element = mixinElement.getSetter(setterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- }
- InterfaceType supertype = currentElement.supertype;
- if (supertype == null) {
- return null;
- }
- currentElement = supertype.element;
- }
- return null;
- }
+ R visitAngularPropertyElement(AngularPropertyElement element);
+
+ R visitAngularScopePropertyElement(AngularScopePropertyElement element);
+
+ R visitAngularSelectorElement(AngularSelectorElement element);
+
+ R visitAngularViewElement(AngularViewElement element);
+
+ R visitClassElement(ClassElement element);
+
+ R visitCompilationUnitElement(CompilationUnitElement element);
+
+ R visitConstructorElement(ConstructorElement element);
+
+ R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element);
+
+ R visitExportElement(ExportElement element);
+
+ R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element);
+
+ R visitFieldElement(FieldElement element);
+
+ R visitFieldFormalParameterElement(FieldFormalParameterElement element);
+
+ R visitFunctionElement(FunctionElement element);
+
+ R visitFunctionTypeAliasElement(FunctionTypeAliasElement element);
+
+ R visitHtmlElement(HtmlElement element);
+
+ R visitImportElement(ImportElement element);
+
+ R visitLabelElement(LabelElement element);
+
+ R visitLibraryElement(LibraryElement element);
+
+ R visitLocalVariableElement(LocalVariableElement element);
+
+ R visitMethodElement(MethodElement element);
+
+ R visitMultiplyDefinedElement(MultiplyDefinedElement element);
+
+ R visitParameterElement(ParameterElement element);
+ R visitPolymerAttributeElement(PolymerAttributeElement element);
+
+ R visitPolymerTagDartElement(PolymerTagDartElement element);
+
+ R visitPolymerTagHtmlElement(PolymerTagHtmlElement element);
+
+ R visitPrefixElement(PrefixElement element);
+
+ R visitPropertyAccessorElement(PropertyAccessorElement element);
+
+ R visitTopLevelVariableElement(TopLevelVariableElement element);
+
+ R visitTypeParameterElement(TypeParameterElement element);
+}
+
+/**
+ * The interface `EmbeddedHtmlScriptElement` defines the behavior of elements representing a
+ * script tag in an HTML file having content that defines a Dart library.
+ */
+abstract class EmbeddedHtmlScriptElement implements HtmlScriptElement {
/**
- * Set whether this class is abstract to correspond to the given value.
+ * Return the library element defined by the content of the script tag.
*
- * @param isAbstract `true` if the class is abstract
+ * @return the library element (not `null`)
*/
- void set abstract(bool isAbstract) {
- setModifier(Modifier.ABSTRACT, isAbstract);
- }
+ LibraryElement get scriptLibrary;
+}
+/**
+ * Instances of the class `EmbeddedHtmlScriptElementImpl` implement an
+ * [EmbeddedHtmlScriptElement].
+ */
+class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl implements EmbeddedHtmlScriptElement {
/**
- * Set the accessors contained in this class to the given accessors.
- *
- * @param accessors the accessors contained in this class
+ * The library defined by the script tag's content.
*/
- void set accessors(List<PropertyAccessorElement> accessors) {
- for (PropertyAccessorElement accessor in accessors) {
- (accessor as PropertyAccessorElementImpl).enclosingElement = this;
- }
- this._accessors = accessors;
- }
+ LibraryElement _scriptLibrary;
/**
- * Set the constructors contained in this class to the given constructors.
+ * Initialize a newly created script element to have the specified tag name and offset.
*
- * @param constructors the constructors contained in this class
+ * @param node the XML node from which this element is derived (not `null`)
*/
- void set constructors(List<ConstructorElement> constructors) {
- for (ConstructorElement constructor in constructors) {
- (constructor as ConstructorElementImpl).enclosingElement = this;
- }
- this._constructors = constructors;
- }
+ EmbeddedHtmlScriptElementImpl(XmlTagNode node) : super(node);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitEmbeddedHtmlScriptElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.EMBEDDED_HTML_SCRIPT;
+
+ @override
+ LibraryElement get scriptLibrary => _scriptLibrary;
/**
- * Set the fields contained in this class to the given fields.
+ * Set the script library defined by the script tag's content.
*
- * @param fields the fields contained in this class
+ * @param scriptLibrary the library or `null` if none
*/
- void set fields(List<FieldElement> fields) {
- for (FieldElement field in fields) {
- (field as FieldElementImpl).enclosingElement = this;
- }
- this._fields = fields;
+ void set scriptLibrary(LibraryElementImpl scriptLibrary) {
+ scriptLibrary.enclosingElement = this;
+ this._scriptLibrary = scriptLibrary;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ safelyVisitChild(_scriptLibrary, visitor);
}
+}
+/**
+ * The interface `ExecutableElement` defines the behavior of elements representing an
+ * executable object, including functions, methods, constructors, getters, and setters.
+ */
+abstract class ExecutableElement implements Element {
/**
- * Set whether this class references 'super' to the given value.
+ * Return an array containing all of the functions defined within this executable element.
*
- * @param isReferencedSuper `true` references 'super'
+ * @return the functions defined within this executable element
*/
- void set hasReferenceToSuper(bool isReferencedSuper) {
- setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper);
- }
+ List<FunctionElement> get functions;
/**
- * Set the methods contained in this class to the given methods.
+ * Return an array containing all of the labels defined within this executable element.
*
- * @param methods the methods contained in this class
+ * @return the labels defined within this executable element
*/
- void set methods(List<MethodElement> methods) {
- for (MethodElement method in methods) {
- (method as MethodElementImpl).enclosingElement = this;
- }
- this._methods = methods;
- }
+ List<LabelElement> get labels;
/**
- * Set whether this class is defined by a typedef construct to correspond to the given value.
+ * Return an array containing all of the local variables defined within this executable element.
*
- * @param isTypedef `true` if the class is defined by a typedef construct
+ * @return the local variables defined within this executable element
*/
- void set typedef(bool isTypedef) {
- setModifier(Modifier.TYPEDEF, isTypedef);
- }
+ List<LocalVariableElement> get localVariables;
/**
- * Set the type parameters defined for this class to the given type parameters.
+ * Return an array containing all of the parameters defined by this executable element.
*
- * @param typeParameters the type parameters defined for this class
+ * @return the parameters defined by this executable element
*/
- void set typeParameters(List<TypeParameterElement> typeParameters) {
- for (TypeParameterElement typeParameter in typeParameters) {
- (typeParameter as TypeParameterElementImpl).enclosingElement = this;
- }
- this._typeParameters = typeParameters;
- }
+ List<ParameterElement> get parameters;
/**
- * Set whether this class is a valid mixin to correspond to the given value.
+ * Return the return type defined by this executable element.
*
- * @param isValidMixin `true` if this class can be used as a mixin
+ * @return the return type defined by this executable element
*/
- void set validMixin(bool isValidMixin) {
- setModifier(Modifier.MIXIN, isValidMixin);
- }
-
- @override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChildren(_accessors, visitor);
- safelyVisitChildren(_constructors, visitor);
- safelyVisitChildren(_fields, visitor);
- safelyVisitChildren(_methods, visitor);
- safelyVisitChildren(_toolkitObjects, visitor);
- safelyVisitChildren(_typeParameters, visitor);
- }
+ DartType get returnType;
- @override
- void appendTo(JavaStringBuilder builder) {
- String name = displayName;
- if (name == null) {
- builder.append("{unnamed class}");
- } else {
- builder.append(name);
- }
- int variableCount = _typeParameters.length;
- if (variableCount > 0) {
- builder.append("<");
- for (int i = 0; i < variableCount; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- (_typeParameters[i] as TypeParameterElementImpl).appendTo(builder);
- }
- builder.append(">");
- }
- }
+ /**
+ * Return the type of function defined by this executable element.
+ *
+ * @return the type of function defined by this executable element
+ */
+ FunctionType get type;
- 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);
- }
- }
- }
- }
- }
+ /**
+ * Return `true` if this executable element is an operator. The test may be based on the
+ * name of the executable element, in which case the result will be correct when the name is
+ * legal.
+ *
+ * @return `true` if this executable element is an operator
+ */
+ bool get isOperator;
- bool _safeIsOrInheritsProxy(ClassElement classElt, Set<ClassElement> visitedClassElts) {
- if (visitedClassElts.contains(classElt)) {
- return false;
- }
- visitedClassElts.add(classElt);
- if (classElt.isProxy) {
- return true;
- } else if (classElt.supertype != null && _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) {
- return true;
- }
- List<InterfaceType> supertypes = classElt.interfaces;
- for (int i = 0; i < supertypes.length; i++) {
- if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) {
- return true;
- }
- }
- supertypes = classElt.mixins;
- for (int i = 0; i < supertypes.length; i++) {
- if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) {
- return true;
- }
- }
- return false;
- }
+ /**
+ * Return `true` if this element is a static element. A static element is an element that is
+ * not associated with a particular instance, but rather with an entire library or class.
+ *
+ * @return `true` if this executable element is a static element
+ */
+ bool get isStatic;
}
/**
- * Instances of the class `CompilationUnitElementImpl` implement a
- * [CompilationUnitElement].
+ * The abstract class `ExecutableElementImpl` implements the behavior common to
+ * `ExecutableElement`s.
*/
-class CompilationUnitElementImpl extends UriReferencedElementImpl implements CompilationUnitElement {
- /**
- * An empty array of compilation unit elements.
- */
- static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElement>(0);
-
+abstract class ExecutableElementImpl extends ElementImpl implements ExecutableElement {
/**
- * The source that corresponds to this compilation unit.
+ * An array containing all of the functions defined within this executable element.
*/
- Source source;
+ List<FunctionElement> _functions = FunctionElementImpl.EMPTY_ARRAY;
/**
- * An array containing all of the top-level accessors (getters and setters) contained in this
- * compilation unit.
+ * An array containing all of the labels defined within this executable element.
*/
- List<PropertyAccessorElement> _accessors = PropertyAccessorElementImpl.EMPTY_ARRAY;
+ List<LabelElement> _labels = LabelElementImpl.EMPTY_ARRAY;
/**
- * An array containing all of the top-level functions contained in this compilation unit.
+ * An array containing all of the local variables defined within this executable element.
*/
- List<FunctionElement> _functions = FunctionElementImpl.EMPTY_ARRAY;
+ List<LocalVariableElement> _localVariables = LocalVariableElementImpl.EMPTY_ARRAY;
/**
- * A table mapping elements to associated toolkit objects.
+ * An array containing all of the parameters defined by this executable element.
*/
- Map<Element, List<ToolkitObjectElement>> _toolkitObjects = {};
+ List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
/**
- * An array containing all of the function type aliases contained in this compilation unit.
+ * The return type defined by this executable element.
*/
- List<FunctionTypeAliasElement> _typeAliases = FunctionTypeAliasElementImpl.EMPTY_ARRAY;
+ DartType returnType;
/**
- * An array containing all of the types contained in this compilation unit.
+ * The type of function defined by this executable element.
*/
- List<ClassElement> _types = ClassElementImpl.EMPTY_ARRAY;
+ FunctionType type;
/**
- * An array containing all of the variables contained in this compilation unit.
+ * An empty array of executable elements.
*/
- List<TopLevelVariableElement> _variables = TopLevelVariableElementImpl.EMPTY_ARRAY;
+ static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>(0);
/**
- * An array containing all of the Angular views contained in this compilation unit.
+ * Initialize a newly created executable element to have the given name.
+ *
+ * @param name the name of this element
*/
- List<AngularViewElement> _angularViews = AngularViewElement.EMPTY_ARRAY;
+ ExecutableElementImpl.forNode(Identifier name) : super.forNode(name);
/**
- * Initialize a newly created compilation unit element to have the given name.
+ * Initialize a newly created executable element to have the given name.
*
* @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- CompilationUnitElementImpl(String name) : super(name, -1);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this);
-
- @override
- bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && source == (object as CompilationUnitElementImpl).source;
-
- @override
- List<PropertyAccessorElement> get accessors => _accessors;
-
- @override
- List<AngularViewElement> get angularViews => _angularViews;
+ ExecutableElementImpl(String name, int nameOffset) : super(name, nameOffset);
@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) {
- if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
- return accessor as PropertyAccessorElementImpl;
- }
- }
- for (VariableElement variable in _variables) {
- if ((variable as VariableElementImpl).identifier == identifier) {
- return variable as VariableElementImpl;
- }
- }
for (ExecutableElement function in _functions) {
if ((function as ExecutableElementImpl).identifier == identifier) {
return function as ExecutableElementImpl;
}
}
- for (FunctionTypeAliasElement typeAlias in _typeAliases) {
- if ((typeAlias as FunctionTypeAliasElementImpl).identifier == identifier) {
- return typeAlias as FunctionTypeAliasElementImpl;
+ for (LabelElement label in _labels) {
+ if ((label as LabelElementImpl).identifier == identifier) {
+ return label as LabelElementImpl;
}
}
- for (ClassElement type in _types) {
- if ((type as ClassElementImpl).identifier == identifier) {
- return type as ClassElementImpl;
+ for (VariableElement variable in _localVariables) {
+ if ((variable as VariableElementImpl).identifier == identifier) {
+ return variable as VariableElementImpl;
+ }
+ }
+ for (ParameterElement parameter in _parameters) {
+ if ((parameter as ParameterElementImpl).identifier == identifier) {
+ return parameter as ParameterElementImpl;
}
}
return null;
}
@override
- LibraryElement get enclosingElement => super.enclosingElement as LibraryElement;
-
- @override
List<FunctionElement> get functions => _functions;
@override
- List<FunctionTypeAliasElement> get functionTypeAliases => _typeAliases;
-
- @override
- ElementKind get kind => ElementKind.COMPILATION_UNIT;
-
- @override
- CompilationUnit get node => unit;
-
- @override
- List<TopLevelVariableElement> get topLevelVariables => _variables;
-
- @override
- ClassElement getType(String className) {
- for (ClassElement type in _types) {
- if (type.name == className) {
- return type;
- }
- }
- return null;
- }
+ List<LabelElement> get labels => _labels;
@override
- List<ClassElement> get types => _types;
+ List<LocalVariableElement> get localVariables => _localVariables;
@override
- int get hashCode => source.hashCode;
+ List<ParameterElement> get parameters => _parameters;
@override
- bool get hasLoadLibraryFunction {
- for (int i = 0; i < _functions.length; i++) {
- if (_functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) {
- return true;
- }
- }
- return false;
- }
+ bool get isOperator => false;
/**
- * Set the top-level accessors (getters and setters) contained in this compilation unit to the
- * given accessors.
+ * Set the functions defined within this executable element to the given functions.
*
- * @param the top-level accessors (getters and setters) contained in this compilation unit
+ * @param functions the functions defined within this executable element
*/
- void set accessors(List<PropertyAccessorElement> accessors) {
- for (PropertyAccessorElement accessor in accessors) {
- (accessor as PropertyAccessorElementImpl).enclosingElement = this;
+ void set functions(List<FunctionElement> functions) {
+ for (FunctionElement function in functions) {
+ (function as FunctionElementImpl).enclosingElement = this;
}
- this._accessors = accessors;
+ this._functions = functions;
}
/**
- * Set the Angular views defined in this compilation unit.
- *
- * @param angularViews the Angular views defined in this compilation unit
- */
- void set angularViews(List<AngularViewElement> angularViews) {
- for (AngularViewElement view in angularViews) {
- (view as AngularViewElementImpl).enclosingElement = this;
- }
- this._angularViews = angularViews;
- }
-
- /**
- * Set the top-level functions contained in this compilation unit to the given functions.
- *
- * @param functions the top-level functions contained in this compilation unit
- */
- void set functions(List<FunctionElement> functions) {
- for (FunctionElement function in functions) {
- (function as FunctionElementImpl).enclosingElement = this;
- }
- this._functions = functions;
- }
-
- /**
- * Set the top-level variables contained in this compilation unit to the given variables.
+ * Set the labels defined within this executable element to the given labels.
*
- * @param variables the top-level variables contained in this compilation unit
+ * @param labels the labels defined within this executable element
*/
- void set topLevelVariables(List<TopLevelVariableElement> variables) {
- for (TopLevelVariableElement field in variables) {
- (field as TopLevelVariableElementImpl).enclosingElement = this;
+ void set labels(List<LabelElement> labels) {
+ for (LabelElement label in labels) {
+ (label as LabelElementImpl).enclosingElement = this;
}
- this._variables = variables;
+ this._labels = labels;
}
/**
- * Set the function type aliases contained in this compilation unit to the given type aliases.
+ * Set the local variables defined within this executable element to the given variables.
*
- * @param typeAliases the function type aliases contained in this compilation unit
+ * @param localVariables the local variables defined within this executable element
*/
- void set typeAliases(List<FunctionTypeAliasElement> typeAliases) {
- for (FunctionTypeAliasElement typeAlias in typeAliases) {
- (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this;
+ void set localVariables(List<LocalVariableElement> localVariables) {
+ for (LocalVariableElement variable in localVariables) {
+ (variable as LocalVariableElementImpl).enclosingElement = this;
}
- this._typeAliases = typeAliases;
+ this._localVariables = localVariables;
}
/**
- * Set the types contained in this compilation unit to the given types.
+ * Set the parameters defined by this executable element to the given parameters.
*
- * @param types types contained in this compilation unit
+ * @param parameters the parameters defined by this executable element
*/
- void set types(List<ClassElement> types) {
- for (ClassElement type in types) {
- (type as ClassElementImpl).enclosingElement = this;
+ void set parameters(List<ParameterElement> parameters) {
+ for (ParameterElement parameter in parameters) {
+ (parameter as ParameterElementImpl).enclosingElement = this;
}
- this._types = types;
+ this._parameters = parameters;
}
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- safelyVisitChildren(_accessors, visitor);
safelyVisitChildren(_functions, visitor);
- safelyVisitChildren(_typeAliases, visitor);
- safelyVisitChildren(_types, visitor);
- safelyVisitChildren(_variables, visitor);
- safelyVisitChildren(_angularViews, visitor);
+ safelyVisitChildren(_labels, visitor);
+ safelyVisitChildren(_localVariables, visitor);
+ safelyVisitChildren(_parameters, visitor);
}
@override
void appendTo(JavaStringBuilder builder) {
- if (source == null) {
- builder.append("{compilation unit}");
- } else {
- builder.append(source.fullName);
+ if (this.kind != ElementKind.GETTER) {
+ builder.append("(");
+ String closing = null;
+ ParameterKind kind = ParameterKind.REQUIRED;
+ int parameterCount = _parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl;
+ ParameterKind parameterKind = parameter.parameterKind;
+ if (parameterKind != kind) {
+ if (closing != null) {
+ builder.append(closing);
+ }
+ if (parameterKind == ParameterKind.POSITIONAL) {
+ builder.append("[");
+ closing = "]";
+ } else if (parameterKind == ParameterKind.NAMED) {
+ builder.append("{");
+ closing = "}";
+ } else {
+ closing = null;
+ }
+ }
+ kind = parameterKind;
+ parameter.appendToWithoutDelimiters(builder);
+ }
+ if (closing != null) {
+ builder.append(closing);
+ }
+ builder.append(")");
}
- }
-
- @override
- String get identifier => source.encoding;
-
- /**
- * Returns the associated toolkit objects.
- *
- * @param element the [Element] to get toolkit objects for
- * @return the associated toolkit objects, may be empty, but not `null`
- */
- List<ToolkitObjectElement> _getToolkitObjects(Element element) {
- List<ToolkitObjectElement> objects = _toolkitObjects[element];
- if (objects != null) {
- return objects;
+ if (type != null) {
+ builder.append(Element.RIGHT_ARROW);
+ builder.append(type.returnType);
}
- return ToolkitObjectElement.EMPTY_ARRAY;
- }
-
- /**
- * Sets the toolkit objects that are associated with the given [Element].
- *
- * @param element the [Element] to associate toolkit objects with
- * @param objects the toolkit objects to associate
- */
- void _setToolkitObjects(Element element, List<ToolkitObjectElement> objects) {
- _toolkitObjects[element] = objects;
}
}
/**
- * Instances of the class `ConstFieldElementImpl` implement a `FieldElement` for a
- * 'const' field that has an initializer.
+ * The abstract class `ExecutableMember` defines the behavior common to members that represent
+ * an executable element defined in a parameterized type where the values of the type parameters are
+ * known.
*/
-class ConstFieldElementImpl extends FieldElementImpl {
- /**
- * The result of evaluating this variable's initializer.
- */
- EvaluationResultImpl _result;
-
+abstract class ExecutableMember extends Member implements ExecutableElement {
/**
- * Initialize a newly created field element to have the given name.
+ * Initialize a newly created element to represent an executable element of the given
+ * parameterized type.
*
- * @param name the name of this element
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
*/
- ConstFieldElementImpl(Identifier name) : super.con1(name);
+ ExecutableMember(ExecutableElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
@override
- EvaluationResultImpl get evaluationResult => _result;
+ ExecutableElement get baseElement => super.baseElement as ExecutableElement;
@override
- void set evaluationResult(EvaluationResultImpl result) {
- this._result = result;
+ List<FunctionElement> get functions {
+ //
+ // Elements within this element should have type parameters substituted, just like this element.
+ //
+ throw new UnsupportedOperationException();
}
-}
-
-/**
- * Instances of the class `ConstLocalVariableElementImpl` implement a
- * `LocalVariableElement` for a local 'const' variable that has an initializer.
- */
-class ConstLocalVariableElementImpl extends LocalVariableElementImpl {
- /**
- * The result of evaluating this variable's initializer.
- */
- EvaluationResultImpl _result;
- /**
- * Initialize a newly created local variable element to have the given name.
- *
- * @param name the name of this element
- */
- ConstLocalVariableElementImpl(Identifier name) : super(name);
+ @override
+ List<LabelElement> get labels => baseElement.labels;
@override
- EvaluationResultImpl get evaluationResult => _result;
+ List<LocalVariableElement> get localVariables {
+ //
+ // Elements within this element should have type parameters substituted, just like this element.
+ //
+ throw new UnsupportedOperationException();
+ }
@override
- void set evaluationResult(EvaluationResultImpl result) {
- this._result = result;
+ List<ParameterElement> get parameters {
+ List<ParameterElement> baseParameters = baseElement.parameters;
+ int parameterCount = baseParameters.length;
+ if (parameterCount == 0) {
+ return baseParameters;
+ }
+ List<ParameterElement> parameterizedParameters = new List<ParameterElement>(parameterCount);
+ for (int i = 0; i < parameterCount; i++) {
+ parameterizedParameters[i] = ParameterMember.from(baseParameters[i], definingType);
+ }
+ return parameterizedParameters;
}
-}
-/**
- * Instances of the class `ConstTopLevelVariableElementImpl` implement a
- * `TopLevelVariableElement` for a top-level 'const' variable that has an initializer.
- */
-class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl {
- /**
- * The result of evaluating this variable's initializer.
- */
- EvaluationResultImpl _result;
+ @override
+ DartType get returnType => substituteFor(baseElement.returnType);
- /**
- * Initialize a newly created top-level variable element to have the given name.
- *
- * @param name the name of this element
- */
- ConstTopLevelVariableElementImpl(Identifier name) : super.con1(name);
+ @override
+ FunctionType get type => substituteFor(baseElement.type);
@override
- EvaluationResultImpl get evaluationResult => _result;
+ bool get isOperator => baseElement.isOperator;
@override
- void set evaluationResult(EvaluationResultImpl result) {
- this._result = result;
+ bool get isStatic => baseElement.isStatic;
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ // TODO(brianwilkerson) We need to finish implementing the accessors used below so that we can
+ // safely invoke them.
+ super.visitChildren(visitor);
+ safelyVisitChildren(baseElement.functions, visitor);
+ safelyVisitChildren(labels, visitor);
+ safelyVisitChildren(baseElement.localVariables, visitor);
+ safelyVisitChildren(parameters, visitor);
}
}
/**
- * Instances of the class `ConstructorElementImpl` implement a `ConstructorElement`.
+ * The interface `ExportElement` defines the behavior of objects representing information
+ * about a single export directive within a library.
*/
-class ConstructorElementImpl extends ExecutableElementImpl implements ConstructorElement {
+abstract class ExportElement implements Element, UriReferencedElement {
/**
- * An empty array of constructor elements.
+ * An empty array of export elements.
*/
- static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>(0);
+ static final List<ExportElement> EMPTY_ARRAY = new List<ExportElement>(0);
/**
- * The constructor to which this constructor is redirecting.
+ * Return an array containing the combinators that were specified as part of the export directive
+ * in the order in which they were specified.
+ *
+ * @return the combinators specified in the export directive
*/
- ConstructorElement redirectedConstructor;
+ List<NamespaceCombinator> get combinators;
/**
- * Initialize a newly created constructor element to have the given name.
+ * Return the library that is exported from this library by this export directive.
*
- * @param name the name of this element
+ * @return the library that is exported from this library
*/
- ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
+ LibraryElement get exportedLibrary;
+}
+/**
+ * Instances of the class `ExportElementImpl` implement an [ExportElement].
+ */
+class ExportElementImpl extends UriReferencedElementImpl implements ExportElement {
/**
- * Initialize a newly created constructor element to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * The library that is exported from this library by this export directive.
*/
- ConstructorElementImpl(String name, int nameOffset) : super(name, nameOffset);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
+ LibraryElement exportedLibrary;
- @override
- ClassElement get enclosingElement => super.enclosingElement as ClassElement;
+ /**
+ * The combinators that were specified as part of the export directive in the order in which they
+ * were specified.
+ */
+ List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_ARRAY;
- @override
- ElementKind get kind => ElementKind.CONSTRUCTOR;
+ /**
+ * Initialize a newly created export element.
+ */
+ ExportElementImpl() : super(null, -1);
@override
- ConstructorDeclaration get node => getNodeMatching((node) => node is ConstructorDeclaration);
+ accept(ElementVisitor visitor) => visitor.visitExportElement(this);
@override
- bool get isConst => hasModifier(Modifier.CONST);
+ ElementKind get kind => ElementKind.EXPORT;
@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;
+ void appendTo(JavaStringBuilder builder) {
+ builder.append("export ");
+ (exportedLibrary as LibraryElementImpl).appendTo(builder);
}
@override
- bool get isFactory => hasModifier(Modifier.FACTORY);
-
- @override
- bool get isStatic => false;
-
- /**
- * Set whether this constructor represents a 'const' constructor to the given value.
- *
- * @param isConst `true` if this constructor represents a 'const' constructor
- */
- void set const2(bool isConst) {
- setModifier(Modifier.CONST, isConst);
- }
+ String get identifier => exportedLibrary.name;
+}
+/**
+ * The interface `ExternalHtmlScriptElement` defines the behavior of elements representing a
+ * script tag in an HTML file having a `source` attribute that references a Dart library
+ * source file.
+ */
+abstract class ExternalHtmlScriptElement implements HtmlScriptElement {
/**
- * Set whether this constructor represents a factory method to the given value.
+ * Return the source referenced by this element, or `null` if this element does not
+ * reference a Dart library source file.
*
- * @param isFactory `true` if this constructor represents a factory method
+ * @return the source for the external Dart library
*/
- void set factory(bool isFactory) {
- setModifier(Modifier.FACTORY, isFactory);
- }
-
- @override
- void appendTo(JavaStringBuilder builder) {
- builder.append(enclosingElement.displayName);
- String name = displayName;
- if (name != null && !name.isEmpty) {
- builder.append(".");
- builder.append(name);
- }
- super.appendTo(builder);
- }
+ Source get scriptSource;
}
/**
- * Instances of the class `DefaultFieldFormalParameterElementImpl` implement a
- * `FieldFormalParameterElementImpl` for parameters that have an initializer.
+ * Instances of the class `ExternalHtmlScriptElementImpl` implement an
+ * [ExternalHtmlScriptElement].
*/
-class DefaultFieldFormalParameterElementImpl extends FieldFormalParameterElementImpl {
+class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl implements ExternalHtmlScriptElement {
/**
- * The result of evaluating this variable's initializer.
+ * The source specified in the `source` attribute or `null` if unspecified.
*/
- EvaluationResultImpl _result;
+ Source scriptSource;
/**
- * Initialize a newly created parameter element to have the given name.
+ * Initialize a newly created script element to have the specified tag name and offset.
*
- * @param name the name of this element
+ * @param node the XML node from which this element is derived (not `null`)
*/
- DefaultFieldFormalParameterElementImpl(Identifier name) : super(name);
+ ExternalHtmlScriptElementImpl(XmlTagNode node) : super(node);
@override
- EvaluationResultImpl get evaluationResult => _result;
+ accept(ElementVisitor visitor) => visitor.visitExternalHtmlScriptElement(this);
@override
- void set evaluationResult(EvaluationResultImpl result) {
- this._result = result;
- }
+ ElementKind get kind => ElementKind.EXTERNAL_HTML_SCRIPT;
}
/**
- * Instances of the class `DefaultParameterElementImpl` implement a `ParameterElement`
- * for parameters that have an initializer.
+ * The interface `FieldElement` defines the behavior of elements representing a field defined
+ * within a type.
*/
-class DefaultParameterElementImpl extends ParameterElementImpl {
+abstract class FieldElement implements ClassMemberElement, PropertyInducingElement {
+}
+
+/**
+ * Instances of the class `FieldElementImpl` implement a `FieldElement`.
+ */
+class FieldElementImpl extends PropertyInducingElementImpl implements FieldElement {
/**
- * The result of evaluating this variable's initializer.
+ * An empty array of field elements.
*/
- EvaluationResultImpl _result;
+ static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>(0);
/**
- * Initialize a newly created parameter element to have the given name.
+ * Initialize a newly created field element to have the given name.
*
* @param name the name of this element
*/
- DefaultParameterElementImpl(Identifier name) : super.con1(name);
+ FieldElementImpl.con1(Identifier name) : super.con1(name);
+
+ /**
+ * Initialize a newly created synthetic field element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ FieldElementImpl.con2(String name) : super.con2(name);
@override
- EvaluationResultImpl get evaluationResult => _result;
+ accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
@override
- void set evaluationResult(EvaluationResultImpl result) {
- this._result = result;
+ ClassElement get enclosingElement => super.enclosingElement as ClassElement;
+
+ @override
+ ElementKind get kind => ElementKind.FIELD;
+
+ @override
+ bool get isStatic => hasModifier(Modifier.STATIC);
+
+ /**
+ * Set whether this field is static to correspond to the given value.
+ *
+ * @param isStatic `true` if the field is static
+ */
+ void set static(bool isStatic) {
+ setModifier(Modifier.STATIC, isStatic);
}
}
/**
- * Instances of the class `DynamicElementImpl` represent the synthetic element representing
- * the declaration of the type `dynamic`.
+ * The interface `FieldFormalParameterElement` defines the behavior of elements representing a
+ * field formal parameter defined within a constructor element.
*/
-class DynamicElementImpl extends ElementImpl {
+abstract class FieldFormalParameterElement implements ParameterElement {
/**
- * Return the unique instance of this class.
+ * Return the field element associated with this field formal parameter, or `null` if the
+ * parameter references a field that doesn't exist.
*
- * @return the unique instance of this class
+ * @return the field element associated with this field formal parameter
*/
- static DynamicElementImpl get instance => DynamicTypeImpl.instance.element as DynamicElementImpl;
+ FieldElement get field;
+}
+/**
+ * Instances of the class `FieldFormalParameterElementImpl` extend
+ * [ParameterElementImpl] to provide the additional information of the [FieldElement]
+ * associated with the parameter.
+ */
+class FieldFormalParameterElementImpl extends ParameterElementImpl implements FieldFormalParameterElement {
/**
- * The type defined by this element.
+ * The field associated with this field formal parameter.
*/
- DynamicTypeImpl type;
+ FieldElement field;
/**
- * 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 [getInstance].
+ * Initialize a newly created parameter element to have the given name.
+ *
+ * @param name the name of this element
*/
- DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) {
- setModifier(Modifier.SYNTHETIC, true);
- }
+ FieldFormalParameterElementImpl(Identifier name) : super.con1(name);
@override
- accept(ElementVisitor visitor) => null;
+ accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(this);
@override
- ElementKind get kind => ElementKind.DYNAMIC;
+ bool get isInitializingFormal => true;
}
/**
- * Instances of the class `ElementAnnotationImpl` implement an [ElementAnnotation].
+ * Instances of the class `FieldFormalParameterMember` represent a parameter element defined
+ * in a parameterized type where the values of the type parameters are known.
*/
-class ElementAnnotationImpl implements ElementAnnotation {
- /**
- * The element representing the field, variable, or constructor being used as an annotation.
- */
- final Element element;
-
- /**
- * An empty array of annotations.
- */
- static List<ElementAnnotationImpl> EMPTY_ARRAY = new List<ElementAnnotationImpl>(0);
-
- /**
- * The name of the class used to mark an element as being deprecated.
- */
- static String _DEPRECATED_CLASS_NAME = "Deprecated";
-
+class FieldFormalParameterMember extends ParameterMember implements FieldFormalParameterElement {
/**
- * The name of the top-level variable used to mark an element as being deprecated.
+ * Initialize a newly created element to represent a parameter of the given parameterized type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
*/
- static String _DEPRECATED_VARIABLE_NAME = "deprecated";
+ FieldFormalParameterMember(FieldFormalParameterElement baseElement, ParameterizedType definingType) : super(baseElement, definingType);
- /**
- * 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";
+ @override
+ accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(this);
- /**
- * The name of the top-level variable used to mark a class as implementing a proxy object.
- */
- static String PROXY_VARIABLE_NAME = "proxy";
+ @override
+ FieldElement get field => (baseElement as FieldFormalParameterElement).field;
+}
+/**
+ * Instances of the class `FieldMember` represent a field element defined in a parameterized
+ * type where the values of the type parameters are known.
+ */
+class FieldMember extends VariableMember implements FieldElement {
/**
- * Initialize a newly created annotation.
+ * If the given field's type is different when any type parameters from the defining type's
+ * declaration are replaced with the actual type arguments from the defining type, create a field
+ * member representing the given field. Return the member that was created, or the base field if
+ * no member was created.
*
- * @param element the element representing the field, variable, or constructor being used as an
- * annotation
+ * @param baseField the base field for which a member might be created
+ * @param definingType the type defining the parameters and arguments to be used in the
+ * substitution
+ * @return the field element that will return the correctly substituted types
*/
- ElementAnnotationImpl(this.element);
-
- @override
- bool get isDeprecated {
- if (element != null) {
- LibraryElement library = element.library;
- if (library != null && library.isDartCore) {
- if (element is ConstructorElement) {
- ConstructorElement constructorElement = element as ConstructorElement;
- if (constructorElement.enclosingElement.name == _DEPRECATED_CLASS_NAME) {
- return true;
- }
- } else if (element is PropertyAccessorElement && element.name == _DEPRECATED_VARIABLE_NAME) {
- return true;
- }
- }
+ static FieldElement from(FieldElement baseField, InterfaceType definingType) {
+ if (baseField == null || definingType.typeArguments.length == 0) {
+ return baseField;
}
- return false;
+ DartType baseType = baseField.type;
+ if (baseType == null) {
+ return baseField;
+ }
+ List<DartType> argumentTypes = definingType.typeArguments;
+ List<DartType> parameterTypes = definingType.element.type.typeArguments;
+ DartType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
+ if (baseType == substitutedType) {
+ return baseField;
+ }
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
+ return new FieldMember(baseField, definingType);
}
+ /**
+ * Initialize a newly created element to represent a field of the given parameterized type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
+ */
+ FieldMember(FieldElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
+
@override
- bool get isOverride {
- if (element != null) {
- LibraryElement library = element.library;
- if (library != null && library.isDartCore) {
- if (element is PropertyAccessorElement && element.name == _OVERRIDE_VARIABLE_NAME) {
- return true;
- }
- }
- }
- return false;
- }
+ accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
@override
- bool get isProxy {
- if (element != null) {
- LibraryElement library = element.library;
- if (library != null && library.isDartCore) {
- if (element is PropertyAccessorElement && element.name == PROXY_VARIABLE_NAME) {
- return true;
- }
- }
- }
- return false;
- }
+ FieldElement get baseElement => super.baseElement as FieldElement;
@override
- String toString() => "@${element.toString()}";
+ ClassElement get enclosingElement => baseElement.enclosingElement;
+
+ @override
+ PropertyAccessorElement get getter => PropertyAccessorMember.from(baseElement.getter, definingType);
+
+ @override
+ PropertyAccessorElement get setter => PropertyAccessorMember.from(baseElement.setter, definingType);
+
+ @override
+ bool get isStatic => baseElement.isStatic;
+
+ @override
+ InterfaceType get definingType => super.definingType as InterfaceType;
}
/**
- * The abstract class `ElementImpl` implements the behavior common to objects that implement
- * an [Element].
+ * The interface `FunctionElement` defines the behavior of elements representing a function.
*/
-abstract class ElementImpl implements Element {
- /**
- * The enclosing element of this element, or `null` if this element is at the root of the
- * element structure.
- */
- ElementImpl _enclosingElement;
-
+abstract class FunctionElement implements ExecutableElement, LocalElement {
/**
- * The name of this element.
+ * The name of the synthetic function defined for libraries that are deferred.
*/
- String _name;
+ static final String LOAD_LIBRARY_NAME = "loadLibrary";
/**
- * The offset of the name of this element in the file that contains the declaration of this
- * element.
+ * Return the resolved [FunctionDeclaration] node that declares this [FunctionElement]
+ * .
+ *
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
+ *
+ * @return the resolved [FunctionDeclaration], not `null`.
*/
- int nameOffset = 0;
+ @override
+ FunctionDeclaration get node;
+}
+/**
+ * Instances of the class `FunctionElementImpl` implement a `FunctionElement`.
+ */
+class FunctionElementImpl extends ExecutableElementImpl implements FunctionElement {
/**
- * A bit-encoded form of the modifiers associated with this element.
+ * The offset to the beginning of the visible range for this element.
*/
- int _modifiers = 0;
+ int _visibleRangeOffset = 0;
/**
- * An array containing all of the metadata associated with this element.
+ * The length of the visible range for this element, or `-1` if this element does not have a
+ * visible range.
*/
- List<ElementAnnotation> metadata = ElementAnnotationImpl.EMPTY_ARRAY;
+ int _visibleRangeLength = -1;
/**
- * A cached copy of the calculated hashCode for this element.
+ * An empty array of function elements.
*/
- int _cachedHashCode = 0;
+ static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>(0);
/**
- * Initialize a newly created element to have the given name.
+ * Initialize a newly created function element to have the given name.
*
* @param name the name of this element
*/
- ElementImpl.forNode(Identifier name) : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
+ FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
/**
- * Initialize a newly created element to have the given name.
+ * Initialize a newly created function element to have no name and the given offset. This is used
+ * for function expressions, which have no name.
*
- * @param name the name of this element
* @param nameOffset the offset of the name of this element in the file that contains the
* declaration of this element
*/
- ElementImpl(String name, this.nameOffset) {
- this._name = StringUtilities.intern(name);
- }
-
- @override
- String computeDocumentationComment() {
- AnalysisContext context = this.context;
- if (context == null) {
- return null;
- }
- return context.computeDocumentationComment(this);
- }
-
- @override
- bool operator ==(Object object) {
- if (identical(this, object)) {
- return true;
- }
- if (object == null || hashCode != object.hashCode) {
- return false;
- }
- return object.runtimeType == runtimeType && (object as Element).location == location;
- }
-
- @override
- Element getAncestor(Predicate<Element> predicate) {
- Element ancestor = _enclosingElement;
- while (ancestor != null && !predicate(ancestor)) {
- ancestor = ancestor.enclosingElement;
- }
- return ancestor;
- }
+ FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset);
/**
- * Return the child of this element that is uniquely identified by the given identifier, or
- * `null` if there is no such child.
+ * Initialize a newly created function element to have the given name and offset.
*
- * @param identifier the identifier used to select a child
- * @return the child of this element with the given identifier
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- ElementImpl getChild(String identifier) => null;
-
- @override
- AnalysisContext get context {
- if (_enclosingElement == null) {
- return null;
- }
- return _enclosingElement.context;
- }
-
- @override
- String get displayName => _name;
-
- @override
- Element get enclosingElement => _enclosingElement;
-
- @override
- LibraryElement get library => getAncestor((element) => element is LibraryElement);
+ FunctionElementImpl(String name, int nameOffset) : super(name, nameOffset);
@override
- ElementLocation get location => new ElementLocationImpl.con1(this);
+ accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
@override
- String get name => _name;
+ ElementKind get kind => ElementKind.FUNCTION;
@override
- AstNode get node => getNodeMatching((node) => node is AstNode);
+ FunctionDeclaration get node => getNodeMatching((node) => node is FunctionDeclaration);
@override
- Source get source {
- if (_enclosingElement == null) {
+ SourceRange get visibleRange {
+ if (_visibleRangeLength < 0) {
return null;
}
- return _enclosingElement.source;
+ return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
}
@override
- CompilationUnit get unit => context.resolveCompilationUnit(source, library);
+ bool get isStatic => enclosingElement is CompilationUnitElement;
- @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 == 0) {
- int hashIdentifier = identifier.hashCode;
- Element enclosing = enclosingElement;
- if (enclosing != null) {
- _cachedHashCode = hashIdentifier + enclosing.hashCode;
- } else {
- _cachedHashCode = hashIdentifier;
- }
- }
- return _cachedHashCode;
+ /**
+ * Set the visible range for this element to the range starting at the given offset with the given
+ * length.
+ *
+ * @param offset the offset to the beginning of the visible range for this element
+ * @param length the length of the visible range for this element, or `-1` if this element
+ * does not have a visible range
+ */
+ void setVisibleRange(int offset, int length) {
+ _visibleRangeOffset = offset;
+ _visibleRangeLength = length;
}
@override
- bool isAccessibleIn(LibraryElement library) {
- if (Identifier.isPrivateName(_name)) {
- return library == this.library;
+ void appendTo(JavaStringBuilder builder) {
+ String name = displayName;
+ if (name != null) {
+ builder.append(name);
}
- return true;
+ super.appendTo(builder);
}
@override
- bool get isDeprecated {
- for (ElementAnnotation annotation in metadata) {
- if (annotation.isDeprecated) {
- return true;
- }
- }
- return false;
- }
+ String get identifier => "${name}@${nameOffset}";
+}
- @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 isPublic => !isPrivate;
-
- @override
- bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
+/**
+ * The interface `FunctionType` defines the behavior common to objects representing the type
+ * of a function, method, constructor, getter, or setter. Function types come in three variations:
+ * <ol>
+ * * The types of functions that only have required parameters. These have the general form
+ * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T</i>.
+ * * The types of functions with optional positional parameters. These have the general form
+ * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, [T<sub>n+1</sub>, &hellip;, T<sub>n+k</sub>]) &rarr;
+ * T</i>.
+ * * The types of functions with named parameters. These have the general form <i>(T<sub>1</sub>,
+ * &hellip;, T<sub>n</sub>, {T<sub>x1</sub> x1, &hellip;, T<sub>xk</sub> xk}) &rarr; T</i>.
+ * </ol>
+ */
+abstract class FunctionType implements ParameterizedType {
+ /**
+ * Return a map from the names of named parameters to the types of the named parameters of this
+ * type of function. The entries in the map will be iterated in the same order as the order in
+ * which the named parameters were defined. If there were no named parameters declared then the
+ * map will be empty.
+ *
+ * @return a map from the name to the types of the named parameters of this type of function
+ */
+ Map<String, DartType> get namedParameterTypes;
/**
- * Set whether this element is synthetic to correspond to the given value.
+ * Return an array containing the types of the normal parameters of this type of function. The
+ * parameter types are in the same order as they appear in the declaration of the function.
*
- * @param isSynthetic `true` if the element is synthetic
+ * @return the types of the normal parameters of this type of function
*/
- void set synthetic(bool isSynthetic) {
- setModifier(Modifier.SYNTHETIC, isSynthetic);
- }
+ List<DartType> get normalParameterTypes;
- @override
- String toString() {
- JavaStringBuilder builder = new JavaStringBuilder();
- appendTo(builder);
- return builder.toString();
- }
+ /**
+ * Return a map from the names of optional (positional) parameters to the types of the optional
+ * parameters of this type of function. The entries in the map will be iterated in the same order
+ * as the order in which the optional parameters were defined. If there were no optional
+ * parameters declared then the map will be empty.
+ *
+ * @return a map from the name to the types of the optional parameters of this type of function
+ */
+ List<DartType> get optionalParameterTypes;
- @override
- void visitChildren(ElementVisitor visitor) {
- }
+ /**
+ * Return an array containing the parameters elements of this type of function. The parameter
+ * types are in the same order as they appear in the declaration of the function.
+ *
+ * @return the parameters elements of this type of function
+ */
+ List<ParameterElement> get parameters;
/**
- * Append a textual representation of this type to the given builder.
+ * Return the type of object returned by this type of function.
*
- * @param builder the builder to which the text is to be appended
+ * @return the type of object returned by this type of function
*/
- void appendTo(JavaStringBuilder builder) {
- if (_name == null) {
- builder.append("<unnamed ");
- builder.append(runtimeType.toString());
- builder.append(">");
- } else {
- builder.append(_name);
- }
- }
+ DartType get returnType;
/**
- * Set this [Element] as an enclosing for given.
+ * Return `true` if this type is a subtype of the given type.
*
- * @param element the element to enclose, must be [ElementImpl]
+ * A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T</i> is a subtype of the
+ * function type <i>(S<sub>1</sub>, &hellip;, S<sub>n</sub>) &rarr; S</i>, if all of the following
+ * conditions are met:
+ * * Either
+ * * <i>S</i> is void, or
+ * * <i>T &hArr; S</i>.
+ *
+ * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> &hArr; S<sub>i</sub></i>.
+ * A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, [T<sub>n+1</sub>, &hellip;,
+ * T<sub>n+k</sub>]) &rarr; T</i> is a subtype of the function type <i>(S<sub>1</sub>, &hellip;,
+ * S<sub>n</sub>, [S<sub>n+1</sub>, &hellip;, S<sub>n+m</sub>]) &rarr; S</i>, if all of the
+ * following conditions are met:
+ * * Either
+ * * <i>S</i> is void, or
+ * * <i>T &hArr; S</i>.
+ *
+ * * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, <i>T<sub>i</sub>
+ * &hArr; S<sub>i</sub></i>.
+ * A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, {T<sub>x1</sub> x1, &hellip;,
+ * T<sub>xk</sub> xk}) &rarr; T</i> is a subtype of the function type <i>(S<sub>1</sub>, &hellip;,
+ * S<sub>n</sub>, {S<sub>y1</sub> y1, &hellip;, S<sub>ym</sub> ym}) &rarr; S</i>, if all of the
+ * following conditions are met:
+ * * Either
+ * * <i>S</i> is void,
+ * * or <i>T &hArr; S</i>.
+ *
+ * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> &hArr; S<sub>i</sub></i>.
+ * * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, &hellip;,
+ * x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>.
+ * * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, &hellip;, y<sub>m</sub>}</i>,
+ * <i>y<sub>i</sub> = x<sub>j</sub> => Tj &hArr; Si</i>.
+ * In addition, the following subtype rules apply:
+ *
+ * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, []) &rarr; T <: (T<sub>1</sub>, &hellip;,
+ * T<sub>n</sub>) &rarr; T.</i><br>
+ * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T <: (T<sub>1</sub>, &hellip;,
+ * T<sub>n</sub>, {}) &rarr; T.</i><br>
+ * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, {}) &rarr; T <: (T<sub>1</sub>, &hellip;,
+ * T<sub>n</sub>) &rarr; T.</i><br>
+ * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T <: (T<sub>1</sub>, &hellip;,
+ * T<sub>n</sub>, []) &rarr; T.</i>
+ *
+ * All functions implement the class `Function`. However not all function types are a
+ * subtype of `Function`. If an interface type <i>I</i> includes a method named
+ * `call()`, and the type of `call()` is the function type <i>F</i>, then <i>I</i> is
+ * considered to be a subtype of <i>F</i>.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is a subtype of the given type
*/
- void encloseElement(ElementImpl element) {
- element.enclosingElement = this;
- }
+ @override
+ bool isSubtypeOf(DartType type);
/**
- * Return an identifier that uniquely identifies this element among the children of this element's
- * parent.
+ * Return the type resulting from substituting the given arguments for this type's parameters.
+ * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`.
*
- * @return an identifier that uniquely identifies this element relative to its parent
+ * @param argumentTypes the actual type arguments being substituted for the type parameters
+ * @return the result of performing the substitution
*/
- String get identifier => name;
+ FunctionType substitute3(List<DartType> argumentTypes);
+
+ @override
+ FunctionType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
+}
+/**
+ * The interface `FunctionTypeAliasElement` defines the behavior of elements representing a
+ * function type alias (`typedef`).
+ */
+abstract class FunctionTypeAliasElement implements Element {
/**
- * Return the resolved [AstNode] of the given type enclosing [getNameOffset].
+ * Return the compilation unit in which this type alias is defined.
+ *
+ * @return the compilation unit in which this type alias is defined
*/
- AstNode getNodeMatching(Predicate<AstNode> predicate) {
- CompilationUnit unit = this.unit;
- if (unit == null) {
- return null;
- }
- int offset = nameOffset;
- AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
- if (node == null) {
- return null;
- }
- return node.getAncestor(predicate);
- }
+ @override
+ CompilationUnitElement get enclosingElement;
/**
- * Return `true` if this element has the given modifier associated with it.
+ * Return the resolved [FunctionTypeAlias] node that declares this
+ * [FunctionTypeAliasElement] .
*
- * @param modifier the modifier being tested for
- * @return `true` if this element has the given modifier associated with it
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
+ *
+ * @return the resolved [FunctionTypeAlias], not `null`.
*/
- bool hasModifier(Modifier modifier) => BooleanArray.getEnum(_modifiers, modifier);
+ @override
+ FunctionTypeAlias get node;
/**
- * If the given child is not `null`, use the given visitor to visit it.
+ * Return an array containing all of the parameters defined by this type alias.
*
- * @param child the child to be visited
- * @param visitor the visitor to be used to visit the child
+ * @return the parameters defined by this type alias
*/
- void safelyVisitChild(Element child, ElementVisitor visitor) {
- if (child != null) {
- child.accept(visitor);
- }
- }
+ List<ParameterElement> get parameters;
/**
- * Use the given visitor to visit all of the children in the given array.
+ * Return the return type defined by this type alias.
*
- * @param children the children to be visited
- * @param visitor the visitor being used to visit the children
+ * @return the return type defined by this type alias
*/
- void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
- if (children != null) {
- for (Element child in children) {
- child.accept(visitor);
- }
- }
- }
+ DartType get returnType;
/**
- * Set the enclosing element of this element to the given element.
+ * Return the type of function defined by this type alias.
*
- * @param element the enclosing element of this element
+ * @return the type of function defined by this type alias
*/
- void set enclosingElement(Element element) {
- _enclosingElement = element as ElementImpl;
- }
+ FunctionType get type;
/**
- * Set whether the given modifier is associated with this element to correspond to the given
- * value.
+ * Return an array containing all of the type parameters defined for this type.
*
- * @param modifier the modifier to be set
- * @param value `true` if the modifier is to be associated with this element
+ * @return the type parameters defined for this type
*/
- void setModifier(Modifier modifier, bool value) {
- _modifiers = BooleanArray.setEnum(_modifiers, modifier, value);
- }
+ List<TypeParameterElement> get typeParameters;
}
/**
- * Instances of the class `ElementLocationImpl` implement an [ElementLocation].
+ * Instances of the class `FunctionTypeAliasElementImpl` implement a
+ * `FunctionTypeAliasElement`.
*/
-class ElementLocationImpl implements ElementLocation {
+class FunctionTypeAliasElementImpl extends ElementImpl implements FunctionTypeAliasElement {
/**
- * The path to the element whose location is represented by this object.
+ * An array containing all of the parameters defined by this type alias.
*/
- List<String> _components;
+ List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
/**
- * The character used to separate components in the encoded form.
+ * The return type defined by this type alias.
*/
- static int _SEPARATOR_CHAR = 0x3B;
+ DartType returnType;
/**
- * Initialize a newly created location to represent the given element.
- *
- * @param element the element whose location is being represented
+ * The type of function defined by this type alias.
*/
- 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 = new List.from(components);
- }
+ FunctionType type;
/**
- * Initialize a newly created location from the given encoded form.
- *
- * @param encoding the encoded form of a location
+ * An array containing all of the type parameters defined for this type.
*/
- ElementLocationImpl.con2(String encoding) {
- this._components = _decode(encoding);
- }
+ List<TypeParameterElement> _typeParameters = TypeParameterElementImpl.EMPTY_ARRAY;
- @override
- bool operator ==(Object object) {
- if (identical(this, object)) {
- return true;
- }
- if (object is! ElementLocationImpl) {
- return false;
- }
- ElementLocationImpl location = object as ElementLocationImpl;
- List<String> otherComponents = location._components;
- int length = _components.length;
- if (otherComponents.length != length) {
- return false;
- }
- for (int i = length - 1; i >= 2; i--) {
- if (_components[i] != otherComponents[i]) {
- return false;
- }
- }
- if (length > 1 && !_equalSourceComponents(_components[1], otherComponents[1])) {
- return false;
- }
- if (length > 0 && !_equalSourceComponents(_components[0], otherComponents[0])) {
- return false;
- }
- return true;
- }
+ /**
+ * An empty array of type alias elements.
+ */
+ static List<FunctionTypeAliasElement> EMPTY_ARRAY = new List<FunctionTypeAliasElement>(0);
/**
- * Return the path to the element whose location is represented by this object.
+ * Initialize a newly created type alias element to have the given name.
*
- * @return the path to the element whose location is represented by this object
+ * @param name the name of this element
*/
- List<String> get components => _components;
+ FunctionTypeAliasElementImpl(Identifier name) : super.forNode(name);
@override
- String get encoding {
- JavaStringBuilder builder = new JavaStringBuilder();
- int length = _components.length;
- for (int i = 0; i < length; i++) {
- if (i > 0) {
- builder.appendChar(_SEPARATOR_CHAR);
- }
- _encode(builder, _components[i]);
- }
- return builder.toString();
- }
+ accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this);
@override
- int get hashCode {
- int result = 1;
- for (int i = 0; i < _components.length; i++) {
- String component = _components[i];
- int componentHash;
- if (i <= 1) {
- componentHash = _hashSourceComponent(component);
- } else {
- componentHash = component.hashCode;
+ ElementImpl getChild(String identifier) {
+ for (VariableElement parameter in _parameters) {
+ if ((parameter as VariableElementImpl).identifier == identifier) {
+ return parameter as VariableElementImpl;
}
- result = 31 * result + componentHash;
}
- return result;
+ for (TypeParameterElement typeParameter in _typeParameters) {
+ if ((typeParameter as TypeParameterElementImpl).identifier == identifier) {
+ return typeParameter as TypeParameterElementImpl;
+ }
+ }
+ return null;
}
@override
- String toString() => encoding;
+ CompilationUnitElement get enclosingElement => super.enclosingElement as CompilationUnitElement;
+
+ @override
+ ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
+
+ @override
+ FunctionTypeAlias get node => getNodeMatching((node) => node is FunctionTypeAlias);
+
+ @override
+ List<ParameterElement> get parameters => _parameters;
+
+ @override
+ List<TypeParameterElement> get typeParameters => _typeParameters;
/**
- * Decode the encoded form of a location into an array of components.
+ * Set the parameters defined by this type alias to the given parameters.
*
- * @param encoding the encoded form of a location
- * @return the components that were encoded
+ * @param parameters the parameters defined by this type alias
*/
- List<String> _decode(String encoding) {
- List<String> components = new List<String>();
- JavaStringBuilder builder = new JavaStringBuilder();
- 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) {
- builder.appendChar(_SEPARATOR_CHAR);
- index += 2;
- } else {
- components.add(builder.toString());
- builder.length = 0;
- index++;
- }
- } else {
- builder.appendChar(currentChar);
- index++;
+ void set parameters(List<ParameterElement> parameters) {
+ if (parameters != null) {
+ for (ParameterElement parameter in parameters) {
+ (parameter as ParameterElementImpl).enclosingElement = this;
}
}
- if (builder.length > 0) {
- components.add(builder.toString());
- }
- return new List.from(components);
+ this._parameters = parameters;
}
/**
- * Append an encoded form of the given component to the given builder.
+ * Set the type parameters defined for this type to the given parameters.
*
- * @param builder the builder to which the encoded component is to be appended
- * @param component the component to be appended to the builder
+ * @param typeParameters the type parameters defined for this type
*/
- void _encode(JavaStringBuilder builder, String component) {
- int length = component.length;
- for (int i = 0; i < length; i++) {
- int currentChar = component.codeUnitAt(i);
- if (currentChar == _SEPARATOR_CHAR) {
- builder.appendChar(_SEPARATOR_CHAR);
- }
- builder.appendChar(currentChar);
+ void set typeParameters(List<TypeParameterElement> typeParameters) {
+ for (TypeParameterElement typeParameter in typeParameters) {
+ (typeParameter as TypeParameterElementImpl).enclosingElement = this;
}
+ this._typeParameters = typeParameters;
}
/**
- * Return `true` if the given components, when interpreted to be encoded sources with a
- * leading source type indicator, are equal when the source type's are ignored.
+ * 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.
*
- * @param left the left component being compared
- * @param right the right component being compared
- * @return `true` if the given components are equal when the source type's are ignored
+ * @param parameters the parameters defined by this type alias
*/
- bool _equalSourceComponents(String left, String right) {
- // TODO(brianwilkerson) This method can go away when sources no longer have a URI kind.
- if (left == null) {
- return right == null;
- } else if (right == null) {
- return false;
- }
- int leftLength = left.length;
- int rightLength = right.length;
- if (leftLength != rightLength) {
- return false;
- } else if (leftLength <= 1 || rightLength <= 1) {
- return left == right;
- }
- return javaStringRegionMatches(left, 1, right, 1, leftLength - 1);
+ void shareParameters(List<ParameterElement> parameters) {
+ this._parameters = parameters;
}
/**
- * Return the hash code of the given encoded source component, ignoring the source type indicator.
+ * Set the type parameters defined for this type 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.
*
- * @param sourceComponent the component to compute a hash code
- * @return the hash code of the given encoded source component
+ * @param typeParameters the type parameters defined for this type
*/
- int _hashSourceComponent(String sourceComponent) {
- // TODO(brianwilkerson) This method can go away when sources no longer have a URI kind.
- if (sourceComponent.length <= 1) {
- return sourceComponent.hashCode;
+ void shareTypeParameters(List<TypeParameterElement> typeParameters) {
+ this._typeParameters = typeParameters;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(_parameters, visitor);
+ safelyVisitChildren(_typeParameters, visitor);
+ }
+
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ builder.append("typedef ");
+ builder.append(displayName);
+ int typeParameterCount = _typeParameters.length;
+ if (typeParameterCount > 0) {
+ builder.append("<");
+ for (int i = 0; i < typeParameterCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ (_typeParameters[i] as TypeParameterElementImpl).appendTo(builder);
+ }
+ builder.append(">");
+ }
+ builder.append("(");
+ int parameterCount = _parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ (_parameters[i] as ParameterElementImpl).appendTo(builder);
+ }
+ builder.append(")");
+ if (type != null) {
+ builder.append(Element.RIGHT_ARROW);
+ builder.append(type.returnType);
}
- return sourceComponent.substring(1).hashCode;
}
}
/**
- * The class `ElementPair` is a pair of [Element]s. [Object#equals] and
- * [Object#hashCode] so this class can be used in hashed data structures.
+ * Instances of the class `FunctionTypeImpl` defines the behavior common to objects
+ * representing the type of a function, method, constructor, getter, or setter.
*/
-class ElementPair {
+class FunctionTypeImpl extends TypeImpl implements FunctionType {
/**
- * The first [Element]
+ * Return `true` if all of the name/type pairs in the first map are equal to the
+ * corresponding name/type pairs in the second map. The maps are expected to iterate over their
+ * entries in the same order in which those entries were added to the map.
+ *
+ * @param firstTypes the first map of name/type pairs being compared
+ * @param secondTypes the second map of name/type pairs being compared
+ * @param visitedElementPairs a set of visited element pairs
+ * @return `true` if all of the name/type pairs in the first map are equal to the
+ * corresponding name/type pairs in the second map
*/
- final Element _first;
+ static bool _equals(Map<String, DartType> firstTypes, Map<String, DartType> secondTypes, Set<ElementPair> visitedElementPairs) {
+ if (secondTypes.length != firstTypes.length) {
+ return false;
+ }
+ JavaIterator<MapEntry<String, DartType>> firstIterator = new JavaIterator(getMapEntrySet(firstTypes));
+ JavaIterator<MapEntry<String, DartType>> secondIterator = new JavaIterator(getMapEntrySet(secondTypes));
+ while (firstIterator.hasNext) {
+ MapEntry<String, DartType> firstEntry = firstIterator.next();
+ MapEntry<String, DartType> secondEntry = secondIterator.next();
+ if (firstEntry.getKey() != secondEntry.getKey() || !(firstEntry.getValue() as TypeImpl).internalEquals(secondEntry.getValue(), visitedElementPairs)) {
+ return false;
+ }
+ }
+ return true;
+ }
/**
- * The second [Element]
- */
- final Element _second;
-
- /**
- * The sole constructor for this class, taking two [Element]s.
- *
- * @param first the first element
- * @param second the second element
- */
- ElementPair(this._first, this._second);
-
- @override
- bool operator ==(Object object) {
- if (identical(object, this)) {
- return true;
- }
- if (object is ElementPair) {
- ElementPair elementPair = object;
- return (_first == elementPair._first) && (_second == elementPair._second);
- }
- return false;
- }
-
- /**
- * Return the first element.
- *
- * @return the first element
+ * An array containing the actual types of the type arguments.
*/
- Element get firstElt => _first;
+ List<DartType> typeArguments = TypeImpl.EMPTY_ARRAY;
/**
- * Return the second element
+ * Initialize a newly created function type to be declared by the given element and to have the
+ * given name.
*
- * @return the second element
- */
- Element get secondElt => _second;
-
- @override
- int get hashCode => ObjectUtilities.combineHashCodes(_first.hashCode, _second.hashCode);
-}
-
-/**
- * Instances of the class `EmbeddedHtmlScriptElementImpl` implement an
- * [EmbeddedHtmlScriptElement].
- */
-class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl implements EmbeddedHtmlScriptElement {
- /**
- * The library defined by the script tag's content.
+ * @param element the element representing the declaration of the function type
*/
- LibraryElement _scriptLibrary;
+ FunctionTypeImpl.con1(ExecutableElement element) : super(element, element == null ? null : element.name);
/**
- * Initialize a newly created script element to have the specified tag name and offset.
+ * Initialize a newly created function type to be declared by the given element and to have the
+ * given name.
*
- * @param node the XML node from which this element is derived (not `null`)
+ * @param element the element representing the declaration of the function type
*/
- EmbeddedHtmlScriptElementImpl(XmlTagNode node) : super(node);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitEmbeddedHtmlScriptElement(this);
+ FunctionTypeImpl.con2(FunctionTypeAliasElement element) : super(element, element == null ? null : element.name);
@override
- ElementKind get kind => ElementKind.EMBEDDED_HTML_SCRIPT;
+ bool operator ==(Object object) => internalEquals(object, new Set<ElementPair>());
@override
- LibraryElement get scriptLibrary => _scriptLibrary;
-
- /**
- * Set the script library defined by the script tag's content.
- *
- * @param scriptLibrary the library or `null` if none
- */
- void set scriptLibrary(LibraryElementImpl scriptLibrary) {
- scriptLibrary.enclosingElement = this;
- this._scriptLibrary = scriptLibrary;
+ String get displayName {
+ String name = this.name;
+ if (name == null || name.length == 0) {
+ // TODO(brianwilkerson) Determine whether function types should ever have an empty name.
+ List<DartType> normalParameterTypes = this.normalParameterTypes;
+ List<DartType> optionalParameterTypes = this.optionalParameterTypes;
+ Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
+ DartType returnType = this.returnType;
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append("(");
+ bool needsComma = false;
+ if (normalParameterTypes.length > 0) {
+ for (DartType type in normalParameterTypes) {
+ if (needsComma) {
+ builder.append(", ");
+ } else {
+ needsComma = true;
+ }
+ builder.append(type.displayName);
+ }
+ }
+ if (optionalParameterTypes.length > 0) {
+ if (needsComma) {
+ builder.append(", ");
+ needsComma = false;
+ }
+ builder.append("[");
+ for (DartType type in optionalParameterTypes) {
+ if (needsComma) {
+ builder.append(", ");
+ } else {
+ needsComma = true;
+ }
+ builder.append(type.displayName);
+ }
+ builder.append("]");
+ needsComma = true;
+ }
+ if (namedParameterTypes.length > 0) {
+ if (needsComma) {
+ builder.append(", ");
+ needsComma = false;
+ }
+ builder.append("{");
+ for (MapEntry<String, DartType> entry in getMapEntrySet(namedParameterTypes)) {
+ if (needsComma) {
+ builder.append(", ");
+ } else {
+ needsComma = true;
+ }
+ builder.append(entry.getKey());
+ builder.append(": ");
+ builder.append(entry.getValue().displayName);
+ }
+ builder.append("}");
+ needsComma = true;
+ }
+ builder.append(")");
+ builder.append(Element.RIGHT_ARROW);
+ if (returnType == null) {
+ builder.append("null");
+ } else {
+ builder.append(returnType.displayName);
+ }
+ name = builder.toString();
+ }
+ return name;
}
@override
- void visitChildren(ElementVisitor visitor) {
- safelyVisitChild(_scriptLibrary, visitor);
+ Map<String, DartType> get namedParameterTypes {
+ LinkedHashMap<String, DartType> namedParameterTypes = new LinkedHashMap<String, DartType>();
+ List<ParameterElement> parameters = baseParameters;
+ if (parameters.length == 0) {
+ return namedParameterTypes;
+ }
+ List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typeParameters);
+ for (ParameterElement parameter in parameters) {
+ if (parameter.parameterKind == ParameterKind.NAMED) {
+ namedParameterTypes[parameter.name] = parameter.type.substitute2(typeArguments, typeParameters);
+ }
+ }
+ return namedParameterTypes;
}
-}
-
-/**
- * The abstract class `ExecutableElementImpl` implements the behavior common to
- * `ExecutableElement`s.
- */
-abstract class ExecutableElementImpl extends ElementImpl implements ExecutableElement {
- /**
- * An array containing all of the functions defined within this executable element.
- */
- List<FunctionElement> _functions = FunctionElementImpl.EMPTY_ARRAY;
-
- /**
- * An array containing all of the labels defined within this executable element.
- */
- List<LabelElement> _labels = LabelElementImpl.EMPTY_ARRAY;
-
- /**
- * An array containing all of the local variables defined within this executable element.
- */
- List<LocalVariableElement> _localVariables = LocalVariableElementImpl.EMPTY_ARRAY;
-
- /**
- * An array containing all of the parameters defined by this executable element.
- */
- List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
-
- /**
- * The return type defined by this executable element.
- */
- DartType returnType;
-
- /**
- * The type of function defined by this executable element.
- */
- FunctionType type;
-
- /**
- * An empty array of executable elements.
- */
- static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>(0);
-
- /**
- * Initialize a newly created executable element to have the given name.
- *
- * @param name the name of this element
- */
- ExecutableElementImpl.forNode(Identifier name) : super.forNode(name);
-
- /**
- * Initialize a newly created executable element to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
- */
- ExecutableElementImpl(String name, int nameOffset) : super(name, nameOffset);
@override
- ElementImpl getChild(String identifier) {
- for (ExecutableElement function in _functions) {
- if ((function as ExecutableElementImpl).identifier == identifier) {
- return function as ExecutableElementImpl;
- }
+ List<DartType> get normalParameterTypes {
+ List<ParameterElement> parameters = baseParameters;
+ if (parameters.length == 0) {
+ return TypeImpl.EMPTY_ARRAY;
}
- for (LabelElement label in _labels) {
- if ((label as LabelElementImpl).identifier == identifier) {
- return label as LabelElementImpl;
+ List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typeParameters);
+ List<DartType> types = new List<DartType>();
+ for (ParameterElement parameter in parameters) {
+ if (parameter.parameterKind == ParameterKind.REQUIRED) {
+ types.add(parameter.type.substitute2(typeArguments, typeParameters));
}
}
- for (VariableElement variable in _localVariables) {
- if ((variable as VariableElementImpl).identifier == identifier) {
- return variable as VariableElementImpl;
- }
+ return new List.from(types);
+ }
+
+ @override
+ List<DartType> get optionalParameterTypes {
+ List<ParameterElement> parameters = baseParameters;
+ if (parameters.length == 0) {
+ return TypeImpl.EMPTY_ARRAY;
}
- for (ParameterElement parameter in _parameters) {
- if ((parameter as ParameterElementImpl).identifier == identifier) {
- return parameter as ParameterElementImpl;
+ List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typeParameters);
+ List<DartType> types = new List<DartType>();
+ for (ParameterElement parameter in parameters) {
+ if (parameter.parameterKind == ParameterKind.POSITIONAL) {
+ types.add(parameter.type.substitute2(typeArguments, typeParameters));
}
}
- return null;
+ return new List.from(types);
}
@override
- List<FunctionElement> get functions => _functions;
-
- @override
- List<LabelElement> get labels => _labels;
-
- @override
- List<LocalVariableElement> get localVariables => _localVariables;
-
- @override
- List<ParameterElement> get parameters => _parameters;
-
- @override
- bool get isOperator => false;
-
- /**
- * Set the functions defined within this executable element to the given functions.
- *
- * @param functions the functions defined within this executable element
- */
- void set functions(List<FunctionElement> functions) {
- for (FunctionElement function in functions) {
- (function as FunctionElementImpl).enclosingElement = this;
+ List<ParameterElement> get parameters {
+ List<ParameterElement> baseParameters = this.baseParameters;
+ // no parameters, quick return
+ int parameterCount = baseParameters.length;
+ if (parameterCount == 0) {
+ return baseParameters;
}
- this._functions = functions;
- }
-
- /**
- * Set the labels defined within this executable element to the given labels.
- *
- * @param labels the labels defined within this executable element
- */
- void set labels(List<LabelElement> labels) {
- for (LabelElement label in labels) {
- (label as LabelElementImpl).enclosingElement = this;
+ // create specialized parameters
+ List<ParameterElement> specializedParameters = new List<ParameterElement>(parameterCount);
+ for (int i = 0; i < parameterCount; i++) {
+ specializedParameters[i] = ParameterMember.from(baseParameters[i], this);
}
- this._labels = labels;
+ return specializedParameters;
}
- /**
- * Set the local variables defined within this executable element to the given variables.
- *
- * @param localVariables the local variables defined within this executable element
- */
- void set localVariables(List<LocalVariableElement> localVariables) {
- for (LocalVariableElement variable in localVariables) {
- (variable as LocalVariableElementImpl).enclosingElement = this;
+ @override
+ DartType get returnType {
+ DartType baseReturnType = this.baseReturnType;
+ if (baseReturnType == null) {
+ // TODO(brianwilkerson) This is a patch. The return type should never be null and we need to
+ // understand why it is and fix it.
+ return DynamicTypeImpl.instance;
}
- this._localVariables = localVariables;
+ return baseReturnType.substitute2(typeArguments, TypeParameterTypeImpl.getTypes(typeParameters));
}
- /**
- * Set the parameters defined by this executable element to the given parameters.
- *
- * @param parameters the parameters defined by this executable element
- */
- void set parameters(List<ParameterElement> parameters) {
- for (ParameterElement parameter in parameters) {
- (parameter as ParameterElementImpl).enclosingElement = this;
+ @override
+ List<TypeParameterElement> get typeParameters {
+ Element element = this.element;
+ if (element is FunctionTypeAliasElement) {
+ return element.typeParameters;
}
- this._parameters = parameters;
+ ClassElement definingClass = element.getAncestor((element) => element is ClassElement);
+ if (definingClass != null) {
+ return definingClass.typeParameters;
+ }
+ return TypeParameterElementImpl.EMPTY_ARRAY;
}
@override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChildren(_functions, visitor);
- safelyVisitChildren(_labels, visitor);
- safelyVisitChildren(_localVariables, visitor);
- safelyVisitChildren(_parameters, visitor);
+ int get hashCode {
+ if (element == null) {
+ return 0;
+ }
+ // Reference the arrays of parameters
+ List<DartType> normalParameterTypes = this.normalParameterTypes;
+ List<DartType> optionalParameterTypes = this.optionalParameterTypes;
+ Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values;
+ // Generate the hashCode
+ int hashCode = returnType.hashCode;
+ for (int i = 0; i < normalParameterTypes.length; i++) {
+ hashCode = (hashCode << 1) + normalParameterTypes[i].hashCode;
+ }
+ for (int i = 0; i < optionalParameterTypes.length; i++) {
+ hashCode = (hashCode << 1) + optionalParameterTypes[i].hashCode;
+ }
+ for (DartType type in namedParameterTypes) {
+ hashCode = (hashCode << 1) + type.hashCode;
+ }
+ return hashCode;
}
@override
- void appendTo(JavaStringBuilder builder) {
- if (this.kind != ElementKind.GETTER) {
- builder.append("(");
- String closing = null;
- ParameterKind kind = ParameterKind.REQUIRED;
- int parameterCount = _parameters.length;
- for (int i = 0; i < parameterCount; i++) {
- if (i > 0) {
- builder.append(", ");
+ bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // trivial base cases
+ if (type == null) {
+ return false;
+ } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
+ return true;
+ } else if (type is! FunctionType) {
+ return false;
+ } else if (this == type) {
+ return true;
+ }
+ FunctionType t = this;
+ FunctionType s = type as FunctionType;
+ List<DartType> tTypes = t.normalParameterTypes;
+ List<DartType> tOpTypes = t.optionalParameterTypes;
+ List<DartType> sTypes = s.normalParameterTypes;
+ List<DartType> sOpTypes = s.optionalParameterTypes;
+ // If one function has positional and the other has named parameters, return false.
+ if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
+ return false;
+ }
+ // named parameters case
+ if (t.namedParameterTypes.length > 0) {
+ // check that the number of required parameters are equal, and check that every t_i is
+ // more specific than every s_i
+ if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
+ return false;
+ } else if (t.normalParameterTypes.length > 0) {
+ for (int i = 0; i < tTypes.length; i++) {
+ if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(sTypes[i], withDynamic, visitedTypePairs)) {
+ return false;
+ }
}
- ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl;
- ParameterKind parameterKind = parameter.parameterKind;
- if (parameterKind != kind) {
- if (closing != null) {
- builder.append(closing);
+ }
+ Map<String, DartType> namedTypesT = t.namedParameterTypes;
+ Map<String, DartType> namedTypesS = s.namedParameterTypes;
+ // if k >= m is false, return false: the passed function type has more named parameter types than this
+ if (namedTypesT.length < namedTypesS.length) {
+ return false;
+ }
+ // Loop through each element in S verifying that T has a matching parameter name and that the
+ // corresponding type is more specific then the type in S.
+ JavaIterator<MapEntry<String, DartType>> iteratorS = new JavaIterator(getMapEntrySet(namedTypesS));
+ while (iteratorS.hasNext) {
+ MapEntry<String, DartType> entryS = iteratorS.next();
+ DartType typeT = namedTypesT[entryS.getKey()];
+ if (typeT == null) {
+ return false;
+ }
+ if (!(typeT as TypeImpl).isMoreSpecificThan2(entryS.getValue(), withDynamic, visitedTypePairs)) {
+ return false;
+ }
+ }
+ } else if (s.namedParameterTypes.length > 0) {
+ return false;
+ } else {
+ // positional parameter case
+ int tArgLength = tTypes.length + tOpTypes.length;
+ int sArgLength = sTypes.length + sOpTypes.length;
+ // Check that the total number of parameters in t is greater than or equal to the number of
+ // parameters in s and that the number of required parameters in s is greater than or equal to
+ // the number of required parameters in t.
+ if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
+ return false;
+ }
+ if (tOpTypes.length == 0 && sOpTypes.length == 0) {
+ // No positional arguments, don't copy contents to new array
+ for (int i = 0; i < sTypes.length; i++) {
+ if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(sTypes[i], withDynamic, visitedTypePairs)) {
+ return false;
}
- if (parameterKind == ParameterKind.POSITIONAL) {
- builder.append("[");
- closing = "]";
- } else if (parameterKind == ParameterKind.NAMED) {
- builder.append("{");
- closing = "}";
- } else {
- closing = null;
+ }
+ } else {
+ // Else, we do have positional parameters, copy required and positional parameter types into
+ // arrays to do the compare (for loop below).
+ List<DartType> tAllTypes = new List<DartType>(sArgLength);
+ for (int i = 0; i < tTypes.length; i++) {
+ tAllTypes[i] = tTypes[i];
+ }
+ for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
+ tAllTypes[i] = tOpTypes[j];
+ }
+ List<DartType> sAllTypes = new List<DartType>(sArgLength);
+ for (int i = 0; i < sTypes.length; i++) {
+ sAllTypes[i] = sTypes[i];
+ }
+ for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
+ sAllTypes[i] = sOpTypes[j];
+ }
+ for (int i = 0; i < sAllTypes.length; i++) {
+ if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan2(sAllTypes[i], withDynamic, visitedTypePairs)) {
+ return false;
}
}
- kind = parameterKind;
- parameter.appendToWithoutDelimiters(builder);
- }
- if (closing != null) {
- builder.append(closing);
}
- builder.append(")");
- }
- if (type != null) {
- builder.append(Element.RIGHT_ARROW);
- builder.append(type.returnType);
}
+ DartType tRetType = t.returnType;
+ DartType sRetType = s.returnType;
+ return sRetType.isVoid || (tRetType as TypeImpl).isMoreSpecificThan2(sRetType, withDynamic, visitedTypePairs);
}
-}
-
-/**
- * Instances of the class `ExportElementImpl` implement an [ExportElement].
- */
-class ExportElementImpl extends UriReferencedElementImpl implements ExportElement {
- /**
- * 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 = NamespaceCombinator.EMPTY_ARRAY;
-
- /**
- * Initialize a newly created export element.
- */
- ExportElementImpl() : super(null, -1);
@override
- accept(ElementVisitor visitor) => visitor.visitExportElement(this);
+ bool isAssignableTo(DartType type) => isSubtypeOf2(type, new Set<TypeImpl_TypePair>());
@override
- ElementKind get kind => ElementKind.EXPORT;
+ FunctionTypeImpl substitute3(List<DartType> argumentTypes) => substitute2(argumentTypes, typeArguments);
@override
- void appendTo(JavaStringBuilder builder) {
- builder.append("export ");
- (exportedLibrary as LibraryElementImpl).appendTo(builder);
+ FunctionTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
+ if (argumentTypes.length != parameterTypes.length) {
+ throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
+ }
+ if (argumentTypes.length == 0) {
+ return this;
+ }
+ Element element = this.element;
+ FunctionTypeImpl newType = (element is ExecutableElement) ? new FunctionTypeImpl.con1(element) : new FunctionTypeImpl.con2(element as FunctionTypeAliasElement);
+ newType.typeArguments = TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
+ return newType;
}
@override
- String get identifier => exportedLibrary.name;
-}
+ void appendTo(JavaStringBuilder builder) {
+ List<DartType> normalParameterTypes = this.normalParameterTypes;
+ List<DartType> optionalParameterTypes = this.optionalParameterTypes;
+ Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
+ DartType returnType = this.returnType;
+ builder.append("(");
+ bool needsComma = false;
+ if (normalParameterTypes.length > 0) {
+ for (DartType type in normalParameterTypes) {
+ if (needsComma) {
+ builder.append(", ");
+ } else {
+ needsComma = true;
+ }
+ (type as TypeImpl).appendTo(builder);
+ }
+ }
+ if (optionalParameterTypes.length > 0) {
+ if (needsComma) {
+ builder.append(", ");
+ needsComma = false;
+ }
+ builder.append("[");
+ for (DartType type in optionalParameterTypes) {
+ if (needsComma) {
+ builder.append(", ");
+ } else {
+ needsComma = true;
+ }
+ (type as TypeImpl).appendTo(builder);
+ }
+ builder.append("]");
+ needsComma = true;
+ }
+ if (namedParameterTypes.length > 0) {
+ if (needsComma) {
+ builder.append(", ");
+ needsComma = false;
+ }
+ builder.append("{");
+ for (MapEntry<String, DartType> entry in getMapEntrySet(namedParameterTypes)) {
+ if (needsComma) {
+ builder.append(", ");
+ } else {
+ needsComma = true;
+ }
+ builder.append(entry.getKey());
+ builder.append(": ");
+ (entry.getValue() as TypeImpl).appendTo(builder);
+ }
+ builder.append("}");
+ needsComma = true;
+ }
+ builder.append(")");
+ builder.append(Element.RIGHT_ARROW);
+ if (returnType == null) {
+ builder.append("null");
+ } else {
+ (returnType as TypeImpl).appendTo(builder);
+ }
+ }
-/**
- * Instances of the class `ExternalHtmlScriptElementImpl` implement an
- * [ExternalHtmlScriptElement].
- */
-class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl implements ExternalHtmlScriptElement {
/**
- * The source specified in the `source` attribute or `null` if unspecified.
+ * @return the base parameter elements of this function element, not `null`.
*/
- Source scriptSource;
+ List<ParameterElement> get baseParameters {
+ Element element = this.element;
+ if (element is ExecutableElement) {
+ return element.parameters;
+ } else {
+ return (element as FunctionTypeAliasElement).parameters;
+ }
+ }
+
+ @override
+ bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) {
+ if (object is! FunctionTypeImpl) {
+ return false;
+ }
+ FunctionTypeImpl otherType = object as FunctionTypeImpl;
+ // If the visitedTypePairs already has the pair (this, type), use the elements to determine equality
+ ElementPair elementPair = new ElementPair(element, otherType.element);
+ if (!visitedElementPairs.add(elementPair)) {
+ return elementPair.firstElt == elementPair.secondElt;
+ }
+ // Compute the result
+ bool result = TypeImpl.equalArrays(normalParameterTypes, otherType.normalParameterTypes, visitedElementPairs) && TypeImpl.equalArrays(optionalParameterTypes, otherType.optionalParameterTypes, visitedElementPairs) && _equals(namedParameterTypes, otherType.namedParameterTypes, visitedElementPairs) && (returnType as TypeImpl).internalEquals(otherType.returnType, visitedElementPairs);
+ // Remove the pair from our visited pairs list
+ visitedElementPairs.remove(elementPair);
+ // Return the result
+ return result;
+ }
+
+ @override
+ bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // trivial base cases
+ if (type == null) {
+ return false;
+ } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
+ return true;
+ } else if (type is! FunctionType) {
+ return false;
+ } else if (this == type) {
+ return true;
+ }
+ FunctionType t = this;
+ FunctionType s = type as FunctionType;
+ List<DartType> tTypes = t.normalParameterTypes;
+ List<DartType> tOpTypes = t.optionalParameterTypes;
+ List<DartType> sTypes = s.normalParameterTypes;
+ List<DartType> sOpTypes = s.optionalParameterTypes;
+ // If one function has positional and the other has named parameters, return false.
+ if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
+ return false;
+ }
+ // named parameters case
+ if (t.namedParameterTypes.length > 0) {
+ // check that the number of required parameters are equal, and check that every t_i is
+ // assignable to every s_i
+ if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
+ return false;
+ } else if (t.normalParameterTypes.length > 0) {
+ for (int i = 0; i < tTypes.length; i++) {
+ if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePairs)) {
+ return false;
+ }
+ }
+ }
+ Map<String, DartType> namedTypesT = t.namedParameterTypes;
+ Map<String, DartType> namedTypesS = s.namedParameterTypes;
+ // if k >= m is false, return false: the passed function type has more named parameter types than this
+ if (namedTypesT.length < namedTypesS.length) {
+ return false;
+ }
+ // Loop through each element in S verifying that T has a matching parameter name and that the
+ // corresponding type is assignable to the type in S.
+ JavaIterator<MapEntry<String, DartType>> iteratorS = new JavaIterator(getMapEntrySet(namedTypesS));
+ while (iteratorS.hasNext) {
+ MapEntry<String, DartType> entryS = iteratorS.next();
+ DartType typeT = namedTypesT[entryS.getKey()];
+ if (typeT == null) {
+ return false;
+ }
+ if (!(typeT as TypeImpl).isAssignableTo2(entryS.getValue(), visitedTypePairs)) {
+ return false;
+ }
+ }
+ } else if (s.namedParameterTypes.length > 0) {
+ return false;
+ } else {
+ // positional parameter case
+ int tArgLength = tTypes.length + tOpTypes.length;
+ int sArgLength = sTypes.length + sOpTypes.length;
+ // Check that the total number of parameters in t is greater than or equal to the number of
+ // parameters in s and that the number of required parameters in s is greater than or equal to
+ // the number of required parameters in t.
+ if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
+ return false;
+ }
+ if (tOpTypes.length == 0 && sOpTypes.length == 0) {
+ // No positional arguments, don't copy contents to new array
+ for (int i = 0; i < sTypes.length; i++) {
+ if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePairs)) {
+ return false;
+ }
+ }
+ } else {
+ // Else, we do have positional parameters, copy required and positional parameter types into
+ // arrays to do the compare (for loop below).
+ List<DartType> tAllTypes = new List<DartType>(sArgLength);
+ for (int i = 0; i < tTypes.length; i++) {
+ tAllTypes[i] = tTypes[i];
+ }
+ for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
+ tAllTypes[i] = tOpTypes[j];
+ }
+ List<DartType> sAllTypes = new List<DartType>(sArgLength);
+ for (int i = 0; i < sTypes.length; i++) {
+ sAllTypes[i] = sTypes[i];
+ }
+ for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
+ sAllTypes[i] = sOpTypes[j];
+ }
+ for (int i = 0; i < sAllTypes.length; i++) {
+ if (!(tAllTypes[i] as TypeImpl).isAssignableTo2(sAllTypes[i], visitedTypePairs)) {
+ return false;
+ }
+ }
+ }
+ }
+ DartType tRetType = t.returnType;
+ DartType sRetType = s.returnType;
+ return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo2(sRetType, visitedTypePairs);
+ }
/**
- * Initialize a newly created script element to have the specified tag name and offset.
+ * Return the return type defined by this function's element.
*
- * @param node the XML node from which this element is derived (not `null`)
+ * @return the return type defined by this function's element
*/
- ExternalHtmlScriptElementImpl(XmlTagNode node) : super(node);
+ DartType get baseReturnType {
+ Element element = this.element;
+ if (element is ExecutableElement) {
+ return element.returnType;
+ } else {
+ return (element as FunctionTypeAliasElement).returnType;
+ }
+ }
+}
+
+/**
+ * Instances of the class `GeneralizingElementVisitor` implement an element visitor that will
+ * recursively visit all of the elements in an element model (like instances of the class
+ * [RecursiveElementVisitor]). In addition, when an element of a specific type is visited not
+ * only will the visit method for that specific type of element be invoked, but additional methods
+ * for the supertypes of that element will also be invoked. For example, using an instance of this
+ * class to visit a [MethodElement] will cause the method
+ * [visitMethodElement] to be invoked but will also cause the methods
+ * [visitExecutableElement] and [visitElement] to be
+ * subsequently invoked. This allows visitors to be written that visit all executable elements
+ * without needing to override the visit method for each of the specific subclasses of
+ * [ExecutableElement].
+ *
+ * Note, however, that unlike many visitors, element visitors visit objects based on the interfaces
+ * implemented by those elements. Because interfaces form a graph structure rather than a tree
+ * structure the way classes do, and because it is generally undesirable for an object to be visited
+ * more than once, this class flattens the interface graph into a pseudo-tree. In particular, this
+ * class treats elements as if the element types were structured in the following way:
+ *
+ *
+ * <pre>
+ * Element
+ * ClassElement
+ * CompilationUnitElement
+ * ExecutableElement
+ * ConstructorElement
+ * LocalElement
+ * FunctionElement
+ * MethodElement
+ * PropertyAccessorElement
+ * ExportElement
+ * HtmlElement
+ * ImportElement
+ * LabelElement
+ * LibraryElement
+ * MultiplyDefinedElement
+ * PrefixElement
+ * TypeAliasElement
+ * TypeParameterElement
+ * UndefinedElement
+ * VariableElement
+ * PropertyInducingElement
+ * FieldElement
+ * TopLevelVariableElement
+ * LocalElement
+ * LocalVariableElement
+ * ParameterElement
+ * FieldFormalParameterElement
+ * </pre>
+ *
+ * Subclasses that override a visit method must either invoke the overridden visit method or
+ * explicitly invoke the more general visit method. Failure to do so will cause the visit methods
+ * for superclasses of the element to not be invoked and will cause the children of the visited node
+ * to not be visited.
+ */
+class GeneralizingElementVisitor<R> implements ElementVisitor<R> {
+ @override
+ R visitAngularComponentElement(AngularComponentElement element) => visitAngularHasSelectorElement(element);
@override
- accept(ElementVisitor visitor) => visitor.visitExternalHtmlScriptElement(this);
+ R visitAngularControllerElement(AngularControllerElement element) => visitAngularHasSelectorElement(element);
@override
- ElementKind get kind => ElementKind.EXTERNAL_HTML_SCRIPT;
-}
+ R visitAngularDirectiveElement(AngularDecoratorElement element) => visitAngularHasSelectorElement(element);
-/**
- * Instances of the class `FieldElementImpl` implement a `FieldElement`.
- */
-class FieldElementImpl extends PropertyInducingElementImpl implements FieldElement {
- /**
- * An empty array of field elements.
- */
- static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>(0);
+ R visitAngularElement(AngularElement element) => visitToolkitObjectElement(element);
- /**
- * Initialize a newly created field element to have the given name.
- *
- * @param name the name of this element
- */
- FieldElementImpl.con1(Identifier name) : super.con1(name);
+ @override
+ R visitAngularFormatterElement(AngularFormatterElement element) => visitAngularElement(element);
- /**
- * Initialize a newly created synthetic field element to have the given name.
- *
- * @param name the name of this element
- */
- FieldElementImpl.con2(String name) : super.con2(name);
+ R visitAngularHasSelectorElement(AngularHasSelectorElement element) => visitAngularElement(element);
@override
- accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
+ R visitAngularPropertyElement(AngularPropertyElement element) => visitAngularElement(element);
@override
- ClassElement get enclosingElement => super.enclosingElement as ClassElement;
+ R visitAngularScopePropertyElement(AngularScopePropertyElement element) => visitAngularElement(element);
@override
- ElementKind get kind => ElementKind.FIELD;
+ R visitAngularSelectorElement(AngularSelectorElement element) => visitAngularElement(element);
@override
- bool get isStatic => hasModifier(Modifier.STATIC);
-
- /**
- * Set whether this field is static to correspond to the given value.
- *
- * @param isStatic `true` if the field is static
- */
- void set static(bool isStatic) {
- setModifier(Modifier.STATIC, isStatic);
- }
-}
-
-/**
- * Instances of the class `FieldFormalParameterElementImpl` extend
- * [ParameterElementImpl] to provide 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.
- *
- * @param name the name of this element
- */
- FieldFormalParameterElementImpl(Identifier name) : super.con1(name);
+ R visitAngularViewElement(AngularViewElement element) => visitAngularElement(element);
@override
- accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(this);
+ R visitClassElement(ClassElement element) => visitElement(element);
@override
- bool get isInitializingFormal => true;
-}
+ R visitCompilationUnitElement(CompilationUnitElement element) => visitElement(element);
-/**
- * Instances of the class `FunctionElementImpl` implement a `FunctionElement`.
- */
-class FunctionElementImpl extends ExecutableElementImpl implements FunctionElement {
- /**
- * The offset to the beginning of the visible range for this element.
- */
- int _visibleRangeOffset = 0;
+ @override
+ R visitConstructorElement(ConstructorElement element) => visitExecutableElement(element);
- /**
- * The length of the visible range for this element, or `-1` if this element does not have a
- * visible range.
- */
- int _visibleRangeLength = -1;
+ R visitElement(Element element) {
+ element.visitChildren(this);
+ return null;
+ }
- /**
- * An empty array of function elements.
- */
- static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>(0);
+ @override
+ R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => visitHtmlScriptElement(element);
- /**
- * Initialize a newly created function element to have the given name.
- *
- * @param name the name of this element
- */
- FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
+ R visitExecutableElement(ExecutableElement element) => visitElement(element);
- /**
- * Initialize a newly created function element to have no name and the given offset. This is used
- * for function expressions, which have no name.
- *
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
- */
- FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset);
+ @override
+ R visitExportElement(ExportElement element) => visitElement(element);
- /**
- * Initialize a newly created function element to have the given name and offset.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
- */
- FunctionElementImpl(String name, int nameOffset) : super(name, nameOffset);
+ @override
+ R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => visitHtmlScriptElement(element);
@override
- accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
+ R visitFieldElement(FieldElement element) => visitPropertyInducingElement(element);
@override
- ElementKind get kind => ElementKind.FUNCTION;
+ R visitFieldFormalParameterElement(FieldFormalParameterElement element) => visitParameterElement(element);
@override
- FunctionDeclaration get node => getNodeMatching((node) => node is FunctionDeclaration);
+ R visitFunctionElement(FunctionElement element) => visitLocalElement(element);
@override
- SourceRange get visibleRange {
- if (_visibleRangeLength < 0) {
- return null;
- }
- return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
- }
+ R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => visitElement(element);
@override
- bool get isStatic => enclosingElement is CompilationUnitElement;
+ R visitHtmlElement(HtmlElement element) => visitElement(element);
- /**
- * Set the visible range for this element to the range starting at the given offset with the given
- * length.
- *
- * @param offset the offset to the beginning of the visible range for this element
- * @param length the length of the visible range for this element, or `-1` if this element
- * does not have a visible range
- */
- void setVisibleRange(int offset, int length) {
- _visibleRangeOffset = offset;
- _visibleRangeLength = length;
- }
+ R visitHtmlScriptElement(HtmlScriptElement element) => visitElement(element);
@override
- void appendTo(JavaStringBuilder builder) {
- String name = displayName;
- if (name != null) {
- builder.append(name);
- }
- super.appendTo(builder);
- }
+ R visitImportElement(ImportElement element) => visitElement(element);
@override
- String get identifier => "${name}@${nameOffset}";
-}
-
-/**
- * Instances of the class `FunctionTypeAliasElementImpl` implement a
- * `FunctionTypeAliasElement`.
- */
-class FunctionTypeAliasElementImpl extends ElementImpl implements FunctionTypeAliasElement {
- /**
- * An array containing all of the parameters defined by this type alias.
- */
- List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
-
- /**
- * The return type defined by this type alias.
- */
- DartType returnType;
+ R visitLabelElement(LabelElement element) => visitElement(element);
- /**
- * The type of function defined by this type alias.
- */
- FunctionType type;
+ @override
+ R visitLibraryElement(LibraryElement element) => visitElement(element);
- /**
- * An array containing all of the type parameters defined for this type.
- */
- List<TypeParameterElement> _typeParameters = TypeParameterElementImpl.EMPTY_ARRAY;
+ R visitLocalElement(LocalElement element) {
+ if (element is LocalVariableElement) {
+ return visitVariableElement(element);
+ } else if (element is ParameterElement) {
+ return visitVariableElement(element);
+ } else if (element is FunctionElement) {
+ return visitExecutableElement(element);
+ }
+ return null;
+ }
- /**
- * An empty array of type alias elements.
- */
- static List<FunctionTypeAliasElement> EMPTY_ARRAY = new List<FunctionTypeAliasElement>(0);
+ @override
+ R visitLocalVariableElement(LocalVariableElement element) => visitLocalElement(element);
- /**
- * Initialize a newly created type alias element to have the given name.
- *
- * @param name the name of this element
- */
- FunctionTypeAliasElementImpl(Identifier name) : super.forNode(name);
+ @override
+ R visitMethodElement(MethodElement element) => visitExecutableElement(element);
@override
- accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this);
+ R visitMultiplyDefinedElement(MultiplyDefinedElement element) => visitElement(element);
@override
- ElementImpl getChild(String identifier) {
- for (VariableElement parameter in _parameters) {
- if ((parameter as VariableElementImpl).identifier == identifier) {
- return parameter as VariableElementImpl;
- }
- }
- for (TypeParameterElement typeParameter in _typeParameters) {
- if ((typeParameter as TypeParameterElementImpl).identifier == identifier) {
- return typeParameter as TypeParameterElementImpl;
- }
- }
- return null;
- }
+ R visitParameterElement(ParameterElement element) => visitLocalElement(element);
@override
- CompilationUnitElement get enclosingElement => super.enclosingElement as CompilationUnitElement;
+ R visitPolymerAttributeElement(PolymerAttributeElement element) => visitPolymerElement(element);
+
+ R visitPolymerElement(PolymerElement element) => visitToolkitObjectElement(element);
@override
- ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
+ R visitPolymerTagDartElement(PolymerTagDartElement element) => visitPolymerElement(element);
@override
- FunctionTypeAlias get node => getNodeMatching((node) => node is FunctionTypeAlias);
+ R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) => visitPolymerElement(element);
@override
- List<ParameterElement> get parameters => _parameters;
+ R visitPrefixElement(PrefixElement element) => visitElement(element);
@override
- List<TypeParameterElement> get typeParameters => _typeParameters;
+ R visitPropertyAccessorElement(PropertyAccessorElement element) => visitExecutableElement(element);
- /**
- * Set the parameters defined by this type alias to the given parameters.
- *
- * @param parameters the parameters defined by this type alias
- */
- void set parameters(List<ParameterElement> parameters) {
- if (parameters != null) {
- for (ParameterElement parameter in parameters) {
- (parameter as ParameterElementImpl).enclosingElement = this;
- }
- }
- this._parameters = parameters;
- }
+ R visitPropertyInducingElement(PropertyInducingElement element) => visitVariableElement(element);
- /**
- * Set the type parameters defined for this type to the given parameters.
- *
- * @param typeParameters the type parameters defined for this type
- */
- void set typeParameters(List<TypeParameterElement> typeParameters) {
- for (TypeParameterElement typeParameter in typeParameters) {
- (typeParameter as TypeParameterElementImpl).enclosingElement = this;
- }
- this._typeParameters = typeParameters;
- }
+ R visitToolkitObjectElement(ToolkitObjectElement element) => visitElement(element);
- /**
- * 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.
- *
- * @param parameters the parameters defined by this type alias
- */
- void shareParameters(List<ParameterElement> parameters) {
- this._parameters = parameters;
- }
+ @override
+ R visitTopLevelVariableElement(TopLevelVariableElement element) => visitPropertyInducingElement(element);
- /**
- * Set the type parameters defined for this type 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.
- *
- * @param typeParameters the type parameters defined for this type
- */
- void shareTypeParameters(List<TypeParameterElement> typeParameters) {
- this._typeParameters = typeParameters;
- }
+ @override
+ R visitTypeParameterElement(TypeParameterElement element) => visitElement(element);
+
+ R visitVariableElement(VariableElement element) => visitElement(element);
+}
+
+/**
+ * Implementation of [AngularSelectorElement] based on presence of attribute.
+ */
+class HasAttributeSelectorElementImpl extends AngularSelectorElementImpl implements AngularHasAttributeSelectorElement {
+ HasAttributeSelectorElementImpl(String attributeName, int offset) : super(attributeName, offset);
@override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChildren(_parameters, visitor);
- safelyVisitChildren(_typeParameters, visitor);
+ bool apply(XmlTagNode node) {
+ String attributeName = name;
+ return node.getAttribute(attributeName) != null;
}
@override
void appendTo(JavaStringBuilder builder) {
- builder.append("typedef ");
- builder.append(displayName);
- int typeParameterCount = _typeParameters.length;
- if (typeParameterCount > 0) {
- builder.append("<");
- for (int i = 0; i < typeParameterCount; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- (_typeParameters[i] as TypeParameterElementImpl).appendTo(builder);
- }
- builder.append(">");
- }
- builder.append("(");
- int parameterCount = _parameters.length;
- for (int i = 0; i < parameterCount; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- (_parameters[i] as ParameterElementImpl).appendTo(builder);
- }
- builder.append(")");
- if (type != null) {
- builder.append(Element.RIGHT_ARROW);
- builder.append(type.returnType);
- }
+ builder.append("[");
+ builder.append(name);
+ builder.append("]");
}
}
/**
+ * The interface `HideElementCombinator` defines the behavior of combinators that cause some
+ * of the names in a namespace to be hidden when being imported.
+ */
+abstract class HideElementCombinator implements NamespaceCombinator {
+ /**
+ * Return an array containing the names that are not to be made visible in the importing library
+ * even if they are defined in the imported library.
+ *
+ * @return the names from the imported library that are hidden from the importing library
+ */
+ List<String> get hiddenNames;
+}
+
+/**
* Instances of the class `HideElementCombinatorImpl` implement a
* [HideElementCombinator].
*/
@@ -5140,6 +5709,34 @@ class HideElementCombinatorImpl implements HideElementCombinator {
}
/**
+ * The interface `HtmlElement` defines the behavior of elements representing an HTML file.
+ */
+abstract class HtmlElement implements Element {
+ /**
+ * Return the [CompilationUnitElement] associated with this Angular HTML file, maybe
+ * `null` if not an Angular file.
+ */
+ CompilationUnitElement get angularCompilationUnit;
+
+ /**
+ * Return an array containing all of the [PolymerTagHtmlElement]s defined in the HTML file.
+ *
+ * @return the [PolymerTagHtmlElement]s elements in the HTML file (not `null`,
+ * contains no `null`s)
+ */
+ List<PolymerTagHtmlElement> get polymerTags;
+
+ /**
+ * Return an array containing all of the script elements contained in the HTML file. This includes
+ * scripts with libraries that are defined by the content of a script tag as well as libraries
+ * that are referenced in the {@core source} attribute of a script tag.
+ *
+ * @return the script elements in the HTML file (not `null`, contains no `null`s)
+ */
+ List<HtmlScriptElement> get scripts;
+}
+
+/**
* Instances of the class `HtmlElementImpl` implement an [HtmlElement].
*/
class HtmlElementImpl extends ElementImpl implements HtmlElement {
@@ -5256,1817 +5853,2010 @@ class HtmlElementImpl extends ElementImpl implements HtmlElement {
}
/**
- * Instances of the class `HtmlScriptElementImpl` implement an [HtmlScriptElement].
- */
-abstract class HtmlScriptElementImpl extends ElementImpl implements HtmlScriptElement {
- /**
- * An empty array of HTML script elements.
- */
- static List<HtmlScriptElement> EMPTY_ARRAY = new List<HtmlScriptElement>(0);
-
- /**
- * Initialize a newly created script element to have the specified tag name and offset.
- *
- * @param node the XML node from which this element is derived (not `null`)
- */
- HtmlScriptElementImpl(XmlTagNode node) : super(node.tag, node.tagToken.offset);
-}
-
-/**
- * Instances of the class `ImportElementImpl` implement an [ImportElement].
+ * The interface `HtmlScriptElement` defines the behavior of elements representing a script
+ * tag in an HTML file.
+ *
+ * @see EmbeddedHtmlScriptElement
+ * @see ExternalHtmlScriptElement
*/
-class ImportElementImpl extends UriReferencedElementImpl implements ImportElement {
- /**
- * 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 = NamespaceCombinator.EMPTY_ARRAY;
-
- /**
- * The prefix that was specified as part of the import directive, or `null` if there was no
- * prefix specified.
- */
- PrefixElement prefix;
-
- /**
- * Initialize a newly created import element.
- *
- * @param offset the directive offset, may be `-1` if synthetic.
- */
- ImportElementImpl(int offset) : super(null, offset);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitImportElement(this);
-
- @override
- ElementKind get kind => ElementKind.IMPORT;
-
- @override
- bool get isDeferred => hasModifier(Modifier.DEFERRED);
-
- /**
- * Set whether this import is for a deferred library to correspond to the given value.
- *
- * @param isDeferred `true` if this import is for a deferred library
- */
- void set deferred(bool isDeferred) {
- setModifier(Modifier.DEFERRED, isDeferred);
- }
-
- @override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChild(prefix, visitor);
- }
-
- @override
- void appendTo(JavaStringBuilder builder) {
- builder.append("import ");
- (importedLibrary as LibraryElementImpl).appendTo(builder);
- }
-
- @override
- String get identifier => "${(importedLibrary as LibraryElementImpl).identifier}@${nameOffset}";
+abstract class HtmlScriptElement implements Element {
}
/**
- * Instances of the class `LabelElementImpl` implement a `LabelElement`.
+ * Instances of the class `HtmlScriptElementImpl` implement an [HtmlScriptElement].
*/
-class LabelElementImpl extends ElementImpl implements LabelElement {
- /**
- * A flag indicating whether this label is associated with a `switch` statement.
- */
- final bool _onSwitchStatement;
-
- /**
- * A flag indicating whether this label is associated with a `switch` member (`case`
- * or `default`).
- */
- final bool _onSwitchMember;
-
- /**
- * An empty array of label elements.
- */
- static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>(0);
-
- /**
- * Initialize a newly created label element to have the given name.
- *
- * @param name the name of this element
- * @param onSwitchStatement `true` if this label is associated with a `switch`
- * statement
- * @param onSwitchMember `true` if this label is associated with a `switch` member
- */
- LabelElementImpl(Identifier name, this._onSwitchStatement, this._onSwitchMember) : super.forNode(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitLabelElement(this);
-
- @override
- ExecutableElement get enclosingElement => super.enclosingElement as ExecutableElement;
-
- @override
- ElementKind get kind => ElementKind.LABEL;
-
+abstract class HtmlScriptElementImpl extends ElementImpl implements HtmlScriptElement {
/**
- * Return `true` if this label is associated with a `switch` member (`case` or
- * `default`).
- *
- * @return `true` if this label is associated with a `switch` member
+ * An empty array of HTML script elements.
*/
- bool get isOnSwitchMember => _onSwitchMember;
+ static List<HtmlScriptElement> EMPTY_ARRAY = new List<HtmlScriptElement>(0);
/**
- * Return `true` if this label is associated with a `switch` statement.
+ * Initialize a newly created script element to have the specified tag name and offset.
*
- * @return `true` if this label is associated with a `switch` statement
+ * @param node the XML node from which this element is derived (not `null`)
*/
- bool get isOnSwitchStatement => _onSwitchStatement;
+ HtmlScriptElementImpl(XmlTagNode node) : super(node.tag, node.tagToken.offset);
}
/**
- * Instances of the class `LibraryElementImpl` implement a `LibraryElement`.
+ * The interface `ImportElement` defines the behavior of objects representing information
+ * about a single import directive within a library.
*/
-class LibraryElementImpl extends ElementImpl implements LibraryElement {
+abstract class ImportElement implements Element, UriReferencedElement {
/**
- * An empty array of library elements.
+ * An empty array of import elements.
*/
- static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>(0);
+ static final List<ImportElement> EMPTY_ARRAY = new List<ImportElement>(0);
/**
- * Determine if the given library is up to date with respect to the given time stamp.
+ * Return an array containing the combinators that were specified as part of the import directive
+ * in the order in which they were specified.
*
- * @param library the library to process
- * @param timeStamp the time stamp to check against
- * @param visitedLibraries the set of visited libraries
+ * @return the combinators specified in the import directive
*/
- static bool _safeIsUpToDate(LibraryElement library, int timeStamp, Set<LibraryElement> visitedLibraries) {
- if (!visitedLibraries.contains(library)) {
- visitedLibraries.add(library);
- AnalysisContext context = library.context;
- // Check the defining compilation unit.
- if (timeStamp < context.getModificationStamp(library.definingCompilationUnit.source)) {
- return false;
- }
- // Check the parted compilation units.
- for (CompilationUnitElement element in library.parts) {
- if (timeStamp < context.getModificationStamp(element.source)) {
- return false;
- }
- }
- // Check the imported libraries.
- for (LibraryElement importedLibrary in library.importedLibraries) {
- if (!_safeIsUpToDate(importedLibrary, timeStamp, visitedLibraries)) {
- return false;
- }
- }
- // Check the exported libraries.
- for (LibraryElement exportedLibrary in library.exportedLibraries) {
- if (!_safeIsUpToDate(exportedLibrary, timeStamp, visitedLibraries)) {
- return false;
- }
- }
- }
- return true;
- }
+ List<NamespaceCombinator> get combinators;
/**
- * The analysis context in which this library is defined.
+ * Return the library that is imported into this library by this import directive.
+ *
+ * @return the library that is imported into this library
*/
- final AnalysisContext context;
+ LibraryElement get importedLibrary;
/**
- * The compilation unit that defines this library.
+ * Return the prefix that was specified as part of the import directive, or `null` if there
+ * was no prefix specified.
+ *
+ * @return the prefix that was specified as part of the import directive
*/
- CompilationUnitElement _definingCompilationUnit;
+ PrefixElement get prefix;
/**
- * The entry point for this library, or `null` if this library does not have an entry point.
+ * Return the offset of the prefix of this import in the file that contains this import directive,
+ * or `-1` if this import is synthetic, does not have a prefix, or otherwise does not have
+ * an offset.
+ *
+ * @return the offset of the prefix of this import
*/
- FunctionElement entryPoint;
+ int get prefixOffset;
/**
- * An array containing specifications of all of the imports defined in this library.
+ * Return `true` if this import is for a deferred library.
+ *
+ * @return `true` if this import is for a deferred library
*/
- List<ImportElement> _imports = ImportElement.EMPTY_ARRAY;
+ bool get isDeferred;
+}
+/**
+ * Instances of the class `ImportElementImpl` implement an [ImportElement].
+ */
+class ImportElementImpl extends UriReferencedElementImpl implements ImportElement {
/**
- * An array containing specifications of all of the exports defined in this library.
+ * The offset of the prefix of this import in the file that contains the this import directive, or
+ * `-1` if this import is synthetic.
*/
- List<ExportElement> _exports = ExportElement.EMPTY_ARRAY;
+ int prefixOffset = 0;
/**
- * An array containing all of the compilation units that are included in this library using a
- * `part` directive.
+ * The library that is imported into this library by this import directive.
*/
- List<CompilationUnitElement> _parts = CompilationUnitElementImpl.EMPTY_ARRAY;
+ LibraryElement importedLibrary;
/**
- * Is `true` if this library is created for Angular analysis.
+ * The combinators that were specified as part of the import directive in the order in which they
+ * were specified.
*/
- bool _isAngularHtml = false;
+ List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_ARRAY;
/**
- * The element representing the synthetic function `loadLibrary` that is defined for this
- * library, or `null` if the element has not yet been created.
+ * The prefix that was specified as part of the import directive, or `null` if there was no
+ * prefix specified.
*/
- FunctionElement _loadLibraryFunction;
+ PrefixElement prefix;
/**
- * Initialize a newly created library element to have the given name.
+ * Initialize a newly created import element.
*
- * @param context the analysis context in which the library is defined
- * @param name the name of this element
+ * @param offset the directive offset, may be `-1` if synthetic.
*/
- LibraryElementImpl(this.context, LibraryIdentifier name) : super.forNode(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);
+ ImportElementImpl(int offset) : super(null, offset);
@override
- bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && _definingCompilationUnit == (object as LibraryElementImpl).definingCompilationUnit;
+ accept(ElementVisitor visitor) => visitor.visitImportElement(this);
@override
- ElementImpl getChild(String identifier) {
- if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier == identifier) {
- return _definingCompilationUnit as CompilationUnitElementImpl;
- }
- for (CompilationUnitElement part in _parts) {
- if ((part as CompilationUnitElementImpl).identifier == identifier) {
- return part as CompilationUnitElementImpl;
- }
- }
- for (ImportElement importElement in _imports) {
- if ((importElement as ImportElementImpl).identifier == identifier) {
- return importElement as ImportElementImpl;
- }
- }
- for (ExportElement exportElement in _exports) {
- if ((exportElement as ExportElementImpl).identifier == identifier) {
- return exportElement as ExportElementImpl;
- }
- }
- return null;
- }
+ ElementKind get kind => ElementKind.IMPORT;
@override
- CompilationUnitElement get definingCompilationUnit => _definingCompilationUnit;
+ bool get isDeferred => hasModifier(Modifier.DEFERRED);
- @override
- List<LibraryElement> get exportedLibraries {
- Set<LibraryElement> libraries = new Set<LibraryElement>();
- for (ExportElement element in _exports) {
- LibraryElement library = element.exportedLibrary;
- if (library != null) {
- libraries.add(library);
- }
- }
- return new List.from(libraries);
+ /**
+ * Set whether this import is for a deferred library to correspond to the given value.
+ *
+ * @param isDeferred `true` if this import is for a deferred library
+ */
+ void set deferred(bool isDeferred) {
+ setModifier(Modifier.DEFERRED, isDeferred);
}
@override
- List<ExportElement> get exports => _exports;
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChild(prefix, visitor);
+ }
@override
- List<LibraryElement> get importedLibraries {
- Set<LibraryElement> libraries = new Set<LibraryElement>();
- for (ImportElement element in _imports) {
- LibraryElement library = element.importedLibrary;
- if (library != null) {
- libraries.add(library);
- }
- }
- return new List.from(libraries);
+ void appendTo(JavaStringBuilder builder) {
+ builder.append("import ");
+ (importedLibrary as LibraryElementImpl).appendTo(builder);
}
@override
- List<ImportElement> get imports => _imports;
+ String get identifier => "${(importedLibrary as LibraryElementImpl).identifier}@${nameOffset}";
+}
- @override
- List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) {
- 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 new List.from(importList);
- }
+/**
+ * The interface `InterfaceType` defines the behavior common to objects representing the type
+ * introduced by either a class or an interface, or a reference to such a type.
+ */
+abstract class InterfaceType implements ParameterizedType {
+ /**
+ * Return an array containing all of the accessors (getters and setters) declared in this type.
+ *
+ * @return the accessors declared in this type
+ */
+ List<PropertyAccessorElement> get accessors;
@override
- ElementKind get kind => ElementKind.LIBRARY;
+ ClassElement get element;
- @override
- LibraryElement get library => this;
+ /**
+ * Return the element representing the getter with the given name that is declared in this class,
+ * or `null` if this class does not declare a getter with the given name.
+ *
+ * @param getterName the name of the getter to be returned
+ * @return the getter declared in this class with the given name
+ */
+ PropertyAccessorElement getGetter(String getterName);
- @override
- FunctionElement get loadLibraryFunction {
- if (_loadLibraryFunction == null) {
- FunctionElementImpl function = new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1);
- function.synthetic = true;
- function.enclosingElement = this;
- function.returnType = loadLibraryReturnType;
- function.type = new FunctionTypeImpl.con1(function);
- _loadLibraryFunction = function;
- }
- return _loadLibraryFunction;
- }
+ /**
+ * Return an array containing all of the interfaces that are implemented by this interface. Note
+ * that this is <b>not</b>, in general, equivalent to getting the interfaces from this type's
+ * element because the types returned by this method will have had their type parameters replaced.
+ *
+ * @return the interfaces that are implemented by this type
+ */
+ List<InterfaceType> get interfaces;
+ /**
+ * Return the least upper bound of this type and the given type, or `null` if there is no
+ * least upper bound.
+ *
+ * Given two interfaces <i>I</i> and <i>J</i>, let <i>S<sub>I</sub></i> be the set of
+ * superinterfaces of <i>I<i>, let <i>S<sub>J</sub></i> be the set of superinterfaces of <i>J</i>
+ * and let <i>S = (I &cup; S<sub>I</sub>) &cap; (J &cup; S<sub>J</sub>)</i>. Furthermore, we
+ * define <i>S<sub>n</sub> = {T | T &isin; S &and; depth(T) = n}</i> for any finite <i>n</i>,
+ * where <i>depth(T)</i> is the number of steps in the longest inheritance path from <i>T</i> to
+ * <i>Object</i>. Let <i>q</i> be the largest number such that <i>S<sub>q</sub></i> has
+ * cardinality one. The least upper bound of <i>I</i> and <i>J</i> is the sole element of
+ * <i>S<sub>q</sub></i>.
+ *
+ * @param type the other type used to compute the least upper bound
+ * @return the least upper bound of this type and the given type
+ */
@override
- List<CompilationUnitElement> get parts => _parts;
+ DartType getLeastUpperBound(DartType type);
+
+ /**
+ * Return the element representing the method with the given name that is declared in this class,
+ * or `null` if this class does not declare a method with the given name.
+ *
+ * @param methodName the name of the method to be returned
+ * @return the method declared in this class with the given name
+ */
+ MethodElement getMethod(String methodName);
- @override
- List<PrefixElement> get prefixes {
- Set<PrefixElement> prefixes = new Set<PrefixElement>();
- for (ImportElement element in _imports) {
- PrefixElement prefix = element.prefix;
- if (prefix != null) {
- prefixes.add(prefix);
- }
- }
- return new List.from(prefixes);
- }
+ /**
+ * Return an array containing all of the methods declared in this type.
+ *
+ * @return the methods declared in this type
+ */
+ List<MethodElement> get methods;
- @override
- Source get source {
- if (_definingCompilationUnit == null) {
- return null;
- }
- return _definingCompilationUnit.source;
- }
+ /**
+ * Return an array containing all of the mixins that are applied to the class being extended in
+ * order to derive the superclass of this class. Note that this is <b>not</b>, in general,
+ * equivalent to getting the mixins from this type's element because the types returned by this
+ * method will have had their type parameters replaced.
+ *
+ * @return the mixins that are applied to derive the superclass of this class
+ */
+ List<InterfaceType> get mixins;
- @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;
- }
+ /**
+ * Return the element representing the setter with the given name that is declared in this class,
+ * or `null` if this class does not declare a setter with the given name.
+ *
+ * @param setterName the name of the setter to be returned
+ * @return the setter declared in this class with the given name
+ */
+ PropertyAccessorElement getSetter(String setterName);
- @override
- List<CompilationUnitElement> get units {
- List<CompilationUnitElement> units = new List<CompilationUnitElement>(1 + _parts.length);
- units[0] = _definingCompilationUnit;
- JavaSystem.arraycopy(_parts, 0, units, 1, _parts.length);
- return units;
- }
+ /**
+ * Return the type representing the superclass of this type, or null if this type represents the
+ * class 'Object'. Note that this is <b>not</b>, in general, equivalent to getting the superclass
+ * from this type's element because the type returned by this method will have had it's type
+ * parameters replaced.
+ *
+ * @return the superclass of this type
+ */
+ InterfaceType get superclass;
- @override
- List<LibraryElement> get visibleLibraries {
- Set<LibraryElement> visibleLibraries = new Set();
- _addVisibleLibraries(visibleLibraries, false);
- return new List.from(visibleLibraries);
- }
+ /**
+ * Return `true` if this type is a direct supertype of the given type. The implicit
+ * interface of class <i>I</i> is a direct supertype of the implicit interface of class <i>J</i>
+ * iff:
+ * * <i>I</i> is Object, and <i>J</i> has no extends clause.
+ * * <i>I</i> is listed in the extends clause of <i>J</i>.
+ * * <i>I</i> is listed in the implements clause of <i>J</i>.
+ * * <i>I</i> is listed in the with clause of <i>J</i>.
+ * * <i>J</i> is a mixin application of the mixin of <i>I</i>.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is a direct supertype of the given type
+ */
+ bool isDirectSupertypeOf(InterfaceType type);
+ /**
+ * Return `true` if this type is more specific than the given type. An interface type
+ * <i>T</i> is more specific than an interface type <i>S</i>, written <i>T &laquo; S</i>, if one
+ * of the following conditions is met:
+ * * Reflexivity: <i>T</i> is <i>S</i>.
+ * * <i>T</i> is bottom.
+ * * <i>S</i> is dynamic.
+ * * Direct supertype: <i>S</i> is a direct supertype of <i>T</i>.
+ * * <i>T</i> is a type parameter and <i>S</i> is the upper bound of <i>T</i>.
+ * * Covariance: <i>T</i> is of the form <i>I&lt;T<sub>1</sub>, &hellip;, T<sub>n</sub>&gt;</i>
+ * and S</i> is of the form <i>I&lt;S<sub>1</sub>, &hellip;, S<sub>n</sub>&gt;</i> and
+ * <i>T<sub>i</sub> &laquo; S<sub>i</sub></i>, <i>1 <= i <= n</i>.
+ * * Transitivity: <i>T &laquo; U</i> and <i>U &laquo; S</i>.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is more specific than the given type
+ */
@override
- bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI);
+ bool isMoreSpecificThan(DartType type);
+ /**
+ * Return `true` if this type is a subtype of the given type. An interface type <i>T</i> is
+ * a subtype of an interface type <i>S</i>, written <i>T</i> <: <i>S</i>, iff
+ * <i>[bottom/dynamic]T</i> &laquo; <i>S</i> (<i>T</i> is more specific than <i>S</i>). If an
+ * interface type <i>I</i> includes a method named <i>call()</i>, and the type of <i>call()</i> is
+ * the function type <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>.
+ *
+ * @param type the type being compared with this type
+ * @return `true` if this type is a subtype of the given type
+ */
@override
- int get hashCode => _definingCompilationUnit.hashCode;
+ bool isSubtypeOf(DartType type);
- @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;
- }
+ /**
+ * Return the element representing the constructor that results from looking up the given
+ * constructor in this class with respect to the given library, or `null` if the look up
+ * fails. The behavior of this method is defined by the Dart Language Specification in section
+ * 12.11.1: <blockquote>If <i>e</i> is of the form <b>new</b> <i>T.id()</i> then let <i>q<i> be
+ * the constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor <i>T<i>. Otherwise, if
+ * <i>q</i> is not defined or not accessible, a NoSuchMethodException is thrown. </blockquote>
+ *
+ * @param constructorName the name of the constructor being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given constructor in this class with respect to the given
+ * library
+ */
+ ConstructorElement lookUpConstructor(String constructorName, LibraryElement library);
- @override
- bool get isAngularHtml => _isAngularHtml;
+ /**
+ * Return the element representing the getter that results from looking up the given getter in
+ * this class with respect to the given library, or `null` if the look up fails. The
+ * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
+ * <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
+ * with respect to library <i>L</i> is:
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
+ * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
+ * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
+ * Otherwise, we say that the lookup has failed.
+ * </blockquote>
+ *
+ * @param getterName the name of the getter being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given getter in this class with respect to the given
+ * library
+ */
+ PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library);
- @override
- bool get isBrowserApplication => entryPoint != null && isOrImportsBrowserLibrary;
+ /**
+ * Return the element representing the getter that results from looking up the given getter in the
+ * superclass of this class with respect to the given library, or `null` if the look up
+ * fails. The behavior of this method is defined by the Dart Language Specification in section
+ * 12.15.1: <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class
+ * <i>C</i> with respect to library <i>L</i> is:
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
+ * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
+ * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
+ * Otherwise, we say that the lookup has failed.
+ * </blockquote>
+ *
+ * @param getterName the name of the getter being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given getter in this class with respect to the given
+ * library
+ */
+ PropertyAccessorElement lookUpGetterInSuperclass(String getterName, LibraryElement library);
- @override
- bool get isDartCore => name == "dart.core";
+ /**
+ * Return the element representing the method that results from looking up the given method in
+ * this class with respect to the given library, or `null` if the look up fails. The
+ * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
+ * <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect to library
+ * <i>L</i> is:
+ * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
+ * that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
+ * the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
+ * to <i>L</i>. Otherwise, we say that the lookup has failed.
+ * </blockquote>
+ *
+ * @param methodName the name of the method being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given method in this class with respect to the given
+ * library
+ */
+ MethodElement lookUpMethod(String methodName, LibraryElement library);
- @override
- bool get isInSdk => StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E);
+ /**
+ * Return the element representing the method that results from looking up the given method in the
+ * superclass of this class with respect to the given library, or `null` if the look up
+ * fails. The behavior of this method is defined by the Dart Language Specification in section
+ * 12.15.1: <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect
+ * to library <i>L</i> is:
+ * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
+ * that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
+ * the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
+ * to <i>L</i>. Otherwise, we say that the lookup has failed.
+ * </blockquote>
+ *
+ * @param methodName the name of the method being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given method in this class with respect to the given
+ * library
+ */
+ MethodElement lookUpMethodInSuperclass(String methodName, LibraryElement library);
- @override
- bool isUpToDate(int timeStamp) {
- Set<LibraryElement> visitedLibraries = new Set();
- return _safeIsUpToDate(this, timeStamp, visitedLibraries);
- }
+ /**
+ * Return the element representing the setter that results from looking up the given setter in
+ * this class with respect to the given library, or `null` if the look up fails. The
+ * behavior of this method is defined by the Dart Language Specification in section 12.16:
+ * <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
+ * with respect to library <i>L</i> is:
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
+ * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
+ * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
+ * Otherwise, we say that the lookup has failed.
+ * </blockquote>
+ *
+ * @param setterName the name of the setter being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given setter in this class with respect to the given
+ * library
+ */
+ PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library);
/**
- * Specifies if this library is created for Angular analysis.
+ * Return the element representing the setter that results from looking up the given setter in the
+ * superclass of this class with respect to the given library, or `null` if the look up
+ * fails. The behavior of this method is defined by the Dart Language Specification in section
+ * 12.16: <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class
+ * <i>C</i> with respect to library <i>L</i> is:
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
+ * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
+ * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
+ * Otherwise, we say that the lookup has failed.
+ * </blockquote>
+ *
+ * @param setterName the name of the setter being looked up
+ * @param library the library with respect to which the lookup is being performed
+ * @return the result of looking up the given setter in this class with respect to the given
+ * library
*/
- void set angularHtml(bool isAngularHtml) {
- this._isAngularHtml = isAngularHtml;
- }
+ PropertyAccessorElement lookUpSetterInSuperclass(String setterName, LibraryElement library);
/**
- * Set the compilation unit that defines this library to the given compilation unit.
+ * Return the type resulting from substituting the given arguments for this type's parameters.
+ * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`.
*
- * @param definingCompilationUnit the compilation unit that defines this library
+ * @param argumentTypes the actual type arguments being substituted for the type parameters
+ * @return the result of performing the substitution
*/
- void set definingCompilationUnit(CompilationUnitElement definingCompilationUnit) {
- (definingCompilationUnit as CompilationUnitElementImpl).enclosingElement = this;
- this._definingCompilationUnit = definingCompilationUnit;
- }
+ InterfaceType substitute4(List<DartType> argumentTypes);
+
+ @override
+ InterfaceType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
+}
+/**
+ * Instances of the class `InterfaceTypeImpl` defines the behavior common to objects
+ * representing the type introduced by either a class or an interface, or a reference to such a
+ * type.
+ */
+class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
/**
- * Set the specifications of all of the exports defined in this library to the given array.
- *
- * @param exports the specifications of all of the exports defined in this library
+ * An empty array of types.
*/
- void set exports(List<ExportElement> exports) {
- for (ExportElement exportElement in exports) {
- (exportElement as ExportElementImpl).enclosingElement = this;
- }
- this._exports = exports;
- }
+ static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>(0);
/**
- * Set whether this library has an import of a "dart-ext" URI to the given value.
+ * This method computes the longest inheritance path from some passed [Type] to Object.
*
- * @param hasExtUri `true` if this library has an import of a "dart-ext" URI
+ * @param type the [Type] to compute the longest inheritance path of from the passed
+ * [Type] to Object
+ * @return the computed longest inheritance path to Object
+ * @see InterfaceType#getLeastUpperBound(Type)
*/
- void set hasExtUri(bool hasExtUri) {
- setModifier(Modifier.HAS_EXT_URI, hasExtUri);
- }
+ static int computeLongestInheritancePathToObject(InterfaceType type) => _computeLongestInheritancePathToObject(type, 0, new Set<ClassElement>());
/**
- * Set the specifications of all of the imports defined in this library to the given array.
+ * Returns the set of all superinterfaces of the passed [Type].
*
- * @param imports the specifications of all of the imports defined in this library
+ * @param type the [Type] to compute the set of superinterfaces of
+ * @return the [Set] of superinterfaces of the passed [Type]
+ * @see #getLeastUpperBound(Type)
*/
- void set imports(List<ImportElement> imports) {
- 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;
- }
+ static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => _computeSuperinterfaceSet(type, new Set<InterfaceType>());
/**
- * Set the compilation units that are included in this library using a `part` directive.
+ * This method computes the longest inheritance path from some passed [Type] to Object. This
+ * method calls itself recursively, callers should use the public method
+ * [computeLongestInheritancePathToObject].
*
- * @param parts the compilation units that are included in this library using a `part`
- * directive
+ * @param type the [Type] to compute the longest inheritance path of from the passed
+ * [Type] to Object
+ * @param depth a field used recursively
+ * @param visitedClasses the classes that have already been visited
+ * @return the computed longest inheritance path to Object
+ * @see #computeLongestInheritancePathToObject(Type)
+ * @see #getLeastUpperBound(Type)
*/
- void set parts(List<CompilationUnitElement> parts) {
- for (CompilationUnitElement compilationUnit in parts) {
- (compilationUnit as CompilationUnitElementImpl).enclosingElement = this;
+ static int _computeLongestInheritancePathToObject(InterfaceType type, int depth, Set<ClassElement> visitedClasses) {
+ ClassElement classElement = type.element;
+ // Object case
+ if (classElement.supertype == null || visitedClasses.contains(classElement)) {
+ return depth;
}
- this._parts = parts;
- }
-
- @override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChild(_definingCompilationUnit, visitor);
- safelyVisitChildren(_exports, visitor);
- safelyVisitChildren(_imports, visitor);
- safelyVisitChildren(_parts, visitor);
+ int longestPath = 1;
+ try {
+ visitedClasses.add(classElement);
+ List<InterfaceType> superinterfaces = classElement.interfaces;
+ int pathLength;
+ if (superinterfaces.length > 0) {
+ // loop through each of the superinterfaces recursively calling this method and keeping track
+ // of the longest path to return
+ for (InterfaceType superinterface in superinterfaces) {
+ pathLength = _computeLongestInheritancePathToObject(superinterface, depth + 1, visitedClasses);
+ if (pathLength > longestPath) {
+ longestPath = pathLength;
+ }
+ }
+ }
+ // finally, perform this same check on the super type
+ // TODO(brianwilkerson) Does this also need to add in the number of mixin classes?
+ InterfaceType supertype = classElement.supertype;
+ pathLength = _computeLongestInheritancePathToObject(supertype, depth + 1, visitedClasses);
+ if (pathLength > longestPath) {
+ longestPath = pathLength;
+ }
+ } finally {
+ visitedClasses.remove(classElement);
+ }
+ return longestPath;
}
- @override
- String get identifier => _definingCompilationUnit.source.encoding;
-
/**
- * Recursively fills set of visible libraries for [getVisibleElementsLibraries].
+ * Returns the set of all superinterfaces of the passed [Type]. This is a recursive method,
+ * callers should call the public [computeSuperinterfaceSet].
+ *
+ * @param type the [Type] to compute the set of superinterfaces of
+ * @param set a [HashSet] used recursively by this method
+ * @return the [Set] of superinterfaces of the passed [Type]
+ * @see #computeSuperinterfaceSet(Type)
+ * @see #getLeastUpperBound(Type)
*/
- void _addVisibleLibraries(Set<LibraryElement> visibleLibraries, bool includeExports) {
- // maybe already processed
- if (!visibleLibraries.add(this)) {
- return;
- }
- // add imported libraries
- for (ImportElement importElement in _imports) {
- LibraryElement importedLibrary = importElement.importedLibrary;
- if (importedLibrary != null) {
- (importedLibrary as LibraryElementImpl)._addVisibleLibraries(visibleLibraries, true);
+ static Set<InterfaceType> _computeSuperinterfaceSet(InterfaceType type, Set<InterfaceType> set) {
+ Element element = type.element;
+ if (element != null) {
+ List<InterfaceType> superinterfaces = type.interfaces;
+ for (InterfaceType superinterface in superinterfaces) {
+ if (set.add(superinterface)) {
+ _computeSuperinterfaceSet(superinterface, set);
+ }
}
- }
- // add exported libraries
- if (includeExports) {
- for (ExportElement exportElement in _exports) {
- LibraryElement exportedLibrary = exportElement.exportedLibrary;
- if (exportedLibrary != null) {
- (exportedLibrary as LibraryElementImpl)._addVisibleLibraries(visibleLibraries, true);
+ InterfaceType supertype = type.superclass;
+ if (supertype != null) {
+ if (set.add(supertype)) {
+ _computeSuperinterfaceSet(supertype, set);
}
}
}
+ return set;
}
/**
- * Return the object representing the type "Future" from the dart:async library, or the type
- * "void" if the type "Future" cannot be accessed.
+ * Return the intersection of the given sets of types, where intersection is based on the equality
+ * of the types themselves.
*
- * @return the type "Future" from the dart:async library
+ * @param first the first set of types to be intersected
+ * @param second the second set of types to be intersected
+ * @return the intersection of the given sets of types
*/
- DartType get loadLibraryReturnType {
- try {
- Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC);
- if (asyncSource == null) {
- AnalysisEngine.instance.logger.logError("Could not create a source for dart:async");
- return VoidTypeImpl.instance;
- }
- LibraryElement asyncElement = context.computeLibraryElement(asyncSource);
- if (asyncElement == null) {
- AnalysisEngine.instance.logger.logError("Could not build the element model for dart:async");
- return VoidTypeImpl.instance;
- }
- ClassElement futureElement = asyncElement.getType("Future");
- if (futureElement == null) {
- AnalysisEngine.instance.logger.logError("Could not find type Future in dart:async");
- return VoidTypeImpl.instance;
- }
- InterfaceType futureType = futureElement.type;
- return futureType.substitute4(<DartType> [DynamicTypeImpl.instance]);
- } on AnalysisException catch (exception) {
- AnalysisEngine.instance.logger.logError2("Could not build the element model for dart:async", exception);
- return VoidTypeImpl.instance;
- }
+ static List<InterfaceType> _intersection(Set<InterfaceType> first, Set<InterfaceType> second) {
+ Set<InterfaceType> result = new Set<InterfaceType>.from(first);
+ result.retainAll(second);
+ return new List.from(result);
}
/**
- * Answer `true` if the receiver directly or indirectly imports the dart:html libraries.
+ * Return the "least upper bound" of the given types under the assumption that the types have the
+ * same element and differ only in terms of the type arguments. The resulting type is composed by
+ * comparing the corresponding type arguments, keeping those that are the same, and using
+ * 'dynamic' for those that are different.
*
- * @return `true` if the receiver directly or indirectly imports the dart:html libraries
+ * @param firstType the first type
+ * @param secondType the second type
+ * @return the "least upper bound" of the given types
*/
- 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);
- }
+ static InterfaceType _leastUpperBound(InterfaceType firstType, InterfaceType secondType) {
+ if (firstType == secondType) {
+ return firstType;
+ }
+ List<DartType> firstArguments = firstType.typeArguments;
+ List<DartType> secondArguments = secondType.typeArguments;
+ int argumentCount = firstArguments.length;
+ if (argumentCount == 0) {
+ return firstType;
+ }
+ List<DartType> lubArguments = new List<DartType>(argumentCount);
+ for (int i = 0; i < argumentCount; i++) {
+ //
+ // Ideally we would take the least upper bound of the two argument types, but this can cause
+ // an infinite recursion (such as when finding the least upper bound of String and num).
+ //
+ if (firstArguments[i] == secondArguments[i]) {
+ lubArguments[i] = firstArguments[i];
}
- for (LibraryElement exportedLibrary in library.exportedLibraries) {
- if (!visited.contains(exportedLibrary)) {
- visited.add(exportedLibrary);
- }
+ if (lubArguments[i] == null) {
+ lubArguments[i] = DynamicTypeImpl.instance;
}
}
- return false;
+ InterfaceTypeImpl lub = new InterfaceTypeImpl.con1(firstType.element);
+ lub.typeArguments = lubArguments;
+ return lub;
}
-}
-
-/**
- * Instances of the class `LocalVariableElementImpl` implement a `LocalVariableElement`.
- */
-class LocalVariableElementImpl extends VariableElementImpl implements LocalVariableElement {
- /**
- * Is `true` if this variable is potentially mutated somewhere in its scope.
- */
- bool _potentiallyMutatedInScope = false;
-
- /**
- * Is `true` if this variable is potentially mutated somewhere in closure.
- */
- bool _potentiallyMutatedInClosure = false;
-
- /**
- * 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.
+ * An array containing the actual types of the type arguments.
*/
- int _visibleRangeLength = -1;
+ List<DartType> typeArguments = TypeImpl.EMPTY_ARRAY;
/**
- * An empty array of field elements.
+ * Initialize a newly created type to be declared by the given element.
+ *
+ * @param element the element representing the declaration of the type
*/
- static List<LocalVariableElement> EMPTY_ARRAY = new List<LocalVariableElement>(0);
+ InterfaceTypeImpl.con1(ClassElement element) : super(element, element.displayName);
/**
- * Initialize a newly created local variable element to have the given name.
+ * Initialize a newly created type to have the given name. This constructor should only be used in
+ * cases where there is no declaration of the type.
*
- * @param name the name of this element
+ * @param name the name of the type
*/
- LocalVariableElementImpl(Identifier name) : super.forNode(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this);
+ InterfaceTypeImpl.con2(String name) : super(null, name);
@override
- ElementKind get kind => ElementKind.LOCAL_VARIABLE;
+ bool operator ==(Object object) => internalEquals(object, new Set<ElementPair>());
@override
- List<ToolkitObjectElement> get toolkitObjects {
- CompilationUnitElementImpl unit = getAncestor((element) => element is CompilationUnitElementImpl);
- if (unit == null) {
- return ToolkitObjectElement.EMPTY_ARRAY;
+ List<PropertyAccessorElement> get accessors {
+ List<PropertyAccessorElement> accessors = element.accessors;
+ List<PropertyAccessorElement> members = new List<PropertyAccessorElement>(accessors.length);
+ for (int i = 0; i < accessors.length; i++) {
+ members[i] = PropertyAccessorMember.from(accessors[i], this);
}
- return unit._getToolkitObjects(this);
+ return members;
}
@override
- SourceRange get visibleRange {
- if (_visibleRangeLength < 0) {
- return null;
+ String get displayName {
+ String name = this.name;
+ List<DartType> typeArguments = this.typeArguments;
+ bool allDynamic = true;
+ for (DartType type in typeArguments) {
+ if (type != null && !type.isDynamic) {
+ allDynamic = false;
+ break;
+ }
}
- return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
+ // If there is at least one non-dynamic type, then list them out
+ if (!allDynamic) {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append(name);
+ builder.append("<");
+ for (int i = 0; i < typeArguments.length; i++) {
+ if (i != 0) {
+ builder.append(", ");
+ }
+ DartType typeArg = typeArguments[i];
+ builder.append(typeArg.displayName);
+ }
+ builder.append(">");
+ name = builder.toString();
+ }
+ return name;
}
@override
- bool get isPotentiallyMutatedInClosure => _potentiallyMutatedInClosure;
+ ClassElement get element => super.element as ClassElement;
@override
- bool get isPotentiallyMutatedInScope => _potentiallyMutatedInScope;
-
- /**
- * Specifies that this variable is potentially mutated somewhere in closure.
- */
- void markPotentiallyMutatedInClosure() {
- _potentiallyMutatedInClosure = true;
- }
-
- /**
- * Specifies that this variable is potentially mutated somewhere in its scope.
- */
- void markPotentiallyMutatedInScope() {
- _potentiallyMutatedInScope = true;
- }
+ PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember.from((element as ClassElementImpl).getGetter(getterName), this);
- /**
- * Set the toolkit specific information objects attached to this variable.
- *
- * @param toolkitObjects the toolkit objects attached to this variable
- */
- void set toolkitObjects(List<ToolkitObjectElement> toolkitObjects) {
- CompilationUnitElementImpl unit = getAncestor((element) => element is CompilationUnitElementImpl);
- if (unit == null) {
- return;
+ @override
+ List<InterfaceType> get interfaces {
+ ClassElement classElement = element;
+ List<InterfaceType> interfaces = classElement.interfaces;
+ List<TypeParameterElement> typeParameters = classElement.typeParameters;
+ List<DartType> parameterTypes = classElement.type.typeArguments;
+ if (typeParameters.length == 0) {
+ return interfaces;
}
- unit._setToolkitObjects(this, toolkitObjects);
- }
-
- /**
- * Set the visible range for this element to the range starting at the given offset with the given
- * length.
- *
- * @param offset the offset to the beginning of the visible range for this element
- * @param length the length of the visible range for this element, or `-1` if this element
- * does not have a visible range
- */
- void setVisibleRange(int offset, int length) {
- _visibleRangeOffset = offset;
- _visibleRangeLength = length;
+ int count = interfaces.length;
+ List<InterfaceType> typedInterfaces = new List<InterfaceType>(count);
+ for (int i = 0; i < count; i++) {
+ typedInterfaces[i] = interfaces[i].substitute2(typeArguments, parameterTypes);
+ }
+ return typedInterfaces;
}
@override
- void appendTo(JavaStringBuilder builder) {
- builder.append(type);
- builder.append(" ");
- builder.append(displayName);
+ DartType getLeastUpperBound(DartType type) {
+ // quick check for self
+ if (identical(type, this)) {
+ return this;
+ }
+ // dynamic
+ DartType dynamicType = DynamicTypeImpl.instance;
+ if (identical(this, dynamicType) || identical(type, dynamicType)) {
+ return dynamicType;
+ }
+ // TODO (jwren) opportunity here for a better, faster algorithm if this turns out to be a bottle-neck
+ if (type is! InterfaceType) {
+ return null;
+ }
+ // new names to match up with the spec
+ InterfaceType i = this;
+ InterfaceType j = type as InterfaceType;
+ // compute set of supertypes
+ Set<InterfaceType> si = computeSuperinterfaceSet(i);
+ Set<InterfaceType> sj = computeSuperinterfaceSet(j);
+ // union si with i and sj with j
+ si.add(i);
+ sj.add(j);
+ // compute intersection, reference as set 's'
+ List<InterfaceType> s = _intersection(si, sj);
+ // for each element in Set s, compute the largest inheritance path to Object
+ List<int> depths = new List<int>.filled(s.length, 0);
+ int maxDepth = 0;
+ for (int n = 0; n < s.length; n++) {
+ depths[n] = computeLongestInheritancePathToObject(s[n]);
+ if (depths[n] > maxDepth) {
+ maxDepth = depths[n];
+ }
+ }
+ // ensure that the currently computed maxDepth is unique,
+ // otherwise, decrement and test for uniqueness again
+ for (; maxDepth >= 0; maxDepth--) {
+ int indexOfLeastUpperBound = -1;
+ int numberOfTypesAtMaxDepth = 0;
+ for (int m = 0; m < depths.length; m++) {
+ if (depths[m] == maxDepth) {
+ numberOfTypesAtMaxDepth++;
+ indexOfLeastUpperBound = m;
+ }
+ }
+ if (numberOfTypesAtMaxDepth == 1) {
+ return s[indexOfLeastUpperBound];
+ }
+ }
+ // illegal state, log and return null- Object at maxDepth == 0 should always return itself as
+ // the least upper bound.
+ // TODO (jwren) log the error state
+ return null;
}
@override
- String get identifier => "${super.identifier}@${nameOffset}";
-}
-
-/**
- * Instances of the class `MethodElementImpl` implement a `MethodElement`.
- */
-class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
- /**
- * An empty array of method elements.
- */
- static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>(0);
-
- /**
- * Initialize a newly created method element to have the given name.
- *
- * @param name the name of this element
- */
- MethodElementImpl.forNode(Identifier name) : super.forNode(name);
-
- /**
- * Initialize a newly created method element to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
- */
- MethodElementImpl(String name, int nameOffset) : super(name, nameOffset);
+ MethodElement getMethod(String methodName) => MethodMember.from((element as ClassElementImpl).getMethod(methodName), this);
@override
- accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
+ List<MethodElement> get methods {
+ List<MethodElement> methods = element.methods;
+ List<MethodElement> members = new List<MethodElement>(methods.length);
+ for (int i = 0; i < methods.length; i++) {
+ members[i] = MethodMember.from(methods[i], this);
+ }
+ return members;
+ }
@override
- String get displayName {
- String displayName = super.displayName;
- if ("unary-" == displayName) {
- return "-";
+ List<InterfaceType> get mixins {
+ ClassElement classElement = element;
+ List<InterfaceType> mixins = classElement.mixins;
+ List<TypeParameterElement> typeParameters = classElement.typeParameters;
+ List<DartType> parameterTypes = classElement.type.typeArguments;
+ if (typeParameters.length == 0) {
+ return mixins;
+ }
+ int count = mixins.length;
+ List<InterfaceType> typedMixins = new List<InterfaceType>(count);
+ for (int i = 0; i < count; i++) {
+ typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes);
}
- return displayName;
+ return typedMixins;
}
@override
- ClassElement get enclosingElement => super.enclosingElement as ClassElement;
-
- @override
- ElementKind get kind => ElementKind.METHOD;
+ PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember.from((element as ClassElementImpl).getSetter(setterName), this);
@override
- String get name {
- String name = super.name;
- if (isOperator && name == "-") {
- if (parameters.length == 0) {
- return "unary-";
- }
+ InterfaceType get superclass {
+ ClassElement classElement = element;
+ InterfaceType supertype = classElement.supertype;
+ if (supertype == null) {
+ return null;
}
- return super.name;
+ return supertype.substitute2(typeArguments, classElement.type.typeArguments);
}
@override
- MethodDeclaration get node => getNodeMatching((node) => node is MethodDeclaration);
-
- @override
- bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+ List<TypeParameterElement> get typeParameters => element.typeParameters;
@override
- bool get isOperator {
- String name = displayName;
- if (name.isEmpty) {
- return false;
+ int get hashCode {
+ ClassElement element = this.element;
+ if (element == null) {
+ return 0;
}
- int first = name.codeUnitAt(0);
- return !((0x61 <= first && first <= 0x7A) || (0x41 <= first && first <= 0x5A) || first == 0x5F || first == 0x24);
+ return element.hashCode;
}
@override
- bool get isStatic => hasModifier(Modifier.STATIC);
-
- /**
- * Set whether this method is abstract to correspond to the given value.
- *
- * @param isAbstract `true` if the method is abstract
- */
- void set abstract(bool isAbstract) {
- setModifier(Modifier.ABSTRACT, isAbstract);
- }
-
- /**
- * Set whether this method is static to correspond to the given value.
- *
- * @param isStatic `true` if the method is static
- */
- void set static(bool isStatic) {
- setModifier(Modifier.STATIC, isStatic);
+ bool get isDartCoreFunction {
+ ClassElement element = this.element;
+ if (element == null) {
+ return false;
+ }
+ return element.name == "Function" && element.library.isDartCore;
}
@override
- void appendTo(JavaStringBuilder builder) {
- builder.append(enclosingElement.displayName);
- builder.append(".");
- builder.append(displayName);
- super.appendTo(builder);
- }
-}
-
-/**
- * The enumeration `Modifier` defines constants for all of the modifiers defined by the Dart
- * language and for a few additional flags that are useful.
- */
-class Modifier extends Enum<Modifier> {
- /**
- * Indicates that the modifier 'abstract' was applied to the element.
- */
- static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0);
-
- /**
- * Indicates that the modifier 'const' was applied to the element.
- */
- static const Modifier CONST = const Modifier('CONST', 1);
-
- /**
- * Indicates that the import element represents a deferred library.
- */
- static const Modifier DEFERRED = const Modifier('DEFERRED', 2);
-
- /**
- * Indicates that the modifier 'factory' was applied to the element.
- */
- static const Modifier FACTORY = const Modifier('FACTORY', 3);
-
- /**
- * Indicates that the modifier 'final' was applied to the element.
- */
- static const Modifier FINAL = const Modifier('FINAL', 4);
-
- /**
- * Indicates that the pseudo-modifier 'get' was applied to the element.
- */
- static const Modifier GETTER = const Modifier('GETTER', 5);
-
- /**
- * 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', 6);
-
- static const Modifier MIXIN = const Modifier('MIXIN', 7);
-
- static const Modifier REFERENCES_SUPER = const Modifier('REFERENCES_SUPER', 8);
-
- /**
- * Indicates that the pseudo-modifier 'set' was applied to the element.
- */
- static const Modifier SETTER = const Modifier('SETTER', 9);
-
- /**
- * Indicates that the modifier 'static' was applied to the element.
- */
- static const Modifier STATIC = const Modifier('STATIC', 10);
-
- /**
- * 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', 11);
-
- static const Modifier TYPEDEF = const Modifier('TYPEDEF', 12);
-
- static const List<Modifier> values = const [
- ABSTRACT,
- CONST,
- DEFERRED,
- FACTORY,
- FINAL,
- GETTER,
- HAS_EXT_URI,
- MIXIN,
- REFERENCES_SUPER,
- SETTER,
- STATIC,
- SYNTHETIC,
- TYPEDEF];
-
- const Modifier(String name, int ordinal) : super(name, ordinal);
-}
-
-/**
- * Instances of the class `MultiplyDefinedElementImpl` represent a collection of elements that
- * have the same name within the same scope.
- */
-class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
- /**
- * Return an element that represents the given conflicting elements.
- *
- * @param context the analysis context in which the multiply defined elements are defined
- * @param firstElement the first element that conflicts
- * @param secondElement the second element that conflicts
- */
- static Element fromElements(AnalysisContext context, Element firstElement, Element secondElement) {
- List<Element> conflictingElements = _computeConflictingElements(firstElement, secondElement);
- int length = conflictingElements.length;
- if (length == 0) {
- return null;
- } else if (length == 1) {
- return conflictingElements[0];
+ bool isDirectSupertypeOf(InterfaceType type) {
+ InterfaceType i = this;
+ InterfaceType j = type;
+ ClassElement jElement = j.element;
+ InterfaceType supertype = jElement.supertype;
+ //
+ // If J has no direct supertype then it is Object, and Object has no direct supertypes.
+ //
+ if (supertype == null) {
+ return false;
}
- return new MultiplyDefinedElementImpl(context, conflictingElements);
- }
-
- /**
- * Add the given element to the list of elements. If the element is a multiply-defined element,
- * add all of the conflicting elements that it represents.
- *
- * @param elements the list to which the element(s) are to be added
- * @param element the element(s) to be added
- */
- static void _add(Set<Element> elements, Element element) {
- if (element is MultiplyDefinedElementImpl) {
- for (Element conflictingElement in element.conflictingElements) {
- elements.add(conflictingElement);
- }
- } else {
- elements.add(element);
+ //
+ // I is listed in the extends clause of J.
+ //
+ List<DartType> jArgs = j.typeArguments;
+ List<DartType> jVars = jElement.type.typeArguments;
+ supertype = supertype.substitute2(jArgs, jVars);
+ if (supertype == i) {
+ return true;
}
- }
-
- /**
- * Use the given elements to construct an array of conflicting elements. If either of the given
- * elements are multiply-defined elements then the conflicting elements they represent will be
- * included in the array. Otherwise, the element itself will be included.
- *
- * @param firstElement the first element to be included
- * @param secondElement the second element to be included
- * @return an array containing all of the conflicting elements
- */
- static List<Element> _computeConflictingElements(Element firstElement, Element secondElement) {
- Set<Element> elements = new Set<Element>();
- _add(elements, firstElement);
- _add(elements, secondElement);
- return new List.from(elements);
- }
-
- /**
- * 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 that conflict.
- */
- final List<Element> conflictingElements;
-
- /**
- * Initialize a newly created element to represent a list of conflicting elements.
- *
- * @param context the analysis context in which the multiply defined elements are defined
- * @param conflictingElements the elements that conflict
- */
- MultiplyDefinedElementImpl(this.context, this.conflictingElements) {
- _name = conflictingElements[0].name;
+ //
+ // I is listed in the implements clause of J.
+ //
+ for (InterfaceType interfaceType in jElement.interfaces) {
+ interfaceType = interfaceType.substitute2(jArgs, jVars);
+ if (interfaceType == i) {
+ return true;
+ }
+ }
+ //
+ // I is listed in the with clause of J.
+ //
+ for (InterfaceType mixinType in jElement.mixins) {
+ mixinType = mixinType.substitute2(jArgs, jVars);
+ if (mixinType == i) {
+ return true;
+ }
+ }
+ //
+ // J is a mixin application of the mixin of I.
+ //
+ // TODO(brianwilkerson) Determine whether this needs to be implemented or whether it is covered
+ // by the case above.
+ return false;
}
@override
- accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this);
-
- @override
- String computeDocumentationComment() => null;
+ bool get isObject => element.supertype == null;
@override
- Element getAncestor(Predicate<Element> predicate) => null;
+ ConstructorElement lookUpConstructor(String constructorName, LibraryElement library) {
+ // prepare base ConstructorElement
+ ConstructorElement constructorElement;
+ if (constructorName == null) {
+ constructorElement = element.unnamedConstructor;
+ } else {
+ constructorElement = element.getNamedConstructor(constructorName);
+ }
+ // not found or not accessible
+ if (constructorElement == null || !constructorElement.isAccessibleIn(library)) {
+ return null;
+ }
+ // return member
+ return ConstructorMember.from(constructorElement, this);
+ }
@override
- String get displayName => _name;
+ PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library) {
+ PropertyAccessorElement element = getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ return lookUpGetterInSuperclass(getterName, library);
+ }
@override
- Element get enclosingElement => null;
+ PropertyAccessorElement lookUpGetterInSuperclass(String getterName, LibraryElement library) {
+ for (InterfaceType mixin in mixins) {
+ PropertyAccessorElement element = mixin.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ Set<ClassElement> visitedClasses = new Set<ClassElement>();
+ InterfaceType supertype = superclass;
+ ClassElement supertypeElement = supertype == null ? null : supertype.element;
+ while (supertype != null && !visitedClasses.contains(supertypeElement)) {
+ visitedClasses.add(supertypeElement);
+ PropertyAccessorElement element = supertype.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ for (InterfaceType mixin in supertype.mixins) {
+ element = mixin.getGetter(getterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ supertype = supertype.superclass;
+ supertypeElement = supertype == null ? null : supertype.element;
+ }
+ return null;
+ }
@override
- ElementKind get kind => ElementKind.ERROR;
+ MethodElement lookUpMethod(String methodName, LibraryElement library) {
+ MethodElement element = getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ return lookUpMethodInSuperclass(methodName, library);
+ }
@override
- LibraryElement get library => null;
+ MethodElement lookUpMethodInSuperclass(String methodName, LibraryElement library) {
+ for (InterfaceType mixin in mixins) {
+ MethodElement element = mixin.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ Set<ClassElement> visitedClasses = new Set<ClassElement>();
+ InterfaceType supertype = superclass;
+ ClassElement supertypeElement = supertype == null ? null : supertype.element;
+ while (supertype != null && !visitedClasses.contains(supertypeElement)) {
+ visitedClasses.add(supertypeElement);
+ MethodElement element = supertype.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ for (InterfaceType mixin in supertype.mixins) {
+ element = mixin.getMethod(methodName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ supertype = supertype.superclass;
+ supertypeElement = supertype == null ? null : supertype.element;
+ }
+ return null;
+ }
@override
- ElementLocation get location => null;
+ PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library) {
+ PropertyAccessorElement element = getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ return lookUpSetterInSuperclass(setterName, library);
+ }
@override
- List<ElementAnnotation> get metadata => ElementAnnotationImpl.EMPTY_ARRAY;
+ PropertyAccessorElement lookUpSetterInSuperclass(String setterName, LibraryElement library) {
+ for (InterfaceType mixin in mixins) {
+ PropertyAccessorElement element = mixin.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ Set<ClassElement> visitedClasses = new Set<ClassElement>();
+ InterfaceType supertype = superclass;
+ ClassElement supertypeElement = supertype == null ? null : supertype.element;
+ while (supertype != null && !visitedClasses.contains(supertypeElement)) {
+ visitedClasses.add(supertypeElement);
+ PropertyAccessorElement element = supertype.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ for (InterfaceType mixin in supertype.mixins) {
+ element = mixin.getSetter(setterName);
+ if (element != null && element.isAccessibleIn(library)) {
+ return element;
+ }
+ }
+ supertype = supertype.superclass;
+ supertypeElement = supertype == null ? null : supertype.element;
+ }
+ return null;
+ }
@override
- String get name => _name;
+ InterfaceTypeImpl substitute4(List<DartType> argumentTypes) => substitute2(argumentTypes, typeArguments);
@override
- int get nameOffset => -1;
+ InterfaceTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
+ if (argumentTypes.length != parameterTypes.length) {
+ throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
+ }
+ if (argumentTypes.length == 0 || typeArguments.length == 0) {
+ return this;
+ }
+ List<DartType> newTypeArguments = TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
+ if (JavaArrays.equals(newTypeArguments, typeArguments)) {
+ return this;
+ }
+ InterfaceTypeImpl newType = new InterfaceTypeImpl.con1(element);
+ newType.typeArguments = newTypeArguments;
+ return newType;
+ }
@override
- AstNode get node => null;
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(name);
+ int argumentCount = typeArguments.length;
+ if (argumentCount > 0) {
+ builder.append("<");
+ for (int i = 0; i < argumentCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ (typeArguments[i] as TypeImpl).appendTo(builder);
+ }
+ builder.append(">");
+ }
+ }
@override
- Source get source => null;
+ bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) {
+ if (object is! InterfaceTypeImpl) {
+ return false;
+ }
+ InterfaceTypeImpl otherType = object as InterfaceTypeImpl;
+ return (element == otherType.element) && TypeImpl.equalArrays(typeArguments, otherType.typeArguments, visitedElementPairs);
+ }
@override
- DartType get type => DynamicTypeImpl.instance;
+ bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // S is dynamic.
+ // The test to determine whether S is dynamic is done here because dynamic is not an instance of
+ // InterfaceType.
+ //
+ if (identical(type, DynamicTypeImpl.instance)) {
+ return true;
+ } else if (type is! InterfaceType) {
+ return false;
+ }
+ return _isMoreSpecificThan(type as InterfaceType, new Set<ClassElement>(), withDynamic, visitedTypePairs);
+ }
@override
- CompilationUnit get unit => null;
+ bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S
+ //
+ if (type.isDynamic) {
+ return true;
+ } else if (type is TypeParameterType) {
+ return false;
+ } else if (type is FunctionType) {
+ ClassElement element = this.element;
+ MethodElement callMethod = element.lookUpMethod("call", element.library);
+ if (callMethod != null) {
+ return callMethod.type.isSubtypeOf(type);
+ }
+ return false;
+ } else if (type is! InterfaceType) {
+ return false;
+ } else if (this == type) {
+ return true;
+ }
+ return _isSubtypeOf(type as InterfaceType, new Set<ClassElement>(), visitedTypePairs);
+ }
- @override
- bool isAccessibleIn(LibraryElement library) {
- for (Element element in conflictingElements) {
- if (element.isAccessibleIn(library)) {
+ bool _isMoreSpecificThan(InterfaceType s, Set<ClassElement> visitedClasses, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // A type T is more specific than a type S, written T << S, if one of the following conditions
+ // is met:
+ //
+ // Reflexivity: T is S.
+ //
+ if (this == s) {
+ return true;
+ }
+ //
+ // T is bottom. (This case is handled by the class BottomTypeImpl.)
+ //
+ // Direct supertype: S is a direct supertype of T.
+ //
+ if (s.isDirectSupertypeOf(this)) {
+ return true;
+ }
+ //
+ // Covariance: T is of the form I<T1, ..., Tn> and S is of the form I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
+ //
+ ClassElement tElement = this.element;
+ ClassElement sElement = s.element;
+ if (tElement == sElement) {
+ List<DartType> tArguments = typeArguments;
+ List<DartType> sArguments = s.typeArguments;
+ if (tArguments.length != sArguments.length) {
+ return false;
+ }
+ for (int i = 0; i < tArguments.length; i++) {
+ if (!(tArguments[i] as TypeImpl).isMoreSpecificThan2(sArguments[i], withDynamic, visitedTypePairs)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ //
+ // Transitivity: T << U and U << S.
+ //
+ // First check for infinite loops
+ ClassElement element = this.element;
+ if (element == null || visitedClasses.contains(element)) {
+ return false;
+ }
+ visitedClasses.add(element);
+ // Iterate over all of the types U that are more specific than T because they are direct
+ // supertypes of T and return true if any of them are more specific than S.
+ InterfaceType supertype = superclass;
+ if (supertype != null && (supertype as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses, withDynamic, visitedTypePairs)) {
+ return true;
+ }
+ for (InterfaceType interfaceType in interfaces) {
+ if ((interfaceType as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses, withDynamic, visitedTypePairs)) {
+ return true;
+ }
+ }
+ for (InterfaceType mixinType in mixins) {
+ if ((mixinType as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses, withDynamic, visitedTypePairs)) {
return true;
}
}
return false;
}
- @override
- bool get isDeprecated => false;
-
- @override
- bool get isOverride => false;
-
- @override
- bool get isPrivate {
- String name = displayName;
- if (name == null) {
+ bool _isSubtypeOf(InterfaceType type, Set<ClassElement> visitedClasses, Set<TypeImpl_TypePair> visitedTypePairs) {
+ InterfaceType typeT = this;
+ InterfaceType typeS = type;
+ ClassElement elementT = element;
+ if (elementT == null || visitedClasses.contains(elementT)) {
return false;
}
- return Identifier.isPrivateName(name);
+ visitedClasses.add(elementT);
+ if (typeT == typeS) {
+ return true;
+ } else if (elementT == typeS.element) {
+ // For each of the type arguments return true if all type args from T is a subtype of all
+ // types from S.
+ List<DartType> typeTArgs = typeT.typeArguments;
+ List<DartType> typeSArgs = typeS.typeArguments;
+ if (typeTArgs.length != typeSArgs.length) {
+ // This case covers the case where two objects are being compared that have a different
+ // number of parameterized types.
+ return false;
+ }
+ for (int i = 0; i < typeTArgs.length; i++) {
+ // Recursively call isSubtypeOf the type arguments and return false if the T argument is not
+ // a subtype of the S argument.
+ if (!(typeTArgs[i] as TypeImpl).isSubtypeOf2(typeSArgs[i], visitedTypePairs)) {
+ return false;
+ }
+ }
+ return true;
+ } else if (typeS.isDartCoreFunction && elementT.getMethod("call") != null) {
+ return true;
+ }
+ InterfaceType supertype = superclass;
+ // The type is Object, return false.
+ if (supertype != null && (supertype as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, visitedTypePairs)) {
+ return true;
+ }
+ List<InterfaceType> interfaceTypes = interfaces;
+ for (InterfaceType interfaceType in interfaceTypes) {
+ if ((interfaceType as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, visitedTypePairs)) {
+ return true;
+ }
+ }
+ List<InterfaceType> mixinTypes = mixins;
+ for (InterfaceType mixinType in mixinTypes) {
+ if ((mixinType as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, visitedTypePairs)) {
+ return true;
+ }
+ }
+ return false;
}
+}
- @override
- bool get isPublic => !isPrivate;
+/**
+ * Combination of [AngularTagSelectorElementImpl] and [HasAttributeSelectorElementImpl].
+ */
+class IsTagHasAttributeSelectorElementImpl extends AngularSelectorElementImpl {
+ final String tagName;
- @override
- bool get isSynthetic => true;
+ final String attributeName;
- @override
- String toString() {
- JavaStringBuilder builder = new JavaStringBuilder();
- builder.append("[");
- int count = conflictingElements.length;
- for (int i = 0; i < count; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- (conflictingElements[i] as ElementImpl).appendTo(builder);
- }
- builder.append("]");
- return builder.toString();
- }
+ IsTagHasAttributeSelectorElementImpl(this.tagName, this.attributeName) : super(null, -1);
@override
- void visitChildren(ElementVisitor visitor) {
- }
+ bool apply(XmlTagNode node) => node.tag == tagName && node.getAttribute(attributeName) != null;
}
/**
- * The interface [MultiplyInheritedMethodElementImpl] defines all of the behavior of an
- * [MethodElementImpl], with the additional information of an array of
- * [ExecutableElement]s from which this element was composed.
+ * The interface `LabelElement` defines the behavior of elements representing a label
+ * associated with a statement.
*/
-class MultiplyInheritedMethodElementImpl extends MethodElementImpl implements MultiplyInheritedExecutableElement {
+abstract class LabelElement implements Element {
/**
- * An array the array of executable elements that were used to compose this element.
+ * Return the executable element in which this label is defined.
+ *
+ * @return the executable element in which this label is defined
*/
- List<ExecutableElement> _elements = MethodElementImpl.EMPTY_ARRAY;
-
- MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) {
- synthetic = true;
- }
-
@override
- List<ExecutableElement> get inheritedElements => _elements;
-
- void set inheritedElements(List<ExecutableElement> elements) {
- this._elements = elements;
- }
+ ExecutableElement get enclosingElement;
}
/**
- * The interface [MultiplyInheritedPropertyAccessorElementImpl] defines all of the behavior of
- * an [PropertyAccessorElementImpl], with the additional information of an array of
- * [ExecutableElement]s from which this element was composed.
+ * Instances of the class `LabelElementImpl` implement a `LabelElement`.
*/
-class MultiplyInheritedPropertyAccessorElementImpl extends PropertyAccessorElementImpl implements MultiplyInheritedExecutableElement {
+class LabelElementImpl extends ElementImpl implements LabelElement {
/**
- * An array the array of executable elements that were used to compose this element.
+ * A flag indicating whether this label is associated with a `switch` statement.
*/
- List<ExecutableElement> _elements = PropertyAccessorElementImpl.EMPTY_ARRAY;
+ final bool _onSwitchStatement;
- MultiplyInheritedPropertyAccessorElementImpl(Identifier name) : super.forNode(name) {
- synthetic = true;
- }
+ /**
+ * A flag indicating whether this label is associated with a `switch` member (`case`
+ * or `default`).
+ */
+ final bool _onSwitchMember;
+
+ /**
+ * An empty array of label elements.
+ */
+ static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>(0);
+
+ /**
+ * Initialize a newly created label element to have the given name.
+ *
+ * @param name the name of this element
+ * @param onSwitchStatement `true` if this label is associated with a `switch`
+ * statement
+ * @param onSwitchMember `true` if this label is associated with a `switch` member
+ */
+ LabelElementImpl(Identifier name, this._onSwitchStatement, this._onSwitchMember) : super.forNode(name);
@override
- List<ExecutableElement> get inheritedElements => _elements;
+ accept(ElementVisitor visitor) => visitor.visitLabelElement(this);
- void set inheritedElements(List<ExecutableElement> elements) {
- this._elements = elements;
- }
+ @override
+ ExecutableElement get enclosingElement => super.enclosingElement as ExecutableElement;
+
+ @override
+ ElementKind get kind => ElementKind.LABEL;
+
+ /**
+ * Return `true` if this label is associated with a `switch` member (`case` or
+ * `default`).
+ *
+ * @return `true` if this label is associated with a `switch` member
+ */
+ bool get isOnSwitchMember => _onSwitchMember;
+
+ /**
+ * Return `true` if this label is associated with a `switch` statement.
+ *
+ * @return `true` if this label is associated with a `switch` statement
+ */
+ bool get isOnSwitchStatement => _onSwitchStatement;
}
/**
- * Instances of the class `ParameterElementImpl` implement a `ParameterElement`.
+ * The interface `LibraryElement` defines the behavior of elements representing a library.
*/
-class ParameterElementImpl extends VariableElementImpl implements ParameterElement {
+abstract class LibraryElement implements Element {
/**
- * Is `true` if this variable is potentially mutated somewhere in its scope.
+ * Return the compilation unit that defines this library.
+ *
+ * @return the compilation unit that defines this library
*/
- bool _potentiallyMutatedInScope = false;
+ CompilationUnitElement get definingCompilationUnit;
/**
- * Is `true` if this variable is potentially mutated somewhere in closure.
+ * Return the entry point for this library, or `null` if this library does not have an entry
+ * point. The entry point is defined to be a zero argument top-level function whose name is
+ * `main`.
+ *
+ * @return the entry point for this library
*/
- bool _potentiallyMutatedInClosure = false;
+ FunctionElement get entryPoint;
/**
- * An array containing all of the parameters defined by this parameter element. There will only be
- * parameters if this parameter is a function typed parameter.
+ * Return an array containing all of the libraries that are exported from this library.
+ *
+ * @return an array containing all of the libraries that are exported from this library
*/
- List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
+ List<LibraryElement> get exportedLibraries;
/**
- * The kind of this parameter.
+ * Return an array containing all of the exports defined in this library.
+ *
+ * @return the exports defined in this library
*/
- ParameterKind parameterKind;
+ List<ExportElement> get exports;
/**
- * The offset to the beginning of the default value range for this element.
+ * Return an array containing all of the libraries that are imported into this library. This
+ * includes all of the libraries that are imported using a prefix (also available through the
+ * prefixes returned by [getPrefixes]) and those that are imported without a prefix.
+ *
+ * @return an array containing all of the libraries that are imported into this library
*/
- int _defaultValueRangeOffset = 0;
+ List<LibraryElement> get importedLibraries;
/**
- * The length of the default value range for this element, or `-1` if this element does not
- * have a default value.
+ * Return an array containing all of the imports defined in this library.
+ *
+ * @return the imports defined in this library
*/
- int _defaultValueRangeLength = -1;
+ List<ImportElement> get imports;
+
+ /**
+ * Return an array containing all of the imports that share the given prefix, or an empty array if
+ * there are no such imports.
+ *
+ * @param prefixElement the prefix element shared by the returned imports
+ */
+ List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement);
+
+ /**
+ * Return the element representing the synthetic function `loadLibrary` that is implicitly
+ * defined for this library if the library is imported using a deferred import.
+ */
+ FunctionElement get loadLibraryFunction;
/**
- * The offset to the beginning of the visible range for this element.
+ * Return an array containing all of the compilation units that are included in this library using
+ * a `part` directive. This does not include the defining compilation unit that contains the
+ * `part` directives.
+ *
+ * @return the compilation units that are included in this library
*/
- int _visibleRangeOffset = 0;
+ List<CompilationUnitElement> get parts;
/**
- * The length of the visible range for this element, or `-1` if this element does not have a
- * visible range.
+ * Return an array containing elements for each of the prefixes used to `import` libraries
+ * into this library. Each prefix can be used in more than one `import` directive.
+ *
+ * @return the prefixes used to `import` libraries into this library
*/
- int _visibleRangeLength = -1;
+ List<PrefixElement> get prefixes;
/**
- * An empty array of field elements.
+ * Return the class defined in this library that has the given name, or `null` if this
+ * library does not define a class with the given name.
+ *
+ * @param className the name of the class to be returned
+ * @return the class with the given name that is defined in this library
*/
- static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>(0);
+ ClassElement getType(String className);
/**
- * Initialize a newly created parameter element to have the given name.
+ * Return an array containing all of the compilation units this library consists of. This includes
+ * the defining compilation unit and units included using the `part` directive.
*
- * @param name the name of this element
+ * @return the compilation units this library consists of
*/
- ParameterElementImpl.con1(Identifier name) : super.forNode(name);
+ List<CompilationUnitElement> get units;
/**
- * Initialize a newly created parameter element to have the given name.
+ * Return an array containing all directly and indirectly imported libraries.
*
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * @return all directly and indirectly imported libraries
*/
- ParameterElementImpl.con2(String name, int nameOffset) : super(name, nameOffset);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
-
- @override
- SourceRange get defaultValueRange {
- if (_defaultValueRangeLength < 0) {
- return null;
- }
- return new SourceRange(_defaultValueRangeOffset, _defaultValueRangeLength);
- }
-
- @override
- ElementKind get kind => ElementKind.PARAMETER;
-
- @override
- List<ParameterElement> get parameters => _parameters;
-
- @override
- SourceRange get visibleRange {
- if (_visibleRangeLength < 0) {
- return null;
- }
- return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
- }
-
- @override
- bool get isInitializingFormal => false;
-
- @override
- bool get isPotentiallyMutatedInClosure => _potentiallyMutatedInClosure;
-
- @override
- bool get isPotentiallyMutatedInScope => _potentiallyMutatedInScope;
+ List<LibraryElement> get visibleLibraries;
/**
- * Specifies that this variable is potentially mutated somewhere in closure.
+ * Return `true` if the defining compilation unit of this library contains at least one
+ * import directive whose URI uses the "dart-ext" scheme.
*/
- void markPotentiallyMutatedInClosure() {
- _potentiallyMutatedInClosure = true;
- }
+ bool get hasExtUri;
/**
- * Specifies that this variable is potentially mutated somewhere in its scope.
+ * Return `true` if this library defines a top-level function named `loadLibrary`.
+ *
+ * @return `true` if this library defines a top-level function named `loadLibrary`
*/
- void markPotentiallyMutatedInScope() {
- _potentiallyMutatedInScope = true;
- }
+ bool get hasLoadLibraryFunction;
/**
- * Set the range of the default value for this parameter to the range starting at the given offset
- * with the given length.
+ * Return `true` if this library is created for Angular analysis. If this library has not
+ * yet had toolkit references resolved, then `false` will be returned.
*
- * @param offset the offset to the beginning of the default value range for this element
- * @param length the length of the default value range for this element, or `-1` if this
- * element does not have a default value
+ * @return `true` if this library is created for Angular analysis
*/
- void setDefaultValueRange(int offset, int length) {
- _defaultValueRangeOffset = offset;
- _defaultValueRangeLength = length;
- }
+ bool get isAngularHtml;
/**
- * Set the parameters defined by this executable element to the given parameters.
+ * Return `true` if this library is an application that can be run in the browser.
*
- * @param parameters the parameters defined by this executable element
+ * @return `true` if this library is an application that can be run in the browser
*/
- void set parameters(List<ParameterElement> parameters) {
- for (ParameterElement parameter in parameters) {
- (parameter as ParameterElementImpl).enclosingElement = this;
- }
- this._parameters = parameters;
- }
+ bool get isBrowserApplication;
/**
- * Set the visible range for this element to the range starting at the given offset with the given
- * length.
+ * Return `true` if this library is the dart:core library.
*
- * @param offset the offset to the beginning of the visible range for this element
- * @param length the length of the visible range for this element, or `-1` if this element
- * does not have a visible range
+ * @return `true` if this library is the dart:core library
*/
- void setVisibleRange(int offset, int length) {
- _visibleRangeOffset = offset;
- _visibleRangeLength = length;
- }
-
- @override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChildren(_parameters, visitor);
- }
+ bool get isDartCore;
- @override
- void appendTo(JavaStringBuilder builder) {
- 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;
- }
- builder.append(left);
- appendToWithoutDelimiters(builder);
- builder.append(right);
- }
+ /**
+ * Return `true` if this library is the dart:core library.
+ *
+ * @return `true` if this library is the dart:core library
+ */
+ bool get isInSdk;
/**
- * Append the type and name of this parameter to the given builder.
+ * Return `true` if this library is up to date with respect to the given time stamp. If any
+ * transitively referenced Source is newer than the time stamp, this method returns false.
*
- * @param builder the builder to which the type and name are to be appended
+ * @param timeStamp the time stamp to compare against
+ * @return `true` if this library is up to date with respect to the given time stamp
*/
- void appendToWithoutDelimiters(JavaStringBuilder builder) {
- builder.append(type);
- builder.append(" ");
- builder.append(displayName);
- }
+ bool isUpToDate(int timeStamp);
}
/**
- * Instances of the class `PrefixElementImpl` implement a `PrefixElement`.
+ * Instances of the class `LibraryElementImpl` implement a `LibraryElement`.
*/
-class PrefixElementImpl extends ElementImpl implements PrefixElement {
+class LibraryElementImpl extends ElementImpl implements LibraryElement {
/**
- * An array containing all of the libraries that are imported using this prefix.
+ * An empty array of library elements.
*/
- List<LibraryElement> _importedLibraries = LibraryElementImpl.EMPTY_ARRAY;
+ static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>(0);
/**
- * An empty array of prefix elements.
+ * Determine if the given library is up to date with respect to the given time stamp.
+ *
+ * @param library the library to process
+ * @param timeStamp the time stamp to check against
+ * @param visitedLibraries the set of visited libraries
*/
- static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>(0);
+ static bool _safeIsUpToDate(LibraryElement library, int timeStamp, Set<LibraryElement> visitedLibraries) {
+ if (!visitedLibraries.contains(library)) {
+ visitedLibraries.add(library);
+ AnalysisContext context = library.context;
+ // Check the defining compilation unit.
+ if (timeStamp < context.getModificationStamp(library.definingCompilationUnit.source)) {
+ return false;
+ }
+ // Check the parted compilation units.
+ for (CompilationUnitElement element in library.parts) {
+ if (timeStamp < context.getModificationStamp(element.source)) {
+ return false;
+ }
+ }
+ // Check the imported libraries.
+ for (LibraryElement importedLibrary in library.importedLibraries) {
+ if (!_safeIsUpToDate(importedLibrary, timeStamp, visitedLibraries)) {
+ return false;
+ }
+ }
+ // Check the exported libraries.
+ for (LibraryElement exportedLibrary in library.exportedLibraries) {
+ if (!_safeIsUpToDate(exportedLibrary, timeStamp, visitedLibraries)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
/**
- * Initialize a newly created prefix element to have the given name.
- *
- * @param name the name of this element
+ * The analysis context in which this library is defined.
*/
- PrefixElementImpl(Identifier name) : super.forNode(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitPrefixElement(this);
-
- @override
- LibraryElement get enclosingElement => super.enclosingElement as LibraryElement;
-
- @override
- List<LibraryElement> get importedLibraries => _importedLibraries;
+ final AnalysisContext context;
- @override
- ElementKind get kind => ElementKind.PREFIX;
+ /**
+ * The compilation unit that defines this library.
+ */
+ CompilationUnitElement _definingCompilationUnit;
/**
- * Set the libraries that are imported using this prefix to the given libraries.
- *
- * @param importedLibraries the libraries that are imported using this prefix
+ * The entry point for this library, or `null` if this library does not have an entry point.
*/
- void set importedLibraries(List<LibraryElement> importedLibraries) {
- for (LibraryElement library in importedLibraries) {
- (library as LibraryElementImpl).enclosingElement = this;
- }
- this._importedLibraries = importedLibraries;
- }
+ FunctionElement entryPoint;
- @override
- void appendTo(JavaStringBuilder builder) {
- builder.append("as ");
- super.appendTo(builder);
- }
+ /**
+ * An array containing specifications of all of the imports defined in this library.
+ */
+ List<ImportElement> _imports = ImportElement.EMPTY_ARRAY;
- @override
- String get identifier => "_${super.identifier}";
-}
+ /**
+ * An array containing specifications of all of the exports defined in this library.
+ */
+ List<ExportElement> _exports = ExportElement.EMPTY_ARRAY;
-/**
- * Instances of the class `PropertyAccessorElementImpl` implement a
- * `PropertyAccessorElement`.
- */
-class PropertyAccessorElementImpl extends ExecutableElementImpl implements PropertyAccessorElement {
/**
- * The variable associated with this accessor.
+ * An array containing all of the compilation units that are included in this library using a
+ * `part` directive.
*/
- PropertyInducingElement variable;
+ List<CompilationUnitElement> _parts = CompilationUnitElementImpl.EMPTY_ARRAY;
/**
- * An empty array of property accessor elements.
+ * Is `true` if this library is created for Angular analysis.
*/
- static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorElement>(0);
+ bool _isAngularHtml = false;
/**
- * Initialize a newly created property accessor element to have the given name.
- *
- * @param name the name of this element
+ * The element representing the synthetic function `loadLibrary` that is defined for this
+ * library, or `null` if the element has not yet been created.
*/
- PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
+ FunctionElement _loadLibraryFunction;
/**
- * Initialize a newly created synthetic property accessor element to be associated with the given
- * variable.
+ * Initialize a newly created library element to have the given name.
*
- * @param variable the variable with which this access is associated
+ * @param context the analysis context in which the library is defined
+ * @param name the name of this element
*/
- PropertyAccessorElementImpl(PropertyInducingElementImpl variable) : super(variable.name, variable.nameOffset) {
- this.variable = variable;
- synthetic = true;
- }
+ LibraryElementImpl(this.context, LibraryIdentifier name) : super.forNode(name);
@override
- accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
+ accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);
@override
- bool operator ==(Object object) => super == object && isGetter == (object as PropertyAccessorElement).isGetter;
+ bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && _definingCompilationUnit == (object as LibraryElementImpl).definingCompilationUnit;
@override
- PropertyAccessorElement get correspondingGetter {
- if (isGetter || variable == null) {
- return null;
+ ElementImpl getChild(String identifier) {
+ if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier == identifier) {
+ return _definingCompilationUnit as CompilationUnitElementImpl;
}
- return variable.getter;
+ for (CompilationUnitElement part in _parts) {
+ if ((part as CompilationUnitElementImpl).identifier == identifier) {
+ return part as CompilationUnitElementImpl;
+ }
+ }
+ for (ImportElement importElement in _imports) {
+ if ((importElement as ImportElementImpl).identifier == identifier) {
+ return importElement as ImportElementImpl;
+ }
+ }
+ for (ExportElement exportElement in _exports) {
+ if ((exportElement as ExportElementImpl).identifier == identifier) {
+ return exportElement as ExportElementImpl;
+ }
+ }
+ return null;
}
@override
- PropertyAccessorElement get correspondingSetter {
- if (isSetter || variable == null) {
- return null;
- }
- return variable.setter;
- }
+ CompilationUnitElement get definingCompilationUnit => _definingCompilationUnit;
@override
- ElementKind get kind {
- if (isGetter) {
- return ElementKind.GETTER;
+ List<LibraryElement> get exportedLibraries {
+ Set<LibraryElement> libraries = new Set<LibraryElement>();
+ for (ExportElement element in _exports) {
+ LibraryElement library = element.exportedLibrary;
+ if (library != null) {
+ libraries.add(library);
+ }
}
- return ElementKind.SETTER;
+ return new List.from(libraries);
}
@override
- String get name {
- if (isSetter) {
- return "${super.name}=";
+ List<ExportElement> get exports => _exports;
+
+ @override
+ List<LibraryElement> get importedLibraries {
+ Set<LibraryElement> libraries = new Set<LibraryElement>();
+ for (ImportElement element in _imports) {
+ LibraryElement library = element.importedLibrary;
+ if (library != null) {
+ libraries.add(library);
+ }
}
- return super.name;
+ return new List.from(libraries);
}
@override
- AstNode get node {
- if (isSynthetic) {
- return null;
- }
- if (enclosingElement is ClassElement) {
- return getNodeMatching((node) => node is MethodDeclaration);
- }
- if (enclosingElement is CompilationUnitElement) {
- return getNodeMatching((node) => node is FunctionDeclaration);
+ List<ImportElement> get imports => _imports;
+
+ @override
+ List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) {
+ 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 null;
+ return new List.from(importList);
}
@override
- int get hashCode => ObjectUtilities.combineHashCodes(super.hashCode, isGetter ? 1 : 2);
+ ElementKind get kind => ElementKind.LIBRARY;
@override
- bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+ LibraryElement get library => this;
@override
- bool get isGetter => hasModifier(Modifier.GETTER);
+ FunctionElement get loadLibraryFunction {
+ if (_loadLibraryFunction == null) {
+ FunctionElementImpl function = new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1);
+ function.synthetic = true;
+ function.enclosingElement = this;
+ function.returnType = loadLibraryReturnType;
+ function.type = new FunctionTypeImpl.con1(function);
+ _loadLibraryFunction = function;
+ }
+ return _loadLibraryFunction;
+ }
@override
- bool get isSetter => hasModifier(Modifier.SETTER);
+ List<CompilationUnitElement> get parts => _parts;
@override
- bool get isStatic => hasModifier(Modifier.STATIC);
+ List<PrefixElement> get prefixes {
+ Set<PrefixElement> prefixes = new Set<PrefixElement>();
+ for (ImportElement element in _imports) {
+ PrefixElement prefix = element.prefix;
+ if (prefix != null) {
+ prefixes.add(prefix);
+ }
+ }
+ return new List.from(prefixes);
+ }
- /**
- * Set whether this accessor is abstract to correspond to the given value.
- *
- * @param isAbstract `true` if the accessor is abstract
- */
- void set abstract(bool isAbstract) {
- setModifier(Modifier.ABSTRACT, isAbstract);
+ @override
+ Source get source {
+ if (_definingCompilationUnit == null) {
+ return null;
+ }
+ return _definingCompilationUnit.source;
}
- /**
- * Set whether this accessor is a getter to correspond to the given value.
- *
- * @param isGetter `true` if the accessor is a getter
- */
- void set getter(bool isGetter) {
- setModifier(Modifier.GETTER, isGetter);
+ @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;
}
- /**
- * Set whether this accessor is a setter to correspond to the given value.
- *
- * @param isSetter `true` if the accessor is a setter
- */
- void set setter(bool isSetter) {
- setModifier(Modifier.SETTER, isSetter);
+ @override
+ List<CompilationUnitElement> get units {
+ List<CompilationUnitElement> units = new List<CompilationUnitElement>(1 + _parts.length);
+ units[0] = _definingCompilationUnit;
+ JavaSystem.arraycopy(_parts, 0, units, 1, _parts.length);
+ return units;
}
- /**
- * Set whether this accessor is static to correspond to the given value.
- *
- * @param isStatic `true` if the accessor is static
- */
- void set static(bool isStatic) {
- setModifier(Modifier.STATIC, isStatic);
+ @override
+ List<LibraryElement> get visibleLibraries {
+ Set<LibraryElement> visibleLibraries = new Set();
+ _addVisibleLibraries(visibleLibraries, false);
+ return new List.from(visibleLibraries);
}
@override
- void appendTo(JavaStringBuilder builder) {
- builder.append(isGetter ? "get " : "set ");
- builder.append(variable.displayName);
- super.appendTo(builder);
+ bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI);
+
+ @override
+ int get hashCode => _definingCompilationUnit.hashCode;
+
+ @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;
}
-}
-/**
- * Instances of the class `PropertyInducingElementImpl` implement a
- * `PropertyInducingElement`.
- */
-abstract class PropertyInducingElementImpl extends VariableElementImpl implements PropertyInducingElement {
- /**
- * The getter associated with this element.
- */
- PropertyAccessorElement getter;
+ @override
+ bool get isAngularHtml => _isAngularHtml;
- /**
- * 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;
+ @override
+ bool get isBrowserApplication => entryPoint != null && isOrImportsBrowserLibrary;
- /**
- * An empty array of elements.
- */
- static List<PropertyInducingElement> EMPTY_ARRAY = new List<PropertyInducingElement>(0);
+ @override
+ bool get isDartCore => name == "dart.core";
- /**
- * Initialize a newly created element to have the given name.
- *
- * @param name the name of this element
- */
- PropertyInducingElementImpl.con1(Identifier name) : super.forNode(name);
+ @override
+ bool get isInSdk => StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E);
- /**
- * Initialize a newly created synthetic element to have the given name.
- *
- * @param name the name of this element
- */
- PropertyInducingElementImpl.con2(String name) : super(name, -1) {
- synthetic = true;
+ @override
+ bool isUpToDate(int timeStamp) {
+ Set<LibraryElement> visitedLibraries = new Set();
+ return _safeIsUpToDate(this, timeStamp, visitedLibraries);
}
-}
-/**
- * Instances of the class `ShowElementCombinatorImpl` implement a
- * [ShowElementCombinator].
- */
-class ShowElementCombinatorImpl implements ShowElementCombinator {
/**
- * The names that are to be made visible in the importing library if they are defined in the
- * imported library.
+ * Specifies if this library is created for Angular analysis.
*/
- List<String> shownNames = StringUtilities.EMPTY_ARRAY;
+ void set angularHtml(bool isAngularHtml) {
+ this._isAngularHtml = isAngularHtml;
+ }
/**
- * The offset of the character immediately following the last character of this node.
+ * Set the compilation unit that defines this library to the given compilation unit.
+ *
+ * @param definingCompilationUnit the compilation unit that defines this library
*/
- int end = -1;
+ void set definingCompilationUnit(CompilationUnitElement definingCompilationUnit) {
+ (definingCompilationUnit as CompilationUnitElementImpl).enclosingElement = this;
+ this._definingCompilationUnit = definingCompilationUnit;
+ }
/**
- * The offset of the 'show' keyword of this element.
+ * Set the specifications of all of the exports defined in this library to the given array.
+ *
+ * @param exports the specifications of all of the exports defined in this library
*/
- int offset = 0;
-
- @override
- String toString() {
- JavaStringBuilder builder = new JavaStringBuilder();
- builder.append("show ");
- int count = shownNames.length;
- for (int i = 0; i < count; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- builder.append(shownNames[i]);
+ void set exports(List<ExportElement> exports) {
+ for (ExportElement exportElement in exports) {
+ (exportElement as ExportElementImpl).enclosingElement = this;
}
- return builder.toString();
+ this._exports = exports;
}
-}
-/**
- * Instances of the class `ToolkitObjectElementImpl` implement a `ToolkitObjectElement`.
- */
-abstract class ToolkitObjectElementImpl extends ElementImpl implements ToolkitObjectElement {
/**
- * Initialize a newly created toolkit object element to have the given name.
+ * Set whether this library has an import of a "dart-ext" URI to the given value.
*
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
- */
- ToolkitObjectElementImpl(String name, int nameOffset) : super(name, nameOffset);
-}
-
-/**
- * Instances of the class `TopLevelVariableElementImpl` implement a
- * `TopLevelVariableElement`.
- */
-class TopLevelVariableElementImpl extends PropertyInducingElementImpl implements TopLevelVariableElement {
- /**
- * An empty array of top-level variable elements.
+ * @param hasExtUri `true` if this library has an import of a "dart-ext" URI
*/
- static List<TopLevelVariableElement> EMPTY_ARRAY = new List<TopLevelVariableElement>(0);
+ void set hasExtUri(bool hasExtUri) {
+ setModifier(Modifier.HAS_EXT_URI, hasExtUri);
+ }
/**
- * Initialize a newly created top-level variable element to have the given name.
+ * Set the specifications of all of the imports defined in this library to the given array.
*
- * @param name the name of this element
+ * @param imports the specifications of all of the imports defined in this library
*/
- TopLevelVariableElementImpl.con1(Identifier name) : super.con1(name);
+ void set imports(List<ImportElement> imports) {
+ 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;
+ }
/**
- * Initialize a newly created synthetic top-level variable element to have the given name.
+ * Set the compilation units that are included in this library using a `part` directive.
*
- * @param name the name of this element
+ * @param parts the compilation units that are included in this library using a `part`
+ * directive
*/
- TopLevelVariableElementImpl.con2(String name) : super.con2(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);
+ void set parts(List<CompilationUnitElement> parts) {
+ for (CompilationUnitElement compilationUnit in parts) {
+ (compilationUnit as CompilationUnitElementImpl).enclosingElement = this;
+ }
+ this._parts = parts;
+ }
@override
- ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChild(_definingCompilationUnit, visitor);
+ safelyVisitChildren(_exports, visitor);
+ safelyVisitChildren(_imports, visitor);
+ safelyVisitChildren(_parts, visitor);
+ }
@override
- bool get isStatic => true;
-}
-
-/**
- * Instances of the class `TypeParameterElementImpl` implement a [TypeParameterElement].
- */
-class TypeParameterElementImpl extends ElementImpl implements TypeParameterElement {
- /**
- * The type defined by this type parameter.
- */
- TypeParameterType type;
+ String get identifier => _definingCompilationUnit.source.encoding;
/**
- * The type representing the bound associated with this parameter, or `null` if this
- * parameter does not have an explicit bound.
+ * Recursively fills set of visible libraries for [getVisibleElementsLibraries].
*/
- DartType bound;
+ void _addVisibleLibraries(Set<LibraryElement> visibleLibraries, bool includeExports) {
+ // maybe already processed
+ if (!visibleLibraries.add(this)) {
+ return;
+ }
+ // add imported libraries
+ for (ImportElement importElement in _imports) {
+ LibraryElement importedLibrary = importElement.importedLibrary;
+ if (importedLibrary != null) {
+ (importedLibrary as LibraryElementImpl)._addVisibleLibraries(visibleLibraries, true);
+ }
+ }
+ // add exported libraries
+ if (includeExports) {
+ for (ExportElement exportElement in _exports) {
+ LibraryElement exportedLibrary = exportElement.exportedLibrary;
+ if (exportedLibrary != null) {
+ (exportedLibrary as LibraryElementImpl)._addVisibleLibraries(visibleLibraries, true);
+ }
+ }
+ }
+ }
/**
- * An empty array of type parameter elements.
+ * Return the object representing the type "Future" from the dart:async library, or the type
+ * "void" if the type "Future" cannot be accessed.
+ *
+ * @return the type "Future" from the dart:async library
*/
- static List<TypeParameterElement> EMPTY_ARRAY = new List<TypeParameterElement>(0);
+ DartType get loadLibraryReturnType {
+ try {
+ Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC);
+ if (asyncSource == null) {
+ AnalysisEngine.instance.logger.logError("Could not create a source for dart:async");
+ return VoidTypeImpl.instance;
+ }
+ LibraryElement asyncElement = context.computeLibraryElement(asyncSource);
+ if (asyncElement == null) {
+ AnalysisEngine.instance.logger.logError("Could not build the element model for dart:async");
+ return VoidTypeImpl.instance;
+ }
+ ClassElement futureElement = asyncElement.getType("Future");
+ if (futureElement == null) {
+ AnalysisEngine.instance.logger.logError("Could not find type Future in dart:async");
+ return VoidTypeImpl.instance;
+ }
+ InterfaceType futureType = futureElement.type;
+ return futureType.substitute4(<DartType> [DynamicTypeImpl.instance]);
+ } on AnalysisException catch (exception) {
+ AnalysisEngine.instance.logger.logError2("Could not build the element model for dart:async", exception);
+ return VoidTypeImpl.instance;
+ }
+ }
/**
- * Initialize a newly created type parameter element to have the given name.
+ * Answer `true` if the receiver directly or indirectly imports the dart:html libraries.
*
- * @param name the name of this element
+ * @return `true` if the receiver directly or indirectly imports the dart:html libraries
*/
- TypeParameterElementImpl(Identifier name) : super.forNode(name);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
-
- @override
- ElementKind get kind => ElementKind.TYPE_PARAMETER;
-
- @override
- void appendTo(JavaStringBuilder builder) {
- builder.append(displayName);
- if (bound != null) {
- builder.append(" extends ");
- builder.append(bound);
+ 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;
}
}
/**
- * Instances of the class `UriReferencedElementImpl` implement an [UriReferencedElement]
- * .
+ * The interface `LocalElement` defines the behavior of elements that can be (but are not
+ * required to be) defined within a method or function (an [ExecutableElement]).
*/
-abstract class UriReferencedElementImpl extends ElementImpl implements UriReferencedElement {
- /**
- * The offset of the URI in the file, may be `-1` if synthetic.
- */
- int uriOffset = -1;
-
- /**
- * The offset of the character immediately following the last character of this node's URI, may be
- * `-1` if synthetic.
- */
- int uriEnd = -1;
-
+abstract class LocalElement implements Element {
/**
- * The URI that is specified by this directive.
+ * Return a source range that covers the approximate portion of the source in which the name of
+ * this element is visible, or `null` if there is no single range of characters within which
+ * the element name is visible.
+ * * For a local variable, this includes everything from the end of the variable's initializer
+ * to the end of the block that encloses the variable declaration.
+ * * For a parameter, this includes the body of the method or function that declares the
+ * parameter.
+ * * For a local function, this includes everything from the beginning of the function's body to
+ * the end of the block that encloses the function declaration.
+ * * For top-level functions, `null` will be returned because they are potentially visible
+ * in multiple sources.
+ *
+ * @return the range of characters in which the name of this element is visible
*/
- String uri;
+ SourceRange get visibleRange;
+}
+/**
+ * The interface `LocalVariableElement` defines the behavior common to elements that represent
+ * a local variable.
+ */
+abstract class LocalVariableElement implements LocalElement, VariableElement {
/**
- * Initialize a newly created import element.
+ * Return an array containing all of the toolkit specific objects attached to this variable.
*
- * @param name the name of this element
- * @param offset the directive offset, may be `-1` if synthetic.
+ * @return the toolkit objects attached to this variable
*/
- UriReferencedElementImpl(String name, int offset) : super(name, offset);
+ List<ToolkitObjectElement> get toolkitObjects;
}
/**
- * Instances of the class `VariableElementImpl` implement a `VariableElement`.
+ * Instances of the class `LocalVariableElementImpl` implement a `LocalVariableElement`.
*/
-abstract class VariableElementImpl extends ElementImpl implements VariableElement {
+class LocalVariableElementImpl extends VariableElementImpl implements LocalVariableElement {
/**
- * The declared type of this variable.
+ * Is `true` if this variable is potentially mutated somewhere in its scope.
*/
- DartType type;
+ bool _potentiallyMutatedInScope = false;
/**
- * A synthetic function representing this variable's initializer, or `null` if this variable
- * does not have an initializer.
+ * Is `true` if this variable is potentially mutated somewhere in closure.
*/
- FunctionElement _initializer;
+ bool _potentiallyMutatedInClosure = false;
/**
- * An empty array of variable elements.
+ * The offset to the beginning of the visible range for this element.
*/
- static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>(0);
+ int _visibleRangeOffset = 0;
/**
- * Initialize a newly created variable element to have the given name.
- *
- * @param name the name of this element
+ * The length of the visible range for this element, or `-1` if this element does not have a
+ * visible range.
*/
- VariableElementImpl.forNode(Identifier name) : super.forNode(name);
+ int _visibleRangeLength = -1;
/**
- * Initialize a newly created variable element to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * An empty array of field elements.
*/
- VariableElementImpl(String name, int nameOffset) : super(name, nameOffset);
+ static List<LocalVariableElement> EMPTY_ARRAY = new List<LocalVariableElement>(0);
/**
- * 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.
+ * Initialize a newly created local variable element to have the given name.
*
- * @return the result of evaluating this variable's initializer
+ * @param name the name of this element
*/
- EvaluationResultImpl get evaluationResult => null;
+ LocalVariableElementImpl(Identifier name) : super.forNode(name);
@override
- FunctionElement get initializer => _initializer;
+ accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this);
@override
- VariableDeclaration get node => getNodeMatching((node) => node is VariableDeclaration);
+ ElementKind get kind => ElementKind.LOCAL_VARIABLE;
@override
- bool get isConst => hasModifier(Modifier.CONST);
+ List<ToolkitObjectElement> get toolkitObjects {
+ CompilationUnitElementImpl unit = getAncestor((element) => element is CompilationUnitElementImpl);
+ if (unit == null) {
+ return ToolkitObjectElement.EMPTY_ARRAY;
+ }
+ return unit._getToolkitObjects(this);
+ }
@override
- bool get isFinal => hasModifier(Modifier.FINAL);
+ SourceRange get visibleRange {
+ if (_visibleRangeLength < 0) {
+ return null;
+ }
+ return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
+ }
- /**
- * Return `true` if this variable is potentially mutated somewhere in a closure. This
- * information is only available for local variables (including parameters) and only after the
- * compilation unit containing the variable has been resolved.
- *
- * @return `true` if this variable is potentially mutated somewhere in closure
- */
- bool get isPotentiallyMutatedInClosure => false;
+ @override
+ bool get isPotentiallyMutatedInClosure => _potentiallyMutatedInClosure;
- /**
- * Return `true` if this variable is potentially mutated somewhere in its scope. This
- * information is only available for local variables (including parameters) and only after the
- * compilation unit containing the variable has been resolved.
- *
- * @return `true` if this variable is potentially mutated somewhere in its scope
- */
- bool get isPotentiallyMutatedInScope => false;
+ @override
+ bool get isPotentiallyMutatedInScope => _potentiallyMutatedInScope;
/**
- * Set whether this variable is const to correspond to the given value.
- *
- * @param isConst `true` if the variable is const
+ * Specifies that this variable is potentially mutated somewhere in closure.
*/
- void set const3(bool isConst) {
- setModifier(Modifier.CONST, isConst);
+ void markPotentiallyMutatedInClosure() {
+ _potentiallyMutatedInClosure = true;
}
/**
- * Set the result of evaluating this variable's initializer as a compile-time constant expression
- * to the given result.
- *
- * @param result the result of evaluating this variable's initializer
+ * Specifies that this variable is potentially mutated somewhere in its scope.
*/
- void set evaluationResult(EvaluationResultImpl result) {
- throw new IllegalStateException("Invalid attempt to set a compile-time constant result");
+ void markPotentiallyMutatedInScope() {
+ _potentiallyMutatedInScope = true;
}
/**
- * Set whether this variable is final to correspond to the given value.
+ * Set the toolkit specific information objects attached to this variable.
*
- * @param isFinal `true` if the variable is final
+ * @param toolkitObjects the toolkit objects attached to this variable
*/
- void set final2(bool isFinal) {
- setModifier(Modifier.FINAL, isFinal);
+ void set toolkitObjects(List<ToolkitObjectElement> toolkitObjects) {
+ CompilationUnitElementImpl unit = getAncestor((element) => element is CompilationUnitElementImpl);
+ if (unit == null) {
+ return;
+ }
+ unit._setToolkitObjects(this, toolkitObjects);
}
/**
- * Set the function representing this variable's initializer to the given function.
+ * Set the visible range for this element to the range starting at the given offset with the given
+ * length.
*
- * @param initializer the function representing this variable's initializer
+ * @param offset the offset to the beginning of the visible range for this element
+ * @param length the length of the visible range for this element, or `-1` if this element
+ * does not have a visible range
*/
- void set initializer(FunctionElement initializer) {
- if (initializer != null) {
- (initializer as FunctionElementImpl).enclosingElement = this;
- }
- this._initializer = initializer;
- }
-
- @override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChild(_initializer, visitor);
+ void setVisibleRange(int offset, int length) {
+ _visibleRangeOffset = offset;
+ _visibleRangeLength = length;
}
@override
@@ -7075,979 +7865,951 @@ abstract class VariableElementImpl extends ElementImpl implements VariableElemen
builder.append(" ");
builder.append(displayName);
}
-}
-
-/**
- * Information about Angular application.
- */
-class AngularApplication {
- final Source entryPoint;
-
- final Set<Source> _librarySources;
-
- final List<AngularElement> elements;
-
- final List<Source> elementSources;
-
- AngularApplication(this.entryPoint, this._librarySources, this.elements, this.elementSources);
- /**
- * Checks if this application depends on the library with the given [Source].
- */
- bool dependsOn(Source librarySource) => _librarySources.contains(librarySource);
+ @override
+ String get identifier => "${super.identifier}@${nameOffset}";
}
/**
- * Implementation of `AngularComponentElement`.
+ * The abstract class `Member` defines the behavior common to elements that represent members
+ * of parameterized types.
*/
-class AngularComponentElementImpl extends AngularHasSelectorElementImpl implements AngularComponentElement {
+abstract class Member implements Element {
/**
- * The offset of the defining <code>Component</code> annotation.
+ * The element on which the parameterized element was created.
*/
- final int _annotationOffset;
+ final Element _baseElement;
/**
- * The array containing all of the properties declared by this component.
+ * The type in which the element is defined.
*/
- List<AngularPropertyElement> _properties = AngularPropertyElement.EMPTY_ARRAY;
+ final ParameterizedType _definingType;
/**
- * The array containing all of the scope properties set by this component.
+ * Initialize a newly created element to represent the member of the given parameterized type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
*/
- List<AngularScopePropertyElement> _scopeProperties = AngularScopePropertyElement.EMPTY_ARRAY;
+ Member(this._baseElement, this._definingType);
- /**
- * The the CSS file URI.
- */
- String styleUri;
+ @override
+ String computeDocumentationComment() => _baseElement.computeDocumentationComment();
- /**
- * The offset of the [styleUri] in the [getSource].
- */
- int styleUriOffset = 0;
+ @override
+ Element getAncestor(Predicate<Element> predicate) => baseElement.getAncestor(predicate);
/**
- * The HTML template URI.
+ * Return the element on which the parameterized element was created.
+ *
+ * @return the element on which the parameterized element was created
*/
- String templateUri;
+ Element get baseElement => _baseElement;
- /**
- * The HTML template source.
- */
- Source templateSource;
+ @override
+ AnalysisContext get context => _baseElement.context;
- /**
- * The offset of the [templateUri] in the [getSource].
- */
- int templateUriOffset = 0;
+ @override
+ String get displayName => _baseElement.displayName;
- /**
- * Initialize a newly created Angular component to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
- */
- AngularComponentElementImpl(String name, int nameOffset, this._annotationOffset) : super(name, nameOffset);
+ @override
+ ElementKind get kind => _baseElement.kind;
+
+ @override
+ LibraryElement get library => _baseElement.library;
+
+ @override
+ ElementLocation get location => _baseElement.location;
+
+ @override
+ List<ElementAnnotation> get metadata => _baseElement.metadata;
+
+ @override
+ String get name => _baseElement.name;
+
+ @override
+ int get nameOffset => _baseElement.nameOffset;
+
+ @override
+ AstNode get node => _baseElement.node;
+
+ @override
+ Source get source => _baseElement.source;
+
+ @override
+ CompilationUnit get unit => _baseElement.unit;
+
+ @override
+ bool isAccessibleIn(LibraryElement library) => _baseElement.isAccessibleIn(library);
+
+ @override
+ bool get isDeprecated => _baseElement.isDeprecated;
@override
- accept(ElementVisitor visitor) => visitor.visitAngularComponentElement(this);
+ bool get isOverride => _baseElement.isOverride;
@override
- ElementKind get kind => ElementKind.ANGULAR_COMPONENT;
+ bool get isPrivate => _baseElement.isPrivate;
@override
- List<AngularPropertyElement> get properties => _properties;
+ bool get isPublic => _baseElement.isPublic;
@override
- List<AngularScopePropertyElement> get scopeProperties => _scopeProperties;
+ bool get isSynthetic => _baseElement.isSynthetic;
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ }
/**
- * Set an array containing all of the properties declared by this component.
+ * Return the type in which the element is defined.
*
- * @param properties the properties to set
+ * @return the type in which the element is defined
*/
- void set properties(List<AngularPropertyElement> properties) {
- for (AngularPropertyElement property in properties) {
- encloseElement(property as AngularPropertyElementImpl);
+ ParameterizedType get definingType => _definingType;
+
+ /**
+ * If the given child is not `null`, use the given visitor to visit it.
+ *
+ * @param child the child to be visited
+ * @param visitor the visitor to be used to visit the child
+ */
+ void safelyVisitChild(Element child, ElementVisitor visitor) {
+ if (child != null) {
+ child.accept(visitor);
}
- this._properties = properties;
}
/**
- * Set an array containing all of the scope properties declared by this component.
+ * Use the given visitor to visit all of the children in the given array.
*
- * @param properties the properties to set
+ * @param children the children to be visited
+ * @param visitor the visitor being used to visit the children
*/
- void set scopeProperties(List<AngularScopePropertyElement> properties) {
- for (AngularScopePropertyElement property in properties) {
- encloseElement(property as AngularScopePropertyElementImpl);
+ void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
+ if (children != null) {
+ for (Element child in children) {
+ child.accept(visitor);
+ }
}
- this._scopeProperties = properties;
}
- @override
- void visitChildren(ElementVisitor visitor) {
- safelyVisitChildren(_properties, visitor);
- safelyVisitChildren(_scopeProperties, visitor);
- super.visitChildren(visitor);
+ /**
+ * Return the type that results from replacing the type parameters in the given type with the type
+ * arguments.
+ *
+ * @param type the type to be transformed
+ * @return the result of transforming the type
+ */
+ DartType substituteFor(DartType type) {
+ List<DartType> argumentTypes = _definingType.typeArguments;
+ List<DartType> parameterTypes = TypeParameterTypeImpl.getTypes(_definingType.typeParameters);
+ return type.substitute2(argumentTypes, parameterTypes);
}
- @override
- String get identifier => "AngularComponent@${_annotationOffset}";
+ /**
+ * Return the array of types that results from replacing the type parameters in the given types
+ * with the type arguments.
+ *
+ * @param types the types to be transformed
+ * @return the result of transforming the types
+ */
+ List<InterfaceType> substituteFor2(List<InterfaceType> types) {
+ int count = types.length;
+ List<InterfaceType> substitutedTypes = new List<InterfaceType>(count);
+ for (int i = 0; i < count; i++) {
+ substitutedTypes[i] = substituteFor(types[i]);
+ }
+ return substitutedTypes;
+ }
}
/**
- * Implementation of `AngularControllerElement`.
+ * The interface `MethodElement` defines the behavior of elements that represent a method
+ * defined within a type.
*/
-class AngularControllerElementImpl extends AngularHasSelectorElementImpl implements AngularControllerElement {
+abstract class MethodElement implements ClassMemberElement, ExecutableElement {
/**
- * Initialize a newly created Angular controller to have the given name.
+ * Return the resolved [MethodDeclaration] node that declares this [MethodElement].
*
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
+ *
+ * @return the resolved [MethodDeclaration], not `null`.
*/
- AngularControllerElementImpl(String name, int nameOffset) : super(name, nameOffset);
-
@override
- accept(ElementVisitor visitor) => visitor.visitAngularControllerElement(this);
+ MethodDeclaration get node;
- @override
- ElementKind get kind => ElementKind.ANGULAR_CONTROLLER;
+ /**
+ * Return `true` if this method is abstract. Methods are abstract if they are not external
+ * and have no body.
+ *
+ * @return `true` if this method is abstract
+ */
+ bool get isAbstract;
}
/**
- * Implementation of `AngularDirectiveElement`.
+ * Instances of the class `MethodElementImpl` implement a `MethodElement`.
*/
-class AngularDecoratorElementImpl extends AngularHasSelectorElementImpl implements AngularDecoratorElement {
+class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
/**
- * The offset of the annotation that defines this directive.
+ * An empty array of method elements.
*/
- final int _offset;
+ static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>(0);
/**
- * The array containing all of the properties declared by this directive.
+ * Initialize a newly created method element to have the given name.
+ *
+ * @param name the name of this element
*/
- List<AngularPropertyElement> _properties = AngularPropertyElement.EMPTY_ARRAY;
+ MethodElementImpl.forNode(Identifier name) : super.forNode(name);
/**
- * Initialize a newly created Angular directive to have the given name.
+ * Initialize a newly created method element to have the given name.
*
- * @param offset the offset of the annotation that defines this directive
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- AngularDecoratorElementImpl(this._offset) : super(null, -1);
+ MethodElementImpl(String name, int nameOffset) : super(name, nameOffset);
@override
- accept(ElementVisitor visitor) => visitor.visitAngularDirectiveElement(this);
+ accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
@override
- String get displayName => selector.displayName;
+ String get displayName {
+ String displayName = super.displayName;
+ if ("unary-" == displayName) {
+ return "-";
+ }
+ return displayName;
+ }
@override
- ElementKind get kind => ElementKind.ANGULAR_DIRECTIVE;
+ ClassElement get enclosingElement => super.enclosingElement as ClassElement;
@override
- List<AngularPropertyElement> get properties => _properties;
+ ElementKind get kind => ElementKind.METHOD;
@override
- bool isClass(String name) {
- Element enclosing = enclosingElement;
- return enclosing is ClassElement && enclosing.name == name;
- }
-
- /**
- * Set an array containing all of the properties declared by this directive.
- *
- * @param properties the properties to set
- */
- void set properties(List<AngularPropertyElement> properties) {
- for (AngularPropertyElement property in properties) {
- encloseElement(property as AngularPropertyElementImpl);
+ String get name {
+ String name = super.name;
+ if (isOperator && name == "-") {
+ if (parameters.length == 0) {
+ return "unary-";
+ }
}
- this._properties = properties;
+ return super.name;
}
@override
- void visitChildren(ElementVisitor visitor) {
- safelyVisitChildren(_properties, visitor);
- super.visitChildren(visitor);
+ MethodDeclaration get node => getNodeMatching((node) => node is MethodDeclaration);
+
+ @override
+ bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+
+ @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
- String get identifier => "Decorator@${_offset}";
-}
+ bool get isStatic => hasModifier(Modifier.STATIC);
-/**
- * Implementation of `AngularElement`.
- */
-abstract class AngularElementImpl extends ToolkitObjectElementImpl implements AngularElement {
/**
- * The [AngularApplication] this element is used in.
+ * Set whether this method is abstract to correspond to the given value.
+ *
+ * @param isAbstract `true` if the method is abstract
*/
- AngularApplication _application;
+ void set abstract(bool isAbstract) {
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
/**
- * Initialize a newly created Angular element to have the given name.
+ * Set whether this method is static to correspond to the given value.
*
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * @param isStatic `true` if the method is static
*/
- AngularElementImpl(String name, int nameOffset) : super(name, nameOffset);
+ void set static(bool isStatic) {
+ setModifier(Modifier.STATIC, isStatic);
+ }
@override
- AngularApplication get application => _application;
-
- /**
- * Set the [AngularApplication] this element is used in.
- */
- void set application(AngularApplication application) {
- this._application = application;
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(enclosingElement.displayName);
+ builder.append(".");
+ builder.append(displayName);
+ super.appendTo(builder);
}
}
/**
- * Implementation of `AngularFormatterElement`.
+ * Instances of the class `MethodMember` represent a method element defined in a parameterized
+ * type where the values of the type parameters are known.
*/
-class AngularFormatterElementImpl extends AngularElementImpl implements AngularFormatterElement {
+class MethodMember extends ExecutableMember implements MethodElement {
/**
- * Initialize a newly created Angular formatter to have the given name.
+ * If the given method's type is different when any type parameters from the defining type's
+ * declaration are replaced with the actual type arguments from the defining type, create a method
+ * member representing the given method. Return the member that was created, or the base method if
+ * no member was created.
*
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * @param baseMethod the base method for which a member might be created
+ * @param definingType the type defining the parameters and arguments to be used in the
+ * substitution
+ * @return the method element that will return the correctly substituted types
*/
- AngularFormatterElementImpl(String name, int nameOffset) : super(name, nameOffset);
+ static MethodElement from(MethodElement baseMethod, InterfaceType definingType) {
+ if (baseMethod == null || definingType.typeArguments.length == 0) {
+ return baseMethod;
+ }
+ FunctionType baseType = baseMethod.type;
+ List<DartType> argumentTypes = definingType.typeArguments;
+ List<DartType> parameterTypes = definingType.element.type.typeArguments;
+ FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
+ if (baseType == substitutedType) {
+ return baseMethod;
+ }
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
+ return new MethodMember(baseMethod, definingType);
+ }
+
+ /**
+ * Initialize a newly created element to represent a method of the given parameterized type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
+ */
+ MethodMember(MethodElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
@override
- accept(ElementVisitor visitor) => visitor.visitAngularFormatterElement(this);
+ accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
@override
- ElementKind get kind => ElementKind.ANGULAR_FORMATTER;
-}
+ MethodElement get baseElement => super.baseElement as MethodElement;
-/**
- * Implementation of [AngularSelectorElement] based on presence of a class.
- */
-class AngularHasClassSelectorElementImpl extends AngularSelectorElementImpl implements AngularHasClassSelectorElement {
- AngularHasClassSelectorElementImpl(String name, int offset) : super(name, offset);
+ @override
+ ClassElement get enclosingElement => baseElement.enclosingElement;
@override
- bool apply(XmlTagNode node) {
- XmlAttributeNode attribute = node.getAttribute("class");
- if (attribute != null) {
- String text = attribute.text;
- if (text != null) {
- String name = this.name;
- for (String className in StringUtils.split(text)) {
- if (className == name) {
- return true;
- }
- }
- }
- }
- return false;
- }
+ MethodDeclaration get node => baseElement.node;
@override
- void appendTo(JavaStringBuilder builder) {
+ bool get isAbstract => baseElement.isAbstract;
+
+ @override
+ String toString() {
+ MethodElement baseElement = this.baseElement;
+ List<ParameterElement> parameters = this.parameters;
+ FunctionType type = this.type;
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append(baseElement.enclosingElement.displayName);
builder.append(".");
- builder.append(name);
+ builder.append(baseElement.displayName);
+ builder.append("(");
+ int parameterCount = parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(parameters[i]).toString();
+ }
+ builder.append(")");
+ if (type != null) {
+ builder.append(Element.RIGHT_ARROW);
+ builder.append(type.returnType);
+ }
+ return builder.toString();
}
}
/**
- * Implementation of `AngularSelectorElement`.
+ * The enumeration `Modifier` defines constants for all of the modifiers defined by the Dart
+ * language and for a few additional flags that are useful.
*/
-abstract class AngularHasSelectorElementImpl extends AngularElementImpl implements AngularHasSelectorElement {
+class Modifier extends Enum<Modifier> {
/**
- * The selector of this element.
+ * Indicates that the modifier 'abstract' was applied to the element.
*/
- AngularSelectorElement _selector;
+ static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0);
/**
- * Initialize a newly created Angular element to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * Indicates that the modifier 'const' was applied to the element.
*/
- AngularHasSelectorElementImpl(String name, int nameOffset) : super(name, nameOffset);
-
- @override
- AngularSelectorElement get selector => _selector;
+ static const Modifier CONST = const Modifier('CONST', 1);
/**
- * Set the selector of this selector-based element.
- *
- * @param selector the selector to set
+ * Indicates that the import element represents a deferred library.
*/
- void set selector(AngularSelectorElement selector) {
- encloseElement(selector as AngularSelectorElementImpl);
- this._selector = selector;
- }
-
- @override
- void visitChildren(ElementVisitor visitor) {
- safelyVisitChild(_selector, visitor);
- super.visitChildren(visitor);
- }
-}
+ static const Modifier DEFERRED = const Modifier('DEFERRED', 2);
-/**
- * Implementation of `AngularPropertyElement`.
- */
-class AngularPropertyElementImpl extends AngularElementImpl implements AngularPropertyElement {
/**
- * The [FieldElement] to which this property is bound.
+ * Indicates that the modifier 'factory' was applied to the element.
*/
- FieldElement field;
+ static const Modifier FACTORY = const Modifier('FACTORY', 3);
/**
- * The offset of the field name in the property map.
+ * Indicates that the modifier 'final' was applied to the element.
*/
- int fieldNameOffset = -1;
+ static const Modifier FINAL = const Modifier('FINAL', 4);
- AngularPropertyKind propertyKind;
+ /**
+ * Indicates that the pseudo-modifier 'get' was applied to the element.
+ */
+ static const Modifier GETTER = const Modifier('GETTER', 5);
/**
- * Initialize a newly created Angular property to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * A flag used for libraries indicating that the defining compilation unit contains at least one
+ * import directive whose URI uses the "dart-ext" scheme.
*/
- AngularPropertyElementImpl(String name, int nameOffset) : super(name, nameOffset);
+ static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 6);
- @override
- accept(ElementVisitor visitor) => visitor.visitAngularPropertyElement(this);
+ static const Modifier MIXIN = const Modifier('MIXIN', 7);
- @override
- ElementKind get kind => ElementKind.ANGULAR_PROPERTY;
-}
+ static const Modifier REFERENCES_SUPER = const Modifier('REFERENCES_SUPER', 8);
-/**
- * Implementation of `AngularScopePropertyElement`.
- */
-class AngularScopePropertyElementImpl extends AngularElementImpl implements AngularScopePropertyElement {
/**
- * The type of the property
+ * Indicates that the pseudo-modifier 'set' was applied to the element.
*/
- final DartType type;
+ static const Modifier SETTER = const Modifier('SETTER', 9);
/**
- * Initialize a newly created Angular scope property to have the given name.
- *
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * Indicates that the modifier 'static' was applied to the element.
*/
- AngularScopePropertyElementImpl(String name, int nameOffset, this.type) : super(name, nameOffset);
+ static const Modifier STATIC = const Modifier('STATIC', 10);
- @override
- accept(ElementVisitor visitor) => visitor.visitAngularScopePropertyElement(this);
+ /**
+ * 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', 11);
- @override
- ElementKind get kind => ElementKind.ANGULAR_SCOPE_PROPERTY;
+ static const Modifier TYPEDEF = const Modifier('TYPEDEF', 12);
+
+ static const List<Modifier> values = const [
+ ABSTRACT,
+ CONST,
+ DEFERRED,
+ FACTORY,
+ FINAL,
+ GETTER,
+ HAS_EXT_URI,
+ MIXIN,
+ REFERENCES_SUPER,
+ SETTER,
+ STATIC,
+ SYNTHETIC,
+ TYPEDEF];
+
+ const Modifier(String name, int ordinal) : super(name, ordinal);
}
/**
- * Implementation of `AngularFormatterElement`.
+ * The interface `MultiplyDefinedElement` defines the behavior of pseudo-elements that
+ * represent multiple elements defined within a single scope that have the same name. This situation
+ * is not allowed by the language, so objects implementing this interface always represent an error.
+ * As a result, most of the normal operations on elements do not make sense and will return useless
+ * results.
*/
-abstract class AngularSelectorElementImpl extends AngularElementImpl implements AngularSelectorElement {
+abstract class MultiplyDefinedElement implements Element {
/**
- * Initialize a newly created Angular selector to have the given name.
+ * Return an array containing all of the elements that were defined within the scope to have the
+ * same name.
*
- * @param name the name of this element
- * @param nameOffset the offset of the name of this element in the file that contains the
- * declaration of this element
+ * @return the elements that were defined with the same name
*/
- AngularSelectorElementImpl(String name, int nameOffset) : super(name, nameOffset);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitAngularSelectorElement(this);
+ List<Element> get conflictingElements;
- @override
- ElementKind get kind => ElementKind.ANGULAR_SELECTOR;
+ /**
+ * Return the type of this element as the dynamic type.
+ *
+ * @return the type of this element as the dynamic type
+ */
+ DartType get type;
}
/**
- * Implementation of [AngularSelectorElement] based on tag name.
+ * Instances of the class `MultiplyDefinedElementImpl` represent a collection of elements that
+ * have the same name within the same scope.
*/
-class AngularTagSelectorElementImpl extends AngularSelectorElementImpl implements AngularTagSelectorElement {
- AngularTagSelectorElementImpl(String name, int offset) : super(name, offset);
+class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
+ /**
+ * Return an element that represents the given conflicting elements.
+ *
+ * @param context the analysis context in which the multiply defined elements are defined
+ * @param firstElement the first element that conflicts
+ * @param secondElement the second element that conflicts
+ */
+ static Element fromElements(AnalysisContext context, Element firstElement, Element secondElement) {
+ List<Element> conflictingElements = _computeConflictingElements(firstElement, secondElement);
+ int length = conflictingElements.length;
+ if (length == 0) {
+ return null;
+ } else if (length == 1) {
+ return conflictingElements[0];
+ }
+ return new MultiplyDefinedElementImpl(context, conflictingElements);
+ }
- @override
- bool apply(XmlTagNode node) {
- String tagName = name;
- return node.tag == tagName;
+ /**
+ * Add the given element to the list of elements. If the element is a multiply-defined element,
+ * add all of the conflicting elements that it represents.
+ *
+ * @param elements the list to which the element(s) are to be added
+ * @param element the element(s) to be added
+ */
+ static void _add(Set<Element> elements, Element element) {
+ if (element is MultiplyDefinedElementImpl) {
+ for (Element conflictingElement in element.conflictingElements) {
+ elements.add(conflictingElement);
+ }
+ } else {
+ elements.add(element);
+ }
}
- @override
- AngularApplication get application => (enclosingElement as AngularElementImpl).application;
-}
+ /**
+ * Use the given elements to construct an array of conflicting elements. If either of the given
+ * elements are multiply-defined elements then the conflicting elements they represent will be
+ * included in the array. Otherwise, the element itself will be included.
+ *
+ * @param firstElement the first element to be included
+ * @param secondElement the second element to be included
+ * @return an array containing all of the conflicting elements
+ */
+ static List<Element> _computeConflictingElements(Element firstElement, Element secondElement) {
+ Set<Element> elements = new Set<Element>();
+ _add(elements, firstElement);
+ _add(elements, secondElement);
+ return new List.from(elements);
+ }
-/**
- * Implementation of `AngularViewElement`.
- */
-class AngularViewElementImpl extends AngularElementImpl implements AngularViewElement {
/**
- * The HTML template URI.
+ * The analysis context in which the multiply defined elements are defined.
*/
- final String templateUri;
+ final AnalysisContext context;
/**
- * The offset of the [templateUri] in the [getSource].
+ * The name of the conflicting elements.
*/
- final int templateUriOffset;
+ String _name;
/**
- * The HTML template source.
+ * A list containing all of the elements that conflict.
*/
- Source templateSource;
+ final List<Element> conflictingElements;
/**
- * Initialize a newly created Angular view.
+ * Initialize a newly created element to represent a list of conflicting elements.
+ *
+ * @param context the analysis context in which the multiply defined elements are defined
+ * @param conflictingElements the elements that conflict
*/
- AngularViewElementImpl(this.templateUri, this.templateUriOffset) : super(null, -1);
+ MultiplyDefinedElementImpl(this.context, this.conflictingElements) {
+ _name = conflictingElements[0].name;
+ }
@override
- accept(ElementVisitor visitor) => visitor.visitAngularViewElement(this);
+ accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this);
@override
- ElementKind get kind => ElementKind.ANGULAR_VIEW;
+ String computeDocumentationComment() => null;
@override
- String get identifier => "AngularView@${templateUriOffset}";
-}
+ Element getAncestor(Predicate<Element> predicate) => null;
-/**
- * Implementation of [AngularSelectorElement] based on presence of attribute.
- */
-class HasAttributeSelectorElementImpl extends AngularSelectorElementImpl implements AngularHasAttributeSelectorElement {
- HasAttributeSelectorElementImpl(String attributeName, int offset) : super(attributeName, offset);
+ @override
+ String get displayName => _name;
@override
- bool apply(XmlTagNode node) {
- String attributeName = name;
- return node.getAttribute(attributeName) != null;
- }
+ Element get enclosingElement => null;
@override
- void appendTo(JavaStringBuilder builder) {
- builder.append("[");
- builder.append(name);
- builder.append("]");
- }
-}
+ ElementKind get kind => ElementKind.ERROR;
-/**
- * Combination of [AngularTagSelectorElementImpl] and [HasAttributeSelectorElementImpl].
- */
-class IsTagHasAttributeSelectorElementImpl extends AngularSelectorElementImpl {
- final String tagName;
+ @override
+ LibraryElement get library => null;
- final String attributeName;
+ @override
+ ElementLocation get location => null;
- IsTagHasAttributeSelectorElementImpl(this.tagName, this.attributeName) : super(null, -1);
+ @override
+ List<ElementAnnotation> get metadata => ElementAnnotationImpl.EMPTY_ARRAY;
@override
- bool apply(XmlTagNode node) => node.tag == tagName && node.getAttribute(attributeName) != null;
-}
+ String get name => _name;
-/**
- * Instances of the class `ConstructorMember` represent a constructor element defined in a
- * parameterized type where the values of the type parameters are known.
- */
-class ConstructorMember extends ExecutableMember implements ConstructorElement {
- /**
- * If the given constructor's type is different when any type parameters from the defining type's
- * declaration are replaced with the actual type arguments from the defining type, create a
- * constructor member representing the given constructor. Return the member that was created, or
- * the base constructor if no member was created.
- *
- * @param baseConstructor the base constructor for which a member might be created
- * @param definingType the type defining the parameters and arguments to be used in the
- * substitution
- * @return the constructor element that will return the correctly substituted types
- */
- static ConstructorElement from(ConstructorElement baseConstructor, InterfaceType definingType) {
- if (baseConstructor == null || definingType.typeArguments.length == 0) {
- return baseConstructor;
- }
- FunctionType baseType = baseConstructor.type;
- if (baseType == null) {
- // TODO(brianwilkerson) We need to understand when this can happen.
- return baseConstructor;
- }
- List<DartType> argumentTypes = definingType.typeArguments;
- List<DartType> parameterTypes = definingType.element.type.typeArguments;
- FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
- if (baseType == substitutedType) {
- return baseConstructor;
- }
- // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
- // memory but speed up some operations. We need to see how often the type is being re-computed.
- return new ConstructorMember(baseConstructor, definingType);
- }
+ @override
+ int get nameOffset => -1;
- /**
- * Initialize a newly created element to represent a constructor of the given parameterized type.
- *
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
- */
- ConstructorMember(ConstructorElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
+ @override
+ AstNode get node => null;
@override
- accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
+ Source get source => null;
@override
- ConstructorElement get baseElement => super.baseElement as ConstructorElement;
+ DartType get type => DynamicTypeImpl.instance;
@override
- ClassElement get enclosingElement => baseElement.enclosingElement;
+ CompilationUnit get unit => null;
@override
- ConstructorDeclaration get node => baseElement.node;
+ bool isAccessibleIn(LibraryElement library) {
+ for (Element element in conflictingElements) {
+ if (element.isAccessibleIn(library)) {
+ return true;
+ }
+ }
+ return false;
+ }
@override
- ConstructorElement get redirectedConstructor => from(baseElement.redirectedConstructor, definingType);
+ bool get isDeprecated => false;
@override
- bool get isConst => baseElement.isConst;
+ bool get isOverride => false;
@override
- bool get isDefaultConstructor => baseElement.isDefaultConstructor;
+ bool get isPrivate {
+ String name = displayName;
+ if (name == null) {
+ return false;
+ }
+ return Identifier.isPrivateName(name);
+ }
@override
- bool get isFactory => baseElement.isFactory;
+ bool get isPublic => !isPrivate;
+
+ @override
+ bool get isSynthetic => true;
@override
String toString() {
- ConstructorElement baseElement = this.baseElement;
- List<ParameterElement> parameters = this.parameters;
- FunctionType type = this.type;
JavaStringBuilder builder = new JavaStringBuilder();
- builder.append(baseElement.enclosingElement.displayName);
- String name = displayName;
- if (name != null && !name.isEmpty) {
- builder.append(".");
- builder.append(name);
- }
- builder.append("(");
- int parameterCount = parameters.length;
- for (int i = 0; i < parameterCount; i++) {
+ builder.append("[");
+ int count = conflictingElements.length;
+ for (int i = 0; i < count; i++) {
if (i > 0) {
builder.append(", ");
}
- builder.append(parameters[i]).toString();
- }
- builder.append(")");
- if (type != null) {
- builder.append(Element.RIGHT_ARROW);
- builder.append(type.returnType);
+ (conflictingElements[i] as ElementImpl).appendTo(builder);
}
+ builder.append("]");
return builder.toString();
}
@override
- InterfaceType get definingType => super.definingType as InterfaceType;
+ void visitChildren(ElementVisitor visitor) {
+ }
}
/**
- * The abstract class `ExecutableMember` defines the behavior common to members that represent
- * an executable element defined in a parameterized type where the values of the type parameters are
- * known.
+ * The interface [MultiplyInheritedExecutableElement] defines all of the behavior of an
+ * [ExecutableElement], with the additional information of an array of
+ * [ExecutableElement]s from which this element was composed.
*/
-abstract class ExecutableMember extends Member implements ExecutableElement {
+abstract class MultiplyInheritedExecutableElement implements ExecutableElement {
/**
- * Initialize a newly created element to represent an executable element of the given
- * parameterized type.
+ * Return an array containing all of the executable elements defined within this executable
+ * element.
*
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
+ * @return the elements defined within this executable element
*/
- ExecutableMember(ExecutableElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
+ List<ExecutableElement> get inheritedElements;
+}
- @override
- ExecutableElement get baseElement => super.baseElement as ExecutableElement;
+/**
+ * The interface [MultiplyInheritedMethodElementImpl] defines all of the behavior of an
+ * [MethodElementImpl], with the additional information of an array of
+ * [ExecutableElement]s from which this element was composed.
+ */
+class MultiplyInheritedMethodElementImpl extends MethodElementImpl implements MultiplyInheritedExecutableElement {
+ /**
+ * An array the array of executable elements that were used to compose this element.
+ */
+ List<ExecutableElement> _elements = MethodElementImpl.EMPTY_ARRAY;
- @override
- List<FunctionElement> get functions {
- //
- // Elements within this element should have type parameters substituted, just like this element.
- //
- throw new UnsupportedOperationException();
+ MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) {
+ synthetic = true;
}
@override
- List<LabelElement> get labels => baseElement.labels;
-
- @override
- List<LocalVariableElement> get localVariables {
- //
- // Elements within this element should have type parameters substituted, just like this element.
- //
- throw new UnsupportedOperationException();
- }
+ List<ExecutableElement> get inheritedElements => _elements;
- @override
- List<ParameterElement> get parameters {
- List<ParameterElement> baseParameters = baseElement.parameters;
- int parameterCount = baseParameters.length;
- if (parameterCount == 0) {
- return baseParameters;
- }
- List<ParameterElement> parameterizedParameters = new List<ParameterElement>(parameterCount);
- for (int i = 0; i < parameterCount; i++) {
- parameterizedParameters[i] = ParameterMember.from(baseParameters[i], definingType);
- }
- return parameterizedParameters;
+ void set inheritedElements(List<ExecutableElement> elements) {
+ this._elements = elements;
}
+}
- @override
- DartType get returnType => substituteFor(baseElement.returnType);
-
- @override
- FunctionType get type => substituteFor(baseElement.type);
+/**
+ * The interface [MultiplyInheritedPropertyAccessorElementImpl] defines all of the behavior of
+ * an [PropertyAccessorElementImpl], with the additional information of an array of
+ * [ExecutableElement]s from which this element was composed.
+ */
+class MultiplyInheritedPropertyAccessorElementImpl extends PropertyAccessorElementImpl implements MultiplyInheritedExecutableElement {
+ /**
+ * An array the array of executable elements that were used to compose this element.
+ */
+ List<ExecutableElement> _elements = PropertyAccessorElementImpl.EMPTY_ARRAY;
- @override
- bool get isOperator => baseElement.isOperator;
+ MultiplyInheritedPropertyAccessorElementImpl(Identifier name) : super.forNode(name) {
+ synthetic = true;
+ }
@override
- bool get isStatic => baseElement.isStatic;
+ List<ExecutableElement> get inheritedElements => _elements;
- @override
- void visitChildren(ElementVisitor visitor) {
- // TODO(brianwilkerson) We need to finish implementing the accessors used below so that we can
- // safely invoke them.
- super.visitChildren(visitor);
- safelyVisitChildren(baseElement.functions, visitor);
- safelyVisitChildren(labels, visitor);
- safelyVisitChildren(baseElement.localVariables, visitor);
- safelyVisitChildren(parameters, visitor);
+ void set inheritedElements(List<ExecutableElement> elements) {
+ this._elements = elements;
}
}
/**
- * Instances of the class `FieldFormalParameterMember` represent a parameter element defined
- * in a parameterized type where the values of the type parameters are known.
+ * The interface `NamespaceCombinator` defines the behavior common to objects that control how
+ * namespaces are combined.
*/
-class FieldFormalParameterMember extends ParameterMember implements FieldFormalParameterElement {
+abstract class NamespaceCombinator {
/**
- * Initialize a newly created element to represent a parameter of the given parameterized type.
- *
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
+ * An empty array of namespace combinators.
*/
- FieldFormalParameterMember(FieldFormalParameterElement baseElement, ParameterizedType definingType) : super(baseElement, definingType);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(this);
-
- @override
- FieldElement get field => (baseElement as FieldFormalParameterElement).field;
+ static final List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>(0);
}
/**
- * Instances of the class `FieldMember` represent a field element defined in a parameterized
- * type where the values of the type parameters are known.
+ * The interface `ParameterElement` defines the behavior of elements representing a parameter
+ * defined within an executable element.
*/
-class FieldMember extends VariableMember implements FieldElement {
+abstract class ParameterElement implements LocalElement, VariableElement {
/**
- * If the given field's type is different when any type parameters from the defining type's
- * declaration are replaced with the actual type arguments from the defining type, create a field
- * member representing the given field. Return the member that was created, or the base field if
- * no member was created.
+ * Return a source range that covers the portion of the source in which the default value for this
+ * parameter is specified, or `null` if there is no default value.
*
- * @param baseField the base field for which a member might be created
- * @param definingType the type defining the parameters and arguments to be used in the
- * substitution
- * @return the field element that will return the correctly substituted types
+ * @return the range of characters in which the default value of this parameter is specified
*/
- static FieldElement from(FieldElement baseField, InterfaceType definingType) {
- if (baseField == null || definingType.typeArguments.length == 0) {
- return baseField;
- }
- DartType baseType = baseField.type;
- if (baseType == null) {
- return baseField;
- }
- List<DartType> argumentTypes = definingType.typeArguments;
- List<DartType> parameterTypes = definingType.element.type.typeArguments;
- DartType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
- if (baseType == substitutedType) {
- return baseField;
- }
- // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
- // memory but speed up some operations. We need to see how often the type is being re-computed.
- return new FieldMember(baseField, definingType);
- }
+ SourceRange get defaultValueRange;
/**
- * Initialize a newly created element to represent a field of the given parameterized type.
+ * Return the kind of this parameter.
*
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
+ * @return the kind of this parameter
*/
- FieldMember(FieldElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
-
- @override
- FieldElement get baseElement => super.baseElement as FieldElement;
-
- @override
- ClassElement get enclosingElement => baseElement.enclosingElement;
-
- @override
- PropertyAccessorElement get getter => PropertyAccessorMember.from(baseElement.getter, definingType);
-
- @override
- PropertyAccessorElement get setter => PropertyAccessorMember.from(baseElement.setter, definingType);
+ ParameterKind get parameterKind;
- @override
- bool get isStatic => baseElement.isStatic;
+ /**
+ * Return an array containing all of the parameters defined by this parameter. A parameter will
+ * only define other parameters if it is a function typed parameter.
+ *
+ * @return the parameters defined by this parameter element
+ */
+ List<ParameterElement> get parameters;
- @override
- InterfaceType get definingType => super.definingType as InterfaceType;
+ /**
+ * Return `true` if this parameter is an initializing formal parameter.
+ *
+ * @return `true` if this parameter is an initializing formal parameter
+ */
+ bool get isInitializingFormal;
}
/**
- * The abstract class `Member` defines the behavior common to elements that represent members
- * of parameterized types.
+ * Instances of the class `ParameterElementImpl` implement a `ParameterElement`.
*/
-abstract class Member implements Element {
+class ParameterElementImpl extends VariableElementImpl implements ParameterElement {
/**
- * The element on which the parameterized element was created.
+ * Is `true` if this variable is potentially mutated somewhere in its scope.
*/
- final Element _baseElement;
+ bool _potentiallyMutatedInScope = false;
/**
- * The type in which the element is defined.
+ * Is `true` if this variable is potentially mutated somewhere in closure.
*/
- final ParameterizedType _definingType;
+ bool _potentiallyMutatedInClosure = false;
/**
- * Initialize a newly created element to represent the member of the given parameterized type.
- *
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
+ * An array containing all of the parameters defined by this parameter element. There will only be
+ * parameters if this parameter is a function typed parameter.
*/
- Member(this._baseElement, this._definingType);
-
- @override
- String computeDocumentationComment() => _baseElement.computeDocumentationComment();
-
- @override
- Element getAncestor(Predicate<Element> predicate) => baseElement.getAncestor(predicate);
+ List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
/**
- * Return the element on which the parameterized element was created.
- *
- * @return the element on which the parameterized element was created
+ * The kind of this parameter.
*/
- Element get baseElement => _baseElement;
-
- @override
- AnalysisContext get context => _baseElement.context;
-
- @override
- String get displayName => _baseElement.displayName;
-
- @override
- ElementKind get kind => _baseElement.kind;
+ ParameterKind parameterKind;
- @override
- LibraryElement get library => _baseElement.library;
+ /**
+ * The offset to the beginning of the default value range for this element.
+ */
+ int _defaultValueRangeOffset = 0;
- @override
- ElementLocation get location => _baseElement.location;
+ /**
+ * The length of the default value range for this element, or `-1` if this element does not
+ * have a default value.
+ */
+ int _defaultValueRangeLength = -1;
- @override
- List<ElementAnnotation> get metadata => _baseElement.metadata;
+ /**
+ * The offset to the beginning of the visible range for this element.
+ */
+ int _visibleRangeOffset = 0;
- @override
- String get name => _baseElement.name;
+ /**
+ * The length of the visible range for this element, or `-1` if this element does not have a
+ * visible range.
+ */
+ int _visibleRangeLength = -1;
- @override
- int get nameOffset => _baseElement.nameOffset;
+ /**
+ * An empty array of field elements.
+ */
+ static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>(0);
- @override
- AstNode get node => _baseElement.node;
+ /**
+ * Initialize a newly created parameter element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ ParameterElementImpl.con1(Identifier name) : super.forNode(name);
- @override
- Source get source => _baseElement.source;
+ /**
+ * Initialize a newly created parameter element to have the given name.
+ *
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
+ */
+ ParameterElementImpl.con2(String name, int nameOffset) : super(name, nameOffset);
@override
- CompilationUnit get unit => _baseElement.unit;
+ accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
@override
- bool isAccessibleIn(LibraryElement library) => _baseElement.isAccessibleIn(library);
+ SourceRange get defaultValueRange {
+ if (_defaultValueRangeLength < 0) {
+ return null;
+ }
+ return new SourceRange(_defaultValueRangeOffset, _defaultValueRangeLength);
+ }
@override
- bool get isDeprecated => _baseElement.isDeprecated;
+ ElementKind get kind => ElementKind.PARAMETER;
@override
- bool get isOverride => _baseElement.isOverride;
+ List<ParameterElement> get parameters => _parameters;
@override
- bool get isPrivate => _baseElement.isPrivate;
+ SourceRange get visibleRange {
+ if (_visibleRangeLength < 0) {
+ return null;
+ }
+ return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
+ }
@override
- bool get isPublic => _baseElement.isPublic;
+ bool get isInitializingFormal => false;
@override
- bool get isSynthetic => _baseElement.isSynthetic;
+ bool get isPotentiallyMutatedInClosure => _potentiallyMutatedInClosure;
@override
- void visitChildren(ElementVisitor visitor) {
- }
-
- /**
- * Return the type in which the element is defined.
- *
- * @return the type in which the element is defined
- */
- ParameterizedType get definingType => _definingType;
-
- /**
- * If the given child is not `null`, use the given visitor to visit it.
- *
- * @param child the child to be visited
- * @param visitor the visitor to be used to visit the child
- */
- void safelyVisitChild(Element child, ElementVisitor visitor) {
- if (child != null) {
- child.accept(visitor);
- }
- }
-
- /**
- * Use the given visitor to visit all of the children in the given array.
- *
- * @param children the children to be visited
- * @param visitor the visitor being used to visit the children
- */
- void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
- if (children != null) {
- for (Element child in children) {
- child.accept(visitor);
- }
- }
+ bool get isPotentiallyMutatedInScope => _potentiallyMutatedInScope;
+
+ /**
+ * Specifies that this variable is potentially mutated somewhere in closure.
+ */
+ void markPotentiallyMutatedInClosure() {
+ _potentiallyMutatedInClosure = true;
}
/**
- * Return the type that results from replacing the type parameters in the given type with the type
- * arguments.
- *
- * @param type the type to be transformed
- * @return the result of transforming the type
+ * Specifies that this variable is potentially mutated somewhere in its scope.
*/
- DartType substituteFor(DartType type) {
- List<DartType> argumentTypes = _definingType.typeArguments;
- List<DartType> parameterTypes = TypeParameterTypeImpl.getTypes(_definingType.typeParameters);
- return type.substitute2(argumentTypes, parameterTypes);
+ void markPotentiallyMutatedInScope() {
+ _potentiallyMutatedInScope = true;
}
/**
- * Return the array of types that results from replacing the type parameters in the given types
- * with the type arguments.
+ * Set the range of the default value for this parameter to the range starting at the given offset
+ * with the given length.
*
- * @param types the types to be transformed
- * @return the result of transforming the types
+ * @param offset the offset to the beginning of the default value range for this element
+ * @param length the length of the default value range for this element, or `-1` if this
+ * element does not have a default value
*/
- List<InterfaceType> substituteFor2(List<InterfaceType> types) {
- int count = types.length;
- List<InterfaceType> substitutedTypes = new List<InterfaceType>(count);
- for (int i = 0; i < count; i++) {
- substitutedTypes[i] = substituteFor(types[i]);
- }
- return substitutedTypes;
+ void setDefaultValueRange(int offset, int length) {
+ _defaultValueRangeOffset = offset;
+ _defaultValueRangeLength = length;
}
-}
-/**
- * Instances of the class `MethodMember` represent a method element defined in a parameterized
- * type where the values of the type parameters are known.
- */
-class MethodMember extends ExecutableMember implements MethodElement {
/**
- * If the given method's type is different when any type parameters from the defining type's
- * declaration are replaced with the actual type arguments from the defining type, create a method
- * member representing the given method. Return the member that was created, or the base method if
- * no member was created.
+ * Set the parameters defined by this executable element to the given parameters.
*
- * @param baseMethod the base method for which a member might be created
- * @param definingType the type defining the parameters and arguments to be used in the
- * substitution
- * @return the method element that will return the correctly substituted types
+ * @param parameters the parameters defined by this executable element
*/
- static MethodElement from(MethodElement baseMethod, InterfaceType definingType) {
- if (baseMethod == null || definingType.typeArguments.length == 0) {
- return baseMethod;
- }
- FunctionType baseType = baseMethod.type;
- List<DartType> argumentTypes = definingType.typeArguments;
- List<DartType> parameterTypes = definingType.element.type.typeArguments;
- FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
- if (baseType == substitutedType) {
- return baseMethod;
+ void set parameters(List<ParameterElement> parameters) {
+ for (ParameterElement parameter in parameters) {
+ (parameter as ParameterElementImpl).enclosingElement = this;
}
- // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
- // memory but speed up some operations. We need to see how often the type is being re-computed.
- return new MethodMember(baseMethod, definingType);
+ this._parameters = parameters;
}
/**
- * Initialize a newly created element to represent a method of the given parameterized type.
+ * Set the visible range for this element to the range starting at the given offset with the given
+ * length.
*
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
+ * @param offset the offset to the beginning of the visible range for this element
+ * @param length the length of the visible range for this element, or `-1` if this element
+ * does not have a visible range
*/
- MethodMember(MethodElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
-
- @override
- MethodElement get baseElement => super.baseElement as MethodElement;
-
- @override
- ClassElement get enclosingElement => baseElement.enclosingElement;
-
- @override
- MethodDeclaration get node => baseElement.node;
+ void setVisibleRange(int offset, int length) {
+ _visibleRangeOffset = offset;
+ _visibleRangeLength = length;
+ }
@override
- bool get isAbstract => baseElement.isAbstract;
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChildren(_parameters, visitor);
+ }
@override
- String toString() {
- MethodElement baseElement = this.baseElement;
- List<ParameterElement> parameters = this.parameters;
- FunctionType type = this.type;
- JavaStringBuilder builder = new JavaStringBuilder();
- builder.append(baseElement.enclosingElement.displayName);
- builder.append(".");
- builder.append(baseElement.displayName);
- builder.append("(");
- int parameterCount = parameters.length;
- for (int i = 0; i < parameterCount; i++) {
- if (i > 0) {
- builder.append(", ");
+ void appendTo(JavaStringBuilder builder) {
+ String left = "";
+ String right = "";
+ while (true) {
+ if (parameterKind == ParameterKind.NAMED) {
+ left = "{";
+ right = "}";
+ } else if (parameterKind == ParameterKind.POSITIONAL) {
+ left = "[";
+ right = "]";
+ } else if (parameterKind == ParameterKind.REQUIRED) {
}
- builder.append(parameters[i]).toString();
- }
- builder.append(")");
- if (type != null) {
- builder.append(Element.RIGHT_ARROW);
- builder.append(type.returnType);
+ break;
}
- return builder.toString();
+ builder.append(left);
+ appendToWithoutDelimiters(builder);
+ builder.append(right);
+ }
+
+ /**
+ * Append the type and name of this parameter to the given builder.
+ *
+ * @param builder the builder to which the type and name are to be appended
+ */
+ void appendToWithoutDelimiters(JavaStringBuilder builder) {
+ builder.append(type);
+ builder.append(" ");
+ builder.append(displayName);
}
}
@@ -8179,163 +8941,54 @@ class ParameterMember extends VariableMember implements ParameterElement {
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- safelyVisitChildren(parameters, visitor);
- }
-}
-
-/**
- * Instances of the class `PropertyAccessorMember` represent a property accessor element
- * defined in a parameterized type where the values of the type parameters are known.
- */
-class PropertyAccessorMember extends ExecutableMember implements PropertyAccessorElement {
- /**
- * If the given property accessor's type is different when any type parameters from the defining
- * type's declaration are replaced with the actual type arguments from the defining type, create a
- * property accessor member representing the given property accessor. Return the member that was
- * created, or the base accessor if no member was created.
- *
- * @param baseAccessor the base property accessor for which a member might be created
- * @param definingType the type defining the parameters and arguments to be used in the
- * substitution
- * @return the property accessor element that will return the correctly substituted types
- */
- static PropertyAccessorElement from(PropertyAccessorElement baseAccessor, InterfaceType definingType) {
- if (baseAccessor == null || definingType.typeArguments.length == 0) {
- return baseAccessor;
- }
- FunctionType baseType = baseAccessor.type;
- List<DartType> argumentTypes = definingType.typeArguments;
- List<DartType> parameterTypes = definingType.element.type.typeArguments;
- FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
- if (baseType == substitutedType) {
- return baseAccessor;
- }
- // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
- // memory but speed up some operations. We need to see how often the type is being re-computed.
- return new PropertyAccessorMember(baseAccessor, definingType);
- }
-
- /**
- * Initialize a newly created element to represent a property accessor of the given parameterized
- * type.
- *
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
- */
- PropertyAccessorMember(PropertyAccessorElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
-
- @override
- accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
-
- @override
- PropertyAccessorElement get baseElement => super.baseElement as PropertyAccessorElement;
-
- @override
- PropertyAccessorElement get correspondingGetter => from(baseElement.correspondingGetter, definingType);
-
- @override
- PropertyAccessorElement get correspondingSetter => from(baseElement.correspondingSetter, definingType);
-
- @override
- Element get enclosingElement => baseElement.enclosingElement;
-
- @override
- PropertyInducingElement get variable {
- PropertyInducingElement variable = baseElement.variable;
- if (variable is FieldElement) {
- return FieldMember.from(variable, definingType);
- }
- return variable;
- }
-
- @override
- bool get isAbstract => baseElement.isAbstract;
-
- @override
- bool get isGetter => baseElement.isGetter;
-
- @override
- bool get isSetter => baseElement.isSetter;
-
- @override
- String toString() {
- PropertyAccessorElement baseElement = this.baseElement;
- List<ParameterElement> parameters = this.parameters;
- FunctionType type = this.type;
- JavaStringBuilder builder = new JavaStringBuilder();
- if (isGetter) {
- builder.append("get ");
- } else {
- builder.append("set ");
- }
- builder.append(baseElement.enclosingElement.displayName);
- builder.append(".");
- builder.append(baseElement.displayName);
- builder.append("(");
- int parameterCount = parameters.length;
- for (int i = 0; i < parameterCount; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- builder.append(parameters[i]).toString();
- }
- builder.append(")");
- if (type != null) {
- builder.append(Element.RIGHT_ARROW);
- builder.append(type.returnType);
- }
- return builder.toString();
- }
-
- @override
- InterfaceType get definingType => super.definingType as InterfaceType;
+ safelyVisitChildren(parameters, visitor);
+ }
}
/**
- * The abstract class `VariableMember` defines the behavior common to members that represent a
- * variable element defined in a parameterized type where the values of the type parameters are
- * known.
+ * The interface `ParameterizedType` defines the behavior common to objects representing a
+ * type with type parameters, such as a class or function type alias.
*/
-abstract class VariableMember extends Member implements VariableElement {
+abstract class ParameterizedType implements DartType {
/**
- * Initialize a newly created element to represent an executable element of the given
- * parameterized type.
+ * Return an array containing the actual types of the type arguments. If this type's element does
+ * not have type parameters, then the array should be empty (although it is possible for type
+ * arguments to be erroneously declared). If the element has type parameters and the actual type
+ * does not explicitly include argument values, then the type "dynamic" will be automatically
+ * provided.
*
- * @param baseElement the element on which the parameterized element was created
- * @param definingType the type in which the element is defined
+ * @return the actual types of the type arguments
*/
- VariableMember(VariableElement baseElement, ParameterizedType definingType) : super(baseElement, definingType);
-
- @override
- VariableElement get baseElement => super.baseElement as VariableElement;
-
- @override
- FunctionElement get initializer {
- //
- // Elements within this element should have type parameters substituted, just like this element.
- //
- throw new UnsupportedOperationException();
- }
-
- @override
- VariableDeclaration get node => baseElement.node;
-
- @override
- DartType get type => substituteFor(baseElement.type);
+ List<DartType> get typeArguments;
- @override
- bool get isConst => baseElement.isConst;
+ /**
+ * Return an array containing all of the type parameters declared for this type.
+ *
+ * @return the type parameters declared for this type
+ */
+ List<TypeParameterElement> get typeParameters;
+}
- @override
- bool get isFinal => baseElement.isFinal;
+/**
+ * The interface `PolymerAttributeElement` defines an attribute in
+ * [PolymerTagHtmlElement].
+ *
+ * <pre>
+ * <polymer-element name="my-example" attributes='attrA attrB'>
+ * </polymer-element>
+ * </pre>
+ */
+abstract class PolymerAttributeElement implements PolymerElement {
+ /**
+ * An empty array of Polymer custom tag attributes.
+ */
+ static final List<PolymerAttributeElement> EMPTY_ARRAY = new List<PolymerAttributeElement>(0);
- @override
- void visitChildren(ElementVisitor visitor) {
- // TODO(brianwilkerson) We need to finish implementing the accessors used below so that we can
- // safely invoke them.
- super.visitChildren(visitor);
- safelyVisitChild(baseElement.initializer, visitor);
- }
+ /**
+ * Return the [FieldElement] associated with this attribute. Maybe `null` if
+ * [PolymerTagDartElement] does not have a field associated with it.
+ */
+ FieldElement get field;
}
/**
@@ -8364,6 +9017,17 @@ class PolymerAttributeElementImpl extends PolymerElementImpl implements PolymerA
}
/**
+ * The interface `PolymerElement` defines the behavior of objects representing information
+ * about a Polymer specific element.
+ */
+abstract class PolymerElement implements ToolkitObjectElement {
+ /**
+ * An empty array of Polymer elements.
+ */
+ static final List<PolymerElement> EMPTY_ARRAY = new List<PolymerElement>(0);
+}
+
+/**
* Implementation of `PolymerElement`.
*/
abstract class PolymerElementImpl extends ToolkitObjectElementImpl implements PolymerElement {
@@ -8378,6 +9042,28 @@ abstract class PolymerElementImpl extends ToolkitObjectElementImpl implements Po
}
/**
+ * The interface `PolymerTagDartElement` defines a Polymer custom tag in Dart.
+ *
+ * <pre>
+ * @CustomTag('my-example')
+ * </pre>
+ */
+abstract class PolymerTagDartElement implements PolymerElement {
+ /**
+ * Return the [ClassElement] that is associated with this Polymer custom tag. Not
+ * `null`, because [PolymerTagDartElement]s are created for [ClassElement]s
+ * marked with the `@CustomTag` annotation.
+ */
+ ClassElement get classElement;
+
+ /**
+ * Return the [PolymerTagHtmlElement] part of this Polymer custom tag. Maybe `null` if
+ * it has not been resolved yet or there are no corresponding Dart part defined.
+ */
+ PolymerTagHtmlElement get htmlElement;
+}
+
+/**
* Implementation of `PolymerTagDartElement`.
*/
class PolymerTagDartElementImpl extends PolymerElementImpl implements PolymerTagDartElement {
@@ -8409,6 +9095,32 @@ class PolymerTagDartElementImpl extends PolymerElementImpl implements PolymerTag
}
/**
+ * The interface `PolymerTagHtmlElement` defines a Polymer custom tag in HTML.
+ *
+ * <pre>
+ * <polymer-element name="my-example" attributes='attrA attrB'>
+ * </polymer-element>
+ * </pre>
+ */
+abstract class PolymerTagHtmlElement implements PolymerElement {
+ /**
+ * An empty array of [PolymerTagHtmlElement]s.
+ */
+ static final List<PolymerTagHtmlElement> EMPTY_ARRAY = new List<PolymerTagHtmlElement>(0);
+
+ /**
+ * Return an array containing all of the attributes declared by this tag.
+ */
+ List<PolymerAttributeElement> get attributes;
+
+ /**
+ * Return the [PolymerTagDartElement] part on this Polymer custom tag. Maybe `null` if
+ * it has not been resolved yet or there are no corresponding Dart part defined.
+ */
+ PolymerTagDartElement get dartElement;
+}
+
+/**
* Implementation of `PolymerTagHtmlElement`.
*/
class PolymerTagHtmlElementImpl extends PolymerElementImpl implements PolymerTagHtmlElement {
@@ -8461,1426 +9173,923 @@ class PolymerTagHtmlElementImpl extends PolymerElementImpl implements PolymerTag
}
/**
- * The unique instance of the class `BottomTypeImpl` implements the type `bottom`.
+ * The interface `PrefixElement` defines the behavior common to elements that represent a
+ * prefix used to import one or more libraries into another library.
*/
-class BottomTypeImpl extends TypeImpl {
+abstract class PrefixElement implements Element {
/**
- * The unique instance of this class.
+ * Return the library into which other libraries are imported using this prefix.
+ *
+ * @return the library into which other libraries are imported using this prefix
*/
- static BottomTypeImpl _INSTANCE = new BottomTypeImpl();
+ @override
+ LibraryElement get enclosingElement;
+
+ /**
+ * Return an array containing all of the libraries that are imported using this prefix.
+ *
+ * @return the libraries that are imported using this prefix
+ */
+ List<LibraryElement> get importedLibraries;
+}
+
+/**
+ * Instances of the class `PrefixElementImpl` implement a `PrefixElement`.
+ */
+class PrefixElementImpl extends ElementImpl implements PrefixElement {
+ /**
+ * An array containing all of the libraries that are imported using this prefix.
+ */
+ List<LibraryElement> _importedLibraries = LibraryElementImpl.EMPTY_ARRAY;
+
+ /**
+ * An empty array of prefix elements.
+ */
+ static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>(0);
+
+ /**
+ * Initialize a newly created prefix element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ PrefixElementImpl(Identifier name) : super.forNode(name);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitPrefixElement(this);
+
+ @override
+ LibraryElement get enclosingElement => super.enclosingElement as LibraryElement;
+
+ @override
+ List<LibraryElement> get importedLibraries => _importedLibraries;
+
+ @override
+ ElementKind get kind => ElementKind.PREFIX;
+
+ /**
+ * Set the libraries that are imported using this prefix to the given libraries.
+ *
+ * @param importedLibraries the libraries that are imported using this prefix
+ */
+ void set importedLibraries(List<LibraryElement> importedLibraries) {
+ for (LibraryElement library in importedLibraries) {
+ (library as LibraryElementImpl).enclosingElement = this;
+ }
+ this._importedLibraries = importedLibraries;
+ }
+
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ builder.append("as ");
+ super.appendTo(builder);
+ }
+
+ @override
+ String get identifier => "_${super.identifier}";
+}
+
+/**
+ * The interface `PropertyAccessorElement` defines the behavior of elements representing a
+ * getter or a setter. Note that explicitly defined property accessors implicitly define a synthetic
+ * field. Symmetrically, synthetic accessors are implicitly created for explicitly defined fields.
+ * The following rules apply:
+ * * Every explicit field is represented by a non-synthetic [FieldElement].
+ * * Every explicit field induces a getter and possibly a setter, both of which are represented by
+ * synthetic [PropertyAccessorElement]s.
+ * * Every explicit getter or setter is represented by a non-synthetic
+ * [PropertyAccessorElement].
+ * * Every explicit getter or setter (or pair thereof if they have the same name) induces a field
+ * that is represented by a synthetic [FieldElement].
+ */
+abstract class PropertyAccessorElement implements ExecutableElement {
+ /**
+ * Return the accessor representing the getter that corresponds to (has the same name as) this
+ * setter, or `null` if this accessor is not a setter or if there is no corresponding
+ * getter.
+ *
+ * @return the getter that corresponds to this setter
+ */
+ PropertyAccessorElement get correspondingGetter;
+
+ /**
+ * Return the accessor representing the setter that corresponds to (has the same name as) this
+ * getter, or `null` if this accessor is not a getter or if there is no corresponding
+ * setter.
+ *
+ * @return the setter that corresponds to this getter
+ */
+ PropertyAccessorElement get correspondingSetter;
+
+ /**
+ * Return the field or top-level variable associated with this accessor. If this accessor was
+ * explicitly defined (is not synthetic) then the variable associated with it will be synthetic.
+ *
+ * @return the variable associated with this accessor
+ */
+ PropertyInducingElement get variable;
+
+ /**
+ * Return `true` if this accessor is abstract. Accessors are abstract if they are not
+ * external and have no body.
+ *
+ * @return `true` if this accessor is abstract
+ */
+ bool get isAbstract;
/**
- * Return the unique instance of this class.
+ * Return `true` if this accessor represents a getter.
*
- * @return the unique instance of this class
+ * @return `true` if this accessor represents a getter
*/
- static BottomTypeImpl get instance => _INSTANCE;
+ bool get isGetter;
/**
- * Prevent the creation of instances of this class.
+ * Return `true` if this accessor represents a setter.
+ *
+ * @return `true` if this accessor represents a setter
*/
- BottomTypeImpl() : super(null, "<bottom>");
-
- @override
- bool operator ==(Object object) => identical(object, this);
-
- @override
- int get hashCode => 0;
-
- @override
- bool get isBottom => true;
-
- @override
- bool isSupertypeOf(DartType type) => false;
-
- @override
- BottomTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) => this;
-
- @override
- bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
-
- @override
- bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) => true;
-
- @override
- bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
+ bool get isSetter;
}
/**
- * The unique instance of the class `DynamicTypeImpl` implements the type `dynamic`.
+ * Instances of the class `PropertyAccessorElementImpl` implement a
+ * `PropertyAccessorElement`.
*/
-class DynamicTypeImpl extends TypeImpl {
+class PropertyAccessorElementImpl extends ExecutableElementImpl implements PropertyAccessorElement {
/**
- * The unique instance of this class.
+ * The variable associated with this accessor.
*/
- static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl();
+ PropertyInducingElement variable;
/**
- * Return the unique instance of this class.
+ * An empty array of property accessor elements.
+ */
+ static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorElement>(0);
+
+ /**
+ * Initialize a newly created property accessor element to have the given name.
*
- * @return the unique instance of this class
+ * @param name the name of this element
*/
- static DynamicTypeImpl get instance => _INSTANCE;
+ PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
/**
- * Prevent the creation of instances of this class.
+ * Initialize a newly created synthetic property accessor element to be associated with the given
+ * variable.
+ *
+ * @param variable the variable with which this access is associated
*/
- DynamicTypeImpl() : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) {
- (element as DynamicElementImpl).type = this;
+ PropertyAccessorElementImpl(PropertyInducingElementImpl variable) : super(variable.name, variable.nameOffset) {
+ this.variable = variable;
+ synthetic = true;
}
@override
- bool operator ==(Object object) => identical(object, this);
-
- @override
- int get hashCode => 1;
+ accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
@override
- bool get isDynamic => true;
+ bool operator ==(Object object) => super == object && isGetter == (object as PropertyAccessorElement).isGetter;
@override
- bool isSupertypeOf(DartType type) => true;
+ PropertyAccessorElement get correspondingGetter {
+ if (isGetter || variable == null) {
+ return null;
+ }
+ return variable.getter;
+ }
@override
- DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
- int length = parameterTypes.length;
- for (int i = 0; i < length; i++) {
- if (parameterTypes[i] == this) {
- return argumentTypes[i];
- }
+ PropertyAccessorElement get correspondingSetter {
+ if (isSetter || variable == null) {
+ return null;
}
- return this;
+ return variable.setter;
}
@override
- bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
+ ElementKind get kind {
+ if (isGetter) {
+ return ElementKind.GETTER;
+ }
+ return ElementKind.SETTER;
+ }
@override
- bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
- // T is S
- if (identical(this, type)) {
- return true;
+ String get name {
+ if (isSetter) {
+ return "${super.name}=";
}
- // else
- return withDynamic;
+ return super.name;
}
@override
- bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
-}
-
-/**
- * Instances of the class `FunctionTypeImpl` defines the behavior common to objects
- * representing the type of a function, method, constructor, getter, or setter.
- */
-class FunctionTypeImpl extends TypeImpl implements FunctionType {
- /**
- * Return `true` if all of the name/type pairs in the first map are equal to the
- * corresponding name/type pairs in the second map. The maps are expected to iterate over their
- * entries in the same order in which those entries were added to the map.
- *
- * @param firstTypes the first map of name/type pairs being compared
- * @param secondTypes the second map of name/type pairs being compared
- * @param visitedElementPairs a set of visited element pairs
- * @return `true` if all of the name/type pairs in the first map are equal to the
- * corresponding name/type pairs in the second map
- */
- static bool _equals(Map<String, DartType> firstTypes, Map<String, DartType> secondTypes, Set<ElementPair> visitedElementPairs) {
- if (secondTypes.length != firstTypes.length) {
- return false;
+ AstNode get node {
+ if (isSynthetic) {
+ return null;
}
- JavaIterator<MapEntry<String, DartType>> firstIterator = new JavaIterator(getMapEntrySet(firstTypes));
- JavaIterator<MapEntry<String, DartType>> secondIterator = new JavaIterator(getMapEntrySet(secondTypes));
- while (firstIterator.hasNext) {
- MapEntry<String, DartType> firstEntry = firstIterator.next();
- MapEntry<String, DartType> secondEntry = secondIterator.next();
- if (firstEntry.getKey() != secondEntry.getKey() || !(firstEntry.getValue() as TypeImpl).internalEquals(secondEntry.getValue(), visitedElementPairs)) {
- return false;
- }
+ if (enclosingElement is ClassElement) {
+ return getNodeMatching((node) => node is MethodDeclaration);
}
- return true;
+ if (enclosingElement is CompilationUnitElement) {
+ return getNodeMatching((node) => node is FunctionDeclaration);
+ }
+ return null;
}
- /**
- * An array containing the actual types of the type arguments.
- */
- List<DartType> typeArguments = TypeImpl.EMPTY_ARRAY;
+ @override
+ int get hashCode => ObjectUtilities.combineHashCodes(super.hashCode, isGetter ? 1 : 2);
+
+ @override
+ bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+
+ @override
+ bool get isGetter => hasModifier(Modifier.GETTER);
+
+ @override
+ bool get isSetter => hasModifier(Modifier.SETTER);
+
+ @override
+ bool get isStatic => hasModifier(Modifier.STATIC);
/**
- * Initialize a newly created function type to be declared by the given element and to have the
- * given name.
+ * Set whether this accessor is abstract to correspond to the given value.
*
- * @param element the element representing the declaration of the function type
+ * @param isAbstract `true` if the accessor is abstract
*/
- FunctionTypeImpl.con1(ExecutableElement element) : super(element, element == null ? null : element.name);
+ void set abstract(bool isAbstract) {
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
/**
- * Initialize a newly created function type to be declared by the given element and to have the
- * given name.
+ * Set whether this accessor is a getter to correspond to the given value.
*
- * @param element the element representing the declaration of the function type
+ * @param isGetter `true` if the accessor is a getter
*/
- FunctionTypeImpl.con2(FunctionTypeAliasElement element) : super(element, element == null ? null : element.name);
-
- @override
- bool operator ==(Object object) => internalEquals(object, new Set<ElementPair>());
-
- @override
- String get displayName {
- String name = this.name;
- if (name == null || name.length == 0) {
- // TODO(brianwilkerson) Determine whether function types should ever have an empty name.
- List<DartType> normalParameterTypes = this.normalParameterTypes;
- List<DartType> optionalParameterTypes = this.optionalParameterTypes;
- Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
- DartType returnType = this.returnType;
- JavaStringBuilder builder = new JavaStringBuilder();
- builder.append("(");
- bool needsComma = false;
- if (normalParameterTypes.length > 0) {
- for (DartType type in normalParameterTypes) {
- if (needsComma) {
- builder.append(", ");
- } else {
- needsComma = true;
- }
- builder.append(type.displayName);
- }
- }
- if (optionalParameterTypes.length > 0) {
- if (needsComma) {
- builder.append(", ");
- needsComma = false;
- }
- builder.append("[");
- for (DartType type in optionalParameterTypes) {
- if (needsComma) {
- builder.append(", ");
- } else {
- needsComma = true;
- }
- builder.append(type.displayName);
- }
- builder.append("]");
- needsComma = true;
- }
- if (namedParameterTypes.length > 0) {
- if (needsComma) {
- builder.append(", ");
- needsComma = false;
- }
- builder.append("{");
- for (MapEntry<String, DartType> entry in getMapEntrySet(namedParameterTypes)) {
- if (needsComma) {
- builder.append(", ");
- } else {
- needsComma = true;
- }
- builder.append(entry.getKey());
- builder.append(": ");
- builder.append(entry.getValue().displayName);
- }
- builder.append("}");
- needsComma = true;
- }
- builder.append(")");
- builder.append(Element.RIGHT_ARROW);
- if (returnType == null) {
- builder.append("null");
- } else {
- builder.append(returnType.displayName);
- }
- name = builder.toString();
- }
- return name;
+ void set getter(bool isGetter) {
+ setModifier(Modifier.GETTER, isGetter);
}
- @override
- Map<String, DartType> get namedParameterTypes {
- LinkedHashMap<String, DartType> namedParameterTypes = new LinkedHashMap<String, DartType>();
- List<ParameterElement> parameters = baseParameters;
- if (parameters.length == 0) {
- return namedParameterTypes;
- }
- List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typeParameters);
- for (ParameterElement parameter in parameters) {
- if (parameter.parameterKind == ParameterKind.NAMED) {
- namedParameterTypes[parameter.name] = parameter.type.substitute2(typeArguments, typeParameters);
- }
- }
- return namedParameterTypes;
+ /**
+ * Set whether this accessor is a setter to correspond to the given value.
+ *
+ * @param isSetter `true` if the accessor is a setter
+ */
+ void set setter(bool isSetter) {
+ setModifier(Modifier.SETTER, isSetter);
}
- @override
- List<DartType> get normalParameterTypes {
- List<ParameterElement> parameters = baseParameters;
- if (parameters.length == 0) {
- return TypeImpl.EMPTY_ARRAY;
- }
- List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typeParameters);
- List<DartType> types = new List<DartType>();
- for (ParameterElement parameter in parameters) {
- if (parameter.parameterKind == ParameterKind.REQUIRED) {
- types.add(parameter.type.substitute2(typeArguments, typeParameters));
- }
- }
- return new List.from(types);
+ /**
+ * Set whether this accessor is static to correspond to the given value.
+ *
+ * @param isStatic `true` if the accessor is static
+ */
+ void set static(bool isStatic) {
+ setModifier(Modifier.STATIC, isStatic);
}
@override
- List<DartType> get optionalParameterTypes {
- List<ParameterElement> parameters = baseParameters;
- if (parameters.length == 0) {
- return TypeImpl.EMPTY_ARRAY;
- }
- List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typeParameters);
- List<DartType> types = new List<DartType>();
- for (ParameterElement parameter in parameters) {
- if (parameter.parameterKind == ParameterKind.POSITIONAL) {
- types.add(parameter.type.substitute2(typeArguments, typeParameters));
- }
- }
- return new List.from(types);
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(isGetter ? "get " : "set ");
+ builder.append(variable.displayName);
+ super.appendTo(builder);
}
+}
- @override
- List<ParameterElement> get parameters {
- List<ParameterElement> baseParameters = this.baseParameters;
- // no parameters, quick return
- int parameterCount = baseParameters.length;
- if (parameterCount == 0) {
- return baseParameters;
+/**
+ * Instances of the class `PropertyAccessorMember` represent a property accessor element
+ * defined in a parameterized type where the values of the type parameters are known.
+ */
+class PropertyAccessorMember extends ExecutableMember implements PropertyAccessorElement {
+ /**
+ * If the given property accessor's type is different when any type parameters from the defining
+ * type's declaration are replaced with the actual type arguments from the defining type, create a
+ * property accessor member representing the given property accessor. Return the member that was
+ * created, or the base accessor if no member was created.
+ *
+ * @param baseAccessor the base property accessor for which a member might be created
+ * @param definingType the type defining the parameters and arguments to be used in the
+ * substitution
+ * @return the property accessor element that will return the correctly substituted types
+ */
+ static PropertyAccessorElement from(PropertyAccessorElement baseAccessor, InterfaceType definingType) {
+ if (baseAccessor == null || definingType.typeArguments.length == 0) {
+ return baseAccessor;
}
- // create specialized parameters
- List<ParameterElement> specializedParameters = new List<ParameterElement>(parameterCount);
- for (int i = 0; i < parameterCount; i++) {
- specializedParameters[i] = ParameterMember.from(baseParameters[i], this);
+ FunctionType baseType = baseAccessor.type;
+ List<DartType> argumentTypes = definingType.typeArguments;
+ List<DartType> parameterTypes = definingType.element.type.typeArguments;
+ FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
+ if (baseType == substitutedType) {
+ return baseAccessor;
}
- return specializedParameters;
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
+ return new PropertyAccessorMember(baseAccessor, definingType);
}
+ /**
+ * Initialize a newly created element to represent a property accessor of the given parameterized
+ * type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
+ */
+ PropertyAccessorMember(PropertyAccessorElement baseElement, InterfaceType definingType) : super(baseElement, definingType);
+
@override
- DartType get returnType {
- DartType baseReturnType = this.baseReturnType;
- if (baseReturnType == null) {
- // TODO(brianwilkerson) This is a patch. The return type should never be null and we need to
- // understand why it is and fix it.
- return DynamicTypeImpl.instance;
- }
- return baseReturnType.substitute2(typeArguments, TypeParameterTypeImpl.getTypes(typeParameters));
- }
+ accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
@override
- List<TypeParameterElement> get typeParameters {
- Element element = this.element;
- if (element is FunctionTypeAliasElement) {
- return element.typeParameters;
- }
- ClassElement definingClass = element.getAncestor((element) => element is ClassElement);
- if (definingClass != null) {
- return definingClass.typeParameters;
- }
- return TypeParameterElementImpl.EMPTY_ARRAY;
- }
+ PropertyAccessorElement get baseElement => super.baseElement as PropertyAccessorElement;
@override
- int get hashCode {
- if (element == null) {
- return 0;
- }
- // Reference the arrays of parameters
- List<DartType> normalParameterTypes = this.normalParameterTypes;
- List<DartType> optionalParameterTypes = this.optionalParameterTypes;
- Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values;
- // Generate the hashCode
- int hashCode = returnType.hashCode;
- for (int i = 0; i < normalParameterTypes.length; i++) {
- hashCode = (hashCode << 1) + normalParameterTypes[i].hashCode;
- }
- for (int i = 0; i < optionalParameterTypes.length; i++) {
- hashCode = (hashCode << 1) + optionalParameterTypes[i].hashCode;
- }
- for (DartType type in namedParameterTypes) {
- hashCode = (hashCode << 1) + type.hashCode;
- }
- return hashCode;
- }
+ PropertyAccessorElement get correspondingGetter => from(baseElement.correspondingGetter, definingType);
@override
- bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
- // trivial base cases
- if (type == null) {
- return false;
- } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
- return true;
- } else if (type is! FunctionType) {
- return false;
- } else if (this == type) {
- return true;
- }
- FunctionType t = this;
- FunctionType s = type as FunctionType;
- List<DartType> tTypes = t.normalParameterTypes;
- List<DartType> tOpTypes = t.optionalParameterTypes;
- List<DartType> sTypes = s.normalParameterTypes;
- List<DartType> sOpTypes = s.optionalParameterTypes;
- // If one function has positional and the other has named parameters, return false.
- if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
- return false;
- }
- // named parameters case
- if (t.namedParameterTypes.length > 0) {
- // check that the number of required parameters are equal, and check that every t_i is
- // more specific than every s_i
- if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
- return false;
- } else if (t.normalParameterTypes.length > 0) {
- for (int i = 0; i < tTypes.length; i++) {
- if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(sTypes[i], withDynamic, visitedTypePairs)) {
- return false;
- }
- }
- }
- Map<String, DartType> namedTypesT = t.namedParameterTypes;
- Map<String, DartType> namedTypesS = s.namedParameterTypes;
- // if k >= m is false, return false: the passed function type has more named parameter types than this
- if (namedTypesT.length < namedTypesS.length) {
- return false;
- }
- // Loop through each element in S verifying that T has a matching parameter name and that the
- // corresponding type is more specific then the type in S.
- JavaIterator<MapEntry<String, DartType>> iteratorS = new JavaIterator(getMapEntrySet(namedTypesS));
- while (iteratorS.hasNext) {
- MapEntry<String, DartType> entryS = iteratorS.next();
- DartType typeT = namedTypesT[entryS.getKey()];
- if (typeT == null) {
- return false;
- }
- if (!(typeT as TypeImpl).isMoreSpecificThan2(entryS.getValue(), withDynamic, visitedTypePairs)) {
- return false;
- }
- }
- } else if (s.namedParameterTypes.length > 0) {
- return false;
- } else {
- // positional parameter case
- int tArgLength = tTypes.length + tOpTypes.length;
- int sArgLength = sTypes.length + sOpTypes.length;
- // Check that the total number of parameters in t is greater than or equal to the number of
- // parameters in s and that the number of required parameters in s is greater than or equal to
- // the number of required parameters in t.
- if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
- return false;
- }
- if (tOpTypes.length == 0 && sOpTypes.length == 0) {
- // No positional arguments, don't copy contents to new array
- for (int i = 0; i < sTypes.length; i++) {
- if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(sTypes[i], withDynamic, visitedTypePairs)) {
- return false;
- }
- }
- } else {
- // Else, we do have positional parameters, copy required and positional parameter types into
- // arrays to do the compare (for loop below).
- List<DartType> tAllTypes = new List<DartType>(sArgLength);
- for (int i = 0; i < tTypes.length; i++) {
- tAllTypes[i] = tTypes[i];
- }
- for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
- tAllTypes[i] = tOpTypes[j];
- }
- List<DartType> sAllTypes = new List<DartType>(sArgLength);
- for (int i = 0; i < sTypes.length; i++) {
- sAllTypes[i] = sTypes[i];
- }
- for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
- sAllTypes[i] = sOpTypes[j];
- }
- for (int i = 0; i < sAllTypes.length; i++) {
- if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan2(sAllTypes[i], withDynamic, visitedTypePairs)) {
- return false;
- }
- }
- }
+ PropertyAccessorElement get correspondingSetter => from(baseElement.correspondingSetter, definingType);
+
+ @override
+ Element get enclosingElement => baseElement.enclosingElement;
+
+ @override
+ PropertyInducingElement get variable {
+ PropertyInducingElement variable = baseElement.variable;
+ if (variable is FieldElement) {
+ return FieldMember.from(variable, definingType);
}
- DartType tRetType = t.returnType;
- DartType sRetType = s.returnType;
- return sRetType.isVoid || (tRetType as TypeImpl).isMoreSpecificThan2(sRetType, withDynamic, visitedTypePairs);
+ return variable;
}
@override
- bool isAssignableTo(DartType type) => isSubtypeOf2(type, new Set<TypeImpl_TypePair>());
+ bool get isAbstract => baseElement.isAbstract;
@override
- FunctionTypeImpl substitute3(List<DartType> argumentTypes) => substitute2(argumentTypes, typeArguments);
+ bool get isGetter => baseElement.isGetter;
@override
- FunctionTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
- if (argumentTypes.length != parameterTypes.length) {
- throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
- }
- if (argumentTypes.length == 0) {
- return this;
- }
- Element element = this.element;
- FunctionTypeImpl newType = (element is ExecutableElement) ? new FunctionTypeImpl.con1(element) : new FunctionTypeImpl.con2(element as FunctionTypeAliasElement);
- newType.typeArguments = TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
- return newType;
- }
+ bool get isSetter => baseElement.isSetter;
@override
- void appendTo(JavaStringBuilder builder) {
- List<DartType> normalParameterTypes = this.normalParameterTypes;
- List<DartType> optionalParameterTypes = this.optionalParameterTypes;
- Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
- DartType returnType = this.returnType;
- builder.append("(");
- bool needsComma = false;
- if (normalParameterTypes.length > 0) {
- for (DartType type in normalParameterTypes) {
- if (needsComma) {
- builder.append(", ");
- } else {
- needsComma = true;
- }
- (type as TypeImpl).appendTo(builder);
- }
- }
- if (optionalParameterTypes.length > 0) {
- if (needsComma) {
- builder.append(", ");
- needsComma = false;
- }
- builder.append("[");
- for (DartType type in optionalParameterTypes) {
- if (needsComma) {
- builder.append(", ");
- } else {
- needsComma = true;
- }
- (type as TypeImpl).appendTo(builder);
- }
- builder.append("]");
- needsComma = true;
+ String toString() {
+ PropertyAccessorElement baseElement = this.baseElement;
+ List<ParameterElement> parameters = this.parameters;
+ FunctionType type = this.type;
+ JavaStringBuilder builder = new JavaStringBuilder();
+ if (isGetter) {
+ builder.append("get ");
+ } else {
+ builder.append("set ");
}
- if (namedParameterTypes.length > 0) {
- if (needsComma) {
+ builder.append(baseElement.enclosingElement.displayName);
+ builder.append(".");
+ builder.append(baseElement.displayName);
+ builder.append("(");
+ int parameterCount = parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ if (i > 0) {
builder.append(", ");
- needsComma = false;
- }
- builder.append("{");
- for (MapEntry<String, DartType> entry in getMapEntrySet(namedParameterTypes)) {
- if (needsComma) {
- builder.append(", ");
- } else {
- needsComma = true;
- }
- builder.append(entry.getKey());
- builder.append(": ");
- (entry.getValue() as TypeImpl).appendTo(builder);
}
- builder.append("}");
- needsComma = true;
+ builder.append(parameters[i]).toString();
}
builder.append(")");
- builder.append(Element.RIGHT_ARROW);
- if (returnType == null) {
- builder.append("null");
- } else {
- (returnType as TypeImpl).appendTo(builder);
+ if (type != null) {
+ builder.append(Element.RIGHT_ARROW);
+ builder.append(type.returnType);
}
+ return builder.toString();
}
+ @override
+ InterfaceType get definingType => super.definingType as InterfaceType;
+}
+
+/**
+ * The interface `PropertyInducingElement` defines the behavior of elements representing a
+ * variable that has an associated getter and possibly a setter. Note that explicitly defined
+ * variables implicitly define a synthetic getter and that non-`final` explicitly defined
+ * variables implicitly define a synthetic setter. Symmetrically, synthetic fields are implicitly
+ * created for explicitly defined getters and setters. The following rules apply:
+ * * Every explicit variable is represented by a non-synthetic [PropertyInducingElement].
+ * * Every explicit variable induces a getter and possibly a setter, both of which are represented
+ * by synthetic [PropertyAccessorElement]s.
+ * * Every explicit getter or setter is represented by a non-synthetic
+ * [PropertyAccessorElement].
+ * * Every explicit getter or setter (or pair thereof if they have the same name) induces a
+ * variable that is represented by a synthetic [PropertyInducingElement].
+ */
+abstract class PropertyInducingElement implements VariableElement {
/**
- * @return the base parameter elements of this function element, not `null`.
+ * Return the getter associated with this variable. If this variable was explicitly defined (is
+ * not synthetic) then the getter associated with it will be synthetic.
+ *
+ * @return the getter associated with this variable
*/
- List<ParameterElement> get baseParameters {
- Element element = this.element;
- if (element is ExecutableElement) {
- return element.parameters;
- } else {
- return (element as FunctionTypeAliasElement).parameters;
- }
- }
-
- @override
- bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) {
- if (object is! FunctionTypeImpl) {
- return false;
- }
- FunctionTypeImpl otherType = object as FunctionTypeImpl;
- // If the visitedTypePairs already has the pair (this, type), use the elements to determine equality
- ElementPair elementPair = new ElementPair(element, otherType.element);
- if (!visitedElementPairs.add(elementPair)) {
- return elementPair.firstElt == elementPair.secondElt;
- }
- // Compute the result
- bool result = TypeImpl.equalArrays(normalParameterTypes, otherType.normalParameterTypes, visitedElementPairs) && TypeImpl.equalArrays(optionalParameterTypes, otherType.optionalParameterTypes, visitedElementPairs) && _equals(namedParameterTypes, otherType.namedParameterTypes, visitedElementPairs) && (returnType as TypeImpl).internalEquals(otherType.returnType, visitedElementPairs);
- // Remove the pair from our visited pairs list
- visitedElementPairs.remove(elementPair);
- // Return the result
- return result;
- }
+ PropertyAccessorElement get getter;
- @override
- bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
- // trivial base cases
- if (type == null) {
- return false;
- } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
- return true;
- } else if (type is! FunctionType) {
- return false;
- } else if (this == type) {
- return true;
- }
- FunctionType t = this;
- FunctionType s = type as FunctionType;
- List<DartType> tTypes = t.normalParameterTypes;
- List<DartType> tOpTypes = t.optionalParameterTypes;
- List<DartType> sTypes = s.normalParameterTypes;
- List<DartType> sOpTypes = s.optionalParameterTypes;
- // If one function has positional and the other has named parameters, return false.
- if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
- return false;
- }
- // named parameters case
- if (t.namedParameterTypes.length > 0) {
- // check that the number of required parameters are equal, and check that every t_i is
- // assignable to every s_i
- if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
- return false;
- } else if (t.normalParameterTypes.length > 0) {
- for (int i = 0; i < tTypes.length; i++) {
- if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePairs)) {
- return false;
- }
- }
- }
- Map<String, DartType> namedTypesT = t.namedParameterTypes;
- Map<String, DartType> namedTypesS = s.namedParameterTypes;
- // if k >= m is false, return false: the passed function type has more named parameter types than this
- if (namedTypesT.length < namedTypesS.length) {
- return false;
- }
- // Loop through each element in S verifying that T has a matching parameter name and that the
- // corresponding type is assignable to the type in S.
- JavaIterator<MapEntry<String, DartType>> iteratorS = new JavaIterator(getMapEntrySet(namedTypesS));
- while (iteratorS.hasNext) {
- MapEntry<String, DartType> entryS = iteratorS.next();
- DartType typeT = namedTypesT[entryS.getKey()];
- if (typeT == null) {
- return false;
- }
- if (!(typeT as TypeImpl).isAssignableTo2(entryS.getValue(), visitedTypePairs)) {
- return false;
- }
- }
- } else if (s.namedParameterTypes.length > 0) {
- return false;
- } else {
- // positional parameter case
- int tArgLength = tTypes.length + tOpTypes.length;
- int sArgLength = sTypes.length + sOpTypes.length;
- // Check that the total number of parameters in t is greater than or equal to the number of
- // parameters in s and that the number of required parameters in s is greater than or equal to
- // the number of required parameters in t.
- if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
- return false;
- }
- if (tOpTypes.length == 0 && sOpTypes.length == 0) {
- // No positional arguments, don't copy contents to new array
- for (int i = 0; i < sTypes.length; i++) {
- if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePairs)) {
- return false;
- }
- }
- } else {
- // Else, we do have positional parameters, copy required and positional parameter types into
- // arrays to do the compare (for loop below).
- List<DartType> tAllTypes = new List<DartType>(sArgLength);
- for (int i = 0; i < tTypes.length; i++) {
- tAllTypes[i] = tTypes[i];
- }
- for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
- tAllTypes[i] = tOpTypes[j];
- }
- List<DartType> sAllTypes = new List<DartType>(sArgLength);
- for (int i = 0; i < sTypes.length; i++) {
- sAllTypes[i] = sTypes[i];
- }
- for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
- sAllTypes[i] = sOpTypes[j];
- }
- for (int i = 0; i < sAllTypes.length; i++) {
- if (!(tAllTypes[i] as TypeImpl).isAssignableTo2(sAllTypes[i], visitedTypePairs)) {
- return false;
- }
- }
- }
- }
- DartType tRetType = t.returnType;
- DartType sRetType = s.returnType;
- return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo2(sRetType, visitedTypePairs);
- }
+ /**
+ * Return the setter associated with this variable, or `null` if the variable is effectively
+ * `final` and therefore does not have a setter associated with it. (This can happen either
+ * because the variable is explicitly defined as being `final` or because the variable is
+ * induced by an explicit getter that does not have a corresponding setter.) If this variable was
+ * explicitly defined (is not synthetic) then the setter associated with it will be synthetic.
+ *
+ * @return the setter associated with this variable
+ */
+ PropertyAccessorElement get setter;
/**
- * Return the return type defined by this function's element.
+ * Return `true` if this element is a static element. A static element is an element that is
+ * not associated with a particular instance, but rather with an entire library or class.
*
- * @return the return type defined by this function's element
+ * @return `true` if this executable element is a static element
*/
- DartType get baseReturnType {
- Element element = this.element;
- if (element is ExecutableElement) {
- return element.returnType;
- } else {
- return (element as FunctionTypeAliasElement).returnType;
- }
- }
+ bool get isStatic;
}
/**
- * Instances of the class `InterfaceTypeImpl` defines the behavior common to objects
- * representing the type introduced by either a class or an interface, or a reference to such a
- * type.
+ * Instances of the class `PropertyInducingElementImpl` implement a
+ * `PropertyInducingElement`.
*/
-class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
+abstract class PropertyInducingElementImpl extends VariableElementImpl implements PropertyInducingElement {
/**
- * An empty array of types.
+ * The getter associated with this element.
*/
- static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>(0);
+ PropertyAccessorElement getter;
/**
- * This method computes the longest inheritance path from some passed [Type] to Object.
- *
- * @param type the [Type] to compute the longest inheritance path of from the passed
- * [Type] to Object
- * @return the computed longest inheritance path to Object
- * @see InterfaceType#getLeastUpperBound(Type)
+ * The setter associated with this element, or `null` if the element is effectively
+ * `final` and therefore does not have a setter associated with it.
*/
- static int computeLongestInheritancePathToObject(InterfaceType type) => _computeLongestInheritancePathToObject(type, 0, new Set<ClassElement>());
+ PropertyAccessorElement setter;
/**
- * Returns the set of all superinterfaces of the passed [Type].
- *
- * @param type the [Type] to compute the set of superinterfaces of
- * @return the [Set] of superinterfaces of the passed [Type]
- * @see #getLeastUpperBound(Type)
+ * An empty array of elements.
*/
- static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => _computeSuperinterfaceSet(type, new Set<InterfaceType>());
+ static List<PropertyInducingElement> EMPTY_ARRAY = new List<PropertyInducingElement>(0);
/**
- * This method computes the longest inheritance path from some passed [Type] to Object. This
- * method calls itself recursively, callers should use the public method
- * [computeLongestInheritancePathToObject].
+ * Initialize a newly created element to have the given name.
*
- * @param type the [Type] to compute the longest inheritance path of from the passed
- * [Type] to Object
- * @param depth a field used recursively
- * @param visitedClasses the classes that have already been visited
- * @return the computed longest inheritance path to Object
- * @see #computeLongestInheritancePathToObject(Type)
- * @see #getLeastUpperBound(Type)
+ * @param name the name of this element
*/
- static int _computeLongestInheritancePathToObject(InterfaceType type, int depth, Set<ClassElement> visitedClasses) {
- ClassElement classElement = type.element;
- // Object case
- if (classElement.supertype == null || visitedClasses.contains(classElement)) {
- return depth;
- }
- int longestPath = 1;
- try {
- visitedClasses.add(classElement);
- List<InterfaceType> superinterfaces = classElement.interfaces;
- int pathLength;
- if (superinterfaces.length > 0) {
- // loop through each of the superinterfaces recursively calling this method and keeping track
- // of the longest path to return
- for (InterfaceType superinterface in superinterfaces) {
- pathLength = _computeLongestInheritancePathToObject(superinterface, depth + 1, visitedClasses);
- if (pathLength > longestPath) {
- longestPath = pathLength;
- }
- }
- }
- // finally, perform this same check on the super type
- // TODO(brianwilkerson) Does this also need to add in the number of mixin classes?
- InterfaceType supertype = classElement.supertype;
- pathLength = _computeLongestInheritancePathToObject(supertype, depth + 1, visitedClasses);
- if (pathLength > longestPath) {
- longestPath = pathLength;
- }
- } finally {
- visitedClasses.remove(classElement);
- }
- return longestPath;
- }
+ PropertyInducingElementImpl.con1(Identifier name) : super.forNode(name);
/**
- * Returns the set of all superinterfaces of the passed [Type]. This is a recursive method,
- * callers should call the public [computeSuperinterfaceSet].
+ * Initialize a newly created synthetic element to have the given name.
*
- * @param type the [Type] to compute the set of superinterfaces of
- * @param set a [HashSet] used recursively by this method
- * @return the [Set] of superinterfaces of the passed [Type]
- * @see #computeSuperinterfaceSet(Type)
- * @see #getLeastUpperBound(Type)
+ * @param name the name of this element
*/
- static Set<InterfaceType> _computeSuperinterfaceSet(InterfaceType type, Set<InterfaceType> set) {
- Element element = type.element;
- if (element != null) {
- List<InterfaceType> superinterfaces = type.interfaces;
- for (InterfaceType superinterface in superinterfaces) {
- if (set.add(superinterface)) {
- _computeSuperinterfaceSet(superinterface, set);
- }
- }
- InterfaceType supertype = type.superclass;
- if (supertype != null) {
- if (set.add(supertype)) {
- _computeSuperinterfaceSet(supertype, set);
- }
- }
- }
- return set;
+ PropertyInducingElementImpl.con2(String name) : super(name, -1) {
+ synthetic = true;
+ }
+}
+
+/**
+ * Instances of the class `RecursiveElementVisitor` implement an element visitor that will
+ * recursively visit all of the element in an element model. For example, using an instance of this
+ * class to visit a [CompilationUnitElement] will also cause all of the types in the
+ * compilation unit to be visited.
+ *
+ * Subclasses that override a visit method must either invoke the overridden visit method or must
+ * explicitly ask the visited element to visit its children. Failure to do so will cause the
+ * children of the visited element to not be visited.
+ */
+class RecursiveElementVisitor<R> implements ElementVisitor<R> {
+ @override
+ R visitAngularComponentElement(AngularComponentElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularControllerElement(AngularControllerElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularDirectiveElement(AngularDecoratorElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularFormatterElement(AngularFormatterElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularPropertyElement(AngularPropertyElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularScopePropertyElement(AngularScopePropertyElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularSelectorElement(AngularSelectorElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAngularViewElement(AngularViewElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitClassElement(ClassElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitCompilationUnitElement(CompilationUnitElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitConstructorElement(ConstructorElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitExportElement(ExportElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFieldElement(FieldElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFieldFormalParameterElement(FieldFormalParameterElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionElement(FunctionElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitHtmlElement(HtmlElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitImportElement(ImportElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitLabelElement(LabelElement element) {
+ element.visitChildren(this);
+ return null;
}
- /**
- * Return the intersection of the given sets of types, where intersection is based on the equality
- * of the types themselves.
- *
- * @param first the first set of types to be intersected
- * @param second the second set of types to be intersected
- * @return the intersection of the given sets of types
- */
- static List<InterfaceType> _intersection(Set<InterfaceType> first, Set<InterfaceType> second) {
- Set<InterfaceType> result = new Set<InterfaceType>.from(first);
- result.retainAll(second);
- return new List.from(result);
+ @override
+ R visitLibraryElement(LibraryElement element) {
+ element.visitChildren(this);
+ return null;
}
- /**
- * Return the "least upper bound" of the given types under the assumption that the types have the
- * same element and differ only in terms of the type arguments. The resulting type is composed by
- * comparing the corresponding type arguments, keeping those that are the same, and using
- * 'dynamic' for those that are different.
- *
- * @param firstType the first type
- * @param secondType the second type
- * @return the "least upper bound" of the given types
- */
- static InterfaceType _leastUpperBound(InterfaceType firstType, InterfaceType secondType) {
- if (firstType == secondType) {
- return firstType;
- }
- List<DartType> firstArguments = firstType.typeArguments;
- List<DartType> secondArguments = secondType.typeArguments;
- int argumentCount = firstArguments.length;
- if (argumentCount == 0) {
- return firstType;
- }
- List<DartType> lubArguments = new List<DartType>(argumentCount);
- for (int i = 0; i < argumentCount; i++) {
- //
- // Ideally we would take the least upper bound of the two argument types, but this can cause
- // an infinite recursion (such as when finding the least upper bound of String and num).
- //
- if (firstArguments[i] == secondArguments[i]) {
- lubArguments[i] = firstArguments[i];
- }
- if (lubArguments[i] == null) {
- lubArguments[i] = DynamicTypeImpl.instance;
- }
- }
- InterfaceTypeImpl lub = new InterfaceTypeImpl.con1(firstType.element);
- lub.typeArguments = lubArguments;
- return lub;
+ @override
+ R visitLocalVariableElement(LocalVariableElement element) {
+ element.visitChildren(this);
+ return null;
}
- /**
- * An array containing the actual types of the type arguments.
- */
- List<DartType> typeArguments = TypeImpl.EMPTY_ARRAY;
+ @override
+ R visitMethodElement(MethodElement element) {
+ element.visitChildren(this);
+ return null;
+ }
- /**
- * Initialize a newly created type to be declared by the given element.
- *
- * @param element the element representing the declaration of the type
- */
- InterfaceTypeImpl.con1(ClassElement element) : super(element, element.displayName);
+ @override
+ R visitMultiplyDefinedElement(MultiplyDefinedElement element) {
+ element.visitChildren(this);
+ return null;
+ }
- /**
- * Initialize a newly created type to have the given name. This constructor should only be used in
- * cases where there is no declaration of the type.
- *
- * @param name the name of the type
- */
- InterfaceTypeImpl.con2(String name) : super(null, name);
+ @override
+ R visitParameterElement(ParameterElement element) {
+ element.visitChildren(this);
+ return null;
+ }
@override
- bool operator ==(Object object) => internalEquals(object, new Set<ElementPair>());
+ R visitPolymerAttributeElement(PolymerAttributeElement element) {
+ element.visitChildren(this);
+ return null;
+ }
@override
- List<PropertyAccessorElement> get accessors {
- List<PropertyAccessorElement> accessors = element.accessors;
- List<PropertyAccessorElement> members = new List<PropertyAccessorElement>(accessors.length);
- for (int i = 0; i < accessors.length; i++) {
- members[i] = PropertyAccessorMember.from(accessors[i], this);
- }
- return members;
+ R visitPolymerTagDartElement(PolymerTagDartElement element) {
+ element.visitChildren(this);
+ return null;
}
@override
- String get displayName {
- String name = this.name;
- List<DartType> typeArguments = this.typeArguments;
- bool allDynamic = true;
- for (DartType type in typeArguments) {
- if (type != null && !type.isDynamic) {
- allDynamic = false;
- break;
- }
- }
- // If there is at least one non-dynamic type, then list them out
- if (!allDynamic) {
- JavaStringBuilder builder = new JavaStringBuilder();
- builder.append(name);
- builder.append("<");
- for (int i = 0; i < typeArguments.length; i++) {
- if (i != 0) {
- builder.append(", ");
- }
- DartType typeArg = typeArguments[i];
- builder.append(typeArg.displayName);
- }
- builder.append(">");
- name = builder.toString();
- }
- return name;
+ R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) {
+ element.visitChildren(this);
+ return null;
}
@override
- ClassElement get element => super.element as ClassElement;
+ R visitPrefixElement(PrefixElement element) {
+ element.visitChildren(this);
+ return null;
+ }
@override
- PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember.from((element as ClassElementImpl).getGetter(getterName), this);
+ R visitPropertyAccessorElement(PropertyAccessorElement element) {
+ element.visitChildren(this);
+ return null;
+ }
@override
- List<InterfaceType> get interfaces {
- ClassElement classElement = element;
- List<InterfaceType> interfaces = classElement.interfaces;
- List<TypeParameterElement> typeParameters = classElement.typeParameters;
- List<DartType> parameterTypes = classElement.type.typeArguments;
- if (typeParameters.length == 0) {
- return interfaces;
- }
- int count = interfaces.length;
- List<InterfaceType> typedInterfaces = new List<InterfaceType>(count);
- for (int i = 0; i < count; i++) {
- typedInterfaces[i] = interfaces[i].substitute2(typeArguments, parameterTypes);
- }
- return typedInterfaces;
+ R visitTopLevelVariableElement(TopLevelVariableElement element) {
+ element.visitChildren(this);
+ return null;
}
@override
- DartType getLeastUpperBound(DartType type) {
- // quick check for self
- if (identical(type, this)) {
- return this;
- }
- // dynamic
- DartType dynamicType = DynamicTypeImpl.instance;
- if (identical(this, dynamicType) || identical(type, dynamicType)) {
- return dynamicType;
- }
- // TODO (jwren) opportunity here for a better, faster algorithm if this turns out to be a bottle-neck
- if (type is! InterfaceType) {
- return null;
- }
- // new names to match up with the spec
- InterfaceType i = this;
- InterfaceType j = type as InterfaceType;
- // compute set of supertypes
- Set<InterfaceType> si = computeSuperinterfaceSet(i);
- Set<InterfaceType> sj = computeSuperinterfaceSet(j);
- // union si with i and sj with j
- si.add(i);
- sj.add(j);
- // compute intersection, reference as set 's'
- List<InterfaceType> s = _intersection(si, sj);
- // for each element in Set s, compute the largest inheritance path to Object
- List<int> depths = new List<int>.filled(s.length, 0);
- int maxDepth = 0;
- for (int n = 0; n < s.length; n++) {
- depths[n] = computeLongestInheritancePathToObject(s[n]);
- if (depths[n] > maxDepth) {
- maxDepth = depths[n];
- }
- }
- // ensure that the currently computed maxDepth is unique,
- // otherwise, decrement and test for uniqueness again
- for (; maxDepth >= 0; maxDepth--) {
- int indexOfLeastUpperBound = -1;
- int numberOfTypesAtMaxDepth = 0;
- for (int m = 0; m < depths.length; m++) {
- if (depths[m] == maxDepth) {
- numberOfTypesAtMaxDepth++;
- indexOfLeastUpperBound = m;
- }
- }
- if (numberOfTypesAtMaxDepth == 1) {
- return s[indexOfLeastUpperBound];
+ R visitTypeParameterElement(TypeParameterElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+}
+
+/**
+ * The interface `ShowElementCombinator` defines the behavior of combinators that cause some
+ * of the names in a namespace to be visible (and the rest hidden) when being imported.
+ */
+abstract class ShowElementCombinator implements NamespaceCombinator {
+ /**
+ * Return the offset of the character immediately following the last character of this node.
+ *
+ * @return the offset of the character just past this node
+ */
+ int get end;
+
+ /**
+ * Return the offset of the 'show' keyword of this element.
+ *
+ * @return the offset of the 'show' keyword of this element
+ */
+ int get offset;
+
+ /**
+ * Return an array containing the names that are to be made visible in the importing library if
+ * they are defined in the imported library.
+ *
+ * @return the names from the imported library that are visible in the importing library
+ */
+ List<String> get shownNames;
+}
+
+/**
+ * Instances of the class `ShowElementCombinatorImpl` implement a
+ * [ShowElementCombinator].
+ */
+class ShowElementCombinatorImpl implements ShowElementCombinator {
+ /**
+ * The names that are to be made visible in the importing library if they are defined in the
+ * imported library.
+ */
+ List<String> shownNames = StringUtilities.EMPTY_ARRAY;
+
+ /**
+ * 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;
+
+ @override
+ String toString() {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append("show ");
+ int count = shownNames.length;
+ for (int i = 0; i < count; i++) {
+ if (i > 0) {
+ builder.append(", ");
}
+ builder.append(shownNames[i]);
}
- // illegal state, log and return null- Object at maxDepth == 0 should always return itself as
- // the least upper bound.
- // TODO (jwren) log the error state
- return null;
+ return builder.toString();
}
+}
+/**
+ * Instances of the class `SimpleElementVisitor` implement an element visitor that will do
+ * nothing when visiting an element. It is intended to be a superclass for classes that use the
+ * visitor pattern primarily as a dispatch mechanism (and hence don't need to recursively visit a
+ * whole structure) and that only need to visit a small number of element types.
+ */
+class SimpleElementVisitor<R> implements ElementVisitor<R> {
@override
- MethodElement getMethod(String methodName) => MethodMember.from((element as ClassElementImpl).getMethod(methodName), this);
+ R visitAngularComponentElement(AngularComponentElement element) => null;
@override
- List<MethodElement> get methods {
- List<MethodElement> methods = element.methods;
- List<MethodElement> members = new List<MethodElement>(methods.length);
- for (int i = 0; i < methods.length; i++) {
- members[i] = MethodMember.from(methods[i], this);
- }
- return members;
- }
+ R visitAngularControllerElement(AngularControllerElement element) => null;
@override
- List<InterfaceType> get mixins {
- ClassElement classElement = element;
- List<InterfaceType> mixins = classElement.mixins;
- List<TypeParameterElement> typeParameters = classElement.typeParameters;
- List<DartType> parameterTypes = classElement.type.typeArguments;
- if (typeParameters.length == 0) {
- return mixins;
- }
- int count = mixins.length;
- List<InterfaceType> typedMixins = new List<InterfaceType>(count);
- for (int i = 0; i < count; i++) {
- typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes);
- }
- return typedMixins;
- }
+ R visitAngularDirectiveElement(AngularDecoratorElement element) => null;
@override
- PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember.from((element as ClassElementImpl).getSetter(setterName), this);
+ R visitAngularFormatterElement(AngularFormatterElement element) => null;
@override
- InterfaceType get superclass {
- ClassElement classElement = element;
- InterfaceType supertype = classElement.supertype;
- if (supertype == null) {
- return null;
- }
- return supertype.substitute2(typeArguments, classElement.type.typeArguments);
- }
+ R visitAngularPropertyElement(AngularPropertyElement element) => null;
@override
- List<TypeParameterElement> get typeParameters => element.typeParameters;
+ R visitAngularScopePropertyElement(AngularScopePropertyElement element) => null;
@override
- int get hashCode {
- ClassElement element = this.element;
- if (element == null) {
- return 0;
- }
- return element.hashCode;
- }
+ R visitAngularSelectorElement(AngularSelectorElement element) => null;
@override
- bool get isDartCoreFunction {
- ClassElement element = this.element;
- if (element == null) {
- return false;
- }
- return element.name == "Function" && element.library.isDartCore;
- }
+ R visitAngularViewElement(AngularViewElement element) => null;
@override
- bool isDirectSupertypeOf(InterfaceType type) {
- InterfaceType i = this;
- InterfaceType j = type;
- ClassElement jElement = j.element;
- InterfaceType supertype = jElement.supertype;
- //
- // If J has no direct supertype then it is Object, and Object has no direct supertypes.
- //
- if (supertype == null) {
- return false;
- }
- //
- // I is listed in the extends clause of J.
- //
- List<DartType> jArgs = j.typeArguments;
- List<DartType> jVars = jElement.type.typeArguments;
- supertype = supertype.substitute2(jArgs, jVars);
- if (supertype == i) {
- return true;
- }
- //
- // I is listed in the implements clause of J.
- //
- for (InterfaceType interfaceType in jElement.interfaces) {
- interfaceType = interfaceType.substitute2(jArgs, jVars);
- if (interfaceType == i) {
- return true;
- }
- }
- //
- // I is listed in the with clause of J.
- //
- for (InterfaceType mixinType in jElement.mixins) {
- mixinType = mixinType.substitute2(jArgs, jVars);
- if (mixinType == i) {
- return true;
- }
- }
- //
- // J is a mixin application of the mixin of I.
- //
- // TODO(brianwilkerson) Determine whether this needs to be implemented or whether it is covered
- // by the case above.
- return false;
- }
+ R visitClassElement(ClassElement element) => null;
@override
- bool get isObject => element.supertype == null;
+ R visitCompilationUnitElement(CompilationUnitElement element) => null;
@override
- ConstructorElement lookUpConstructor(String constructorName, LibraryElement library) {
- // prepare base ConstructorElement
- ConstructorElement constructorElement;
- if (constructorName == null) {
- constructorElement = element.unnamedConstructor;
- } else {
- constructorElement = element.getNamedConstructor(constructorName);
- }
- // not found or not accessible
- if (constructorElement == null || !constructorElement.isAccessibleIn(library)) {
- return null;
- }
- // return member
- return ConstructorMember.from(constructorElement, this);
- }
+ R visitConstructorElement(ConstructorElement element) => null;
@override
- PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library) {
- PropertyAccessorElement element = getGetter(getterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- return lookUpGetterInSuperclass(getterName, library);
- }
+ R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => null;
@override
- PropertyAccessorElement lookUpGetterInSuperclass(String getterName, LibraryElement library) {
- for (InterfaceType mixin in mixins) {
- PropertyAccessorElement element = mixin.getGetter(getterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- Set<ClassElement> visitedClasses = new Set<ClassElement>();
- InterfaceType supertype = superclass;
- ClassElement supertypeElement = supertype == null ? null : supertype.element;
- while (supertype != null && !visitedClasses.contains(supertypeElement)) {
- visitedClasses.add(supertypeElement);
- PropertyAccessorElement element = supertype.getGetter(getterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- for (InterfaceType mixin in supertype.mixins) {
- element = mixin.getGetter(getterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- supertype = supertype.superclass;
- supertypeElement = supertype == null ? null : supertype.element;
- }
- return null;
- }
+ R visitExportElement(ExportElement element) => null;
@override
- MethodElement lookUpMethod(String methodName, LibraryElement library) {
- MethodElement element = getMethod(methodName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- return lookUpMethodInSuperclass(methodName, library);
- }
+ R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => null;
@override
- MethodElement lookUpMethodInSuperclass(String methodName, LibraryElement library) {
- for (InterfaceType mixin in mixins) {
- MethodElement element = mixin.getMethod(methodName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- Set<ClassElement> visitedClasses = new Set<ClassElement>();
- InterfaceType supertype = superclass;
- ClassElement supertypeElement = supertype == null ? null : supertype.element;
- while (supertype != null && !visitedClasses.contains(supertypeElement)) {
- visitedClasses.add(supertypeElement);
- MethodElement element = supertype.getMethod(methodName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- for (InterfaceType mixin in supertype.mixins) {
- element = mixin.getMethod(methodName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- supertype = supertype.superclass;
- supertypeElement = supertype == null ? null : supertype.element;
- }
- return null;
- }
+ R visitFieldElement(FieldElement element) => null;
@override
- PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library) {
- PropertyAccessorElement element = getSetter(setterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- return lookUpSetterInSuperclass(setterName, library);
- }
+ R visitFieldFormalParameterElement(FieldFormalParameterElement element) => null;
+
+ @override
+ R visitFunctionElement(FunctionElement element) => null;
+
+ @override
+ R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null;
+
+ @override
+ R visitHtmlElement(HtmlElement element) => null;
+
+ @override
+ R visitImportElement(ImportElement element) => null;
+
+ @override
+ R visitLabelElement(LabelElement element) => null;
+
+ @override
+ R visitLibraryElement(LibraryElement element) => null;
+
+ @override
+ R visitLocalVariableElement(LocalVariableElement element) => null;
+
+ @override
+ R visitMethodElement(MethodElement element) => null;
+
+ @override
+ R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null;
@override
- PropertyAccessorElement lookUpSetterInSuperclass(String setterName, LibraryElement library) {
- for (InterfaceType mixin in mixins) {
- PropertyAccessorElement element = mixin.getSetter(setterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- Set<ClassElement> visitedClasses = new Set<ClassElement>();
- InterfaceType supertype = superclass;
- ClassElement supertypeElement = supertype == null ? null : supertype.element;
- while (supertype != null && !visitedClasses.contains(supertypeElement)) {
- visitedClasses.add(supertypeElement);
- PropertyAccessorElement element = supertype.getSetter(setterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- for (InterfaceType mixin in supertype.mixins) {
- element = mixin.getSetter(setterName);
- if (element != null && element.isAccessibleIn(library)) {
- return element;
- }
- }
- supertype = supertype.superclass;
- supertypeElement = supertype == null ? null : supertype.element;
- }
- return null;
- }
+ R visitParameterElement(ParameterElement element) => null;
@override
- InterfaceTypeImpl substitute4(List<DartType> argumentTypes) => substitute2(argumentTypes, typeArguments);
+ R visitPolymerAttributeElement(PolymerAttributeElement element) => null;
@override
- InterfaceTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
- if (argumentTypes.length != parameterTypes.length) {
- throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
- }
- if (argumentTypes.length == 0 || typeArguments.length == 0) {
- return this;
- }
- List<DartType> newTypeArguments = TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
- if (JavaArrays.equals(newTypeArguments, typeArguments)) {
- return this;
- }
- InterfaceTypeImpl newType = new InterfaceTypeImpl.con1(element);
- newType.typeArguments = newTypeArguments;
- return newType;
- }
+ R visitPolymerTagDartElement(PolymerTagDartElement element) => null;
@override
- void appendTo(JavaStringBuilder builder) {
- builder.append(name);
- int argumentCount = typeArguments.length;
- if (argumentCount > 0) {
- builder.append("<");
- for (int i = 0; i < argumentCount; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- (typeArguments[i] as TypeImpl).appendTo(builder);
- }
- builder.append(">");
- }
- }
+ R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) => null;
@override
- bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) {
- if (object is! InterfaceTypeImpl) {
- return false;
- }
- InterfaceTypeImpl otherType = object as InterfaceTypeImpl;
- return (element == otherType.element) && TypeImpl.equalArrays(typeArguments, otherType.typeArguments, visitedElementPairs);
- }
+ R visitPrefixElement(PrefixElement element) => null;
@override
- bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
- //
- // S is dynamic.
- // The test to determine whether S is dynamic is done here because dynamic is not an instance of
- // InterfaceType.
- //
- if (identical(type, DynamicTypeImpl.instance)) {
- return true;
- } else if (type is! InterfaceType) {
- return false;
- }
- return _isMoreSpecificThan(type as InterfaceType, new Set<ClassElement>(), withDynamic, visitedTypePairs);
- }
+ R visitPropertyAccessorElement(PropertyAccessorElement element) => null;
@override
- bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
- //
- // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S
- //
- if (type.isDynamic) {
- return true;
- } else if (type is TypeParameterType) {
- return false;
- } else if (type is FunctionType) {
- ClassElement element = this.element;
- MethodElement callMethod = element.lookUpMethod("call", element.library);
- if (callMethod != null) {
- return callMethod.type.isSubtypeOf(type);
- }
- return false;
- } else if (type is! InterfaceType) {
- return false;
- } else if (this == type) {
- return true;
- }
- return _isSubtypeOf(type as InterfaceType, new Set<ClassElement>(), visitedTypePairs);
- }
+ R visitTopLevelVariableElement(TopLevelVariableElement element) => null;
- bool _isMoreSpecificThan(InterfaceType s, Set<ClassElement> visitedClasses, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
- //
- // A type T is more specific than a type S, written T << S, if one of the following conditions
- // is met:
- //
- // Reflexivity: T is S.
- //
- if (this == s) {
- return true;
- }
- //
- // T is bottom. (This case is handled by the class BottomTypeImpl.)
- //
- // Direct supertype: S is a direct supertype of T.
- //
- if (s.isDirectSupertypeOf(this)) {
- return true;
- }
- //
- // Covariance: T is of the form I<T1, ..., Tn> and S is of the form I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
- //
- ClassElement tElement = this.element;
- ClassElement sElement = s.element;
- if (tElement == sElement) {
- List<DartType> tArguments = typeArguments;
- List<DartType> sArguments = s.typeArguments;
- if (tArguments.length != sArguments.length) {
- return false;
- }
- for (int i = 0; i < tArguments.length; i++) {
- if (!(tArguments[i] as TypeImpl).isMoreSpecificThan2(sArguments[i], withDynamic, visitedTypePairs)) {
- return false;
- }
- }
- return true;
- }
- //
- // Transitivity: T << U and U << S.
- //
- // First check for infinite loops
- ClassElement element = this.element;
- if (element == null || visitedClasses.contains(element)) {
- return false;
- }
- visitedClasses.add(element);
- // Iterate over all of the types U that are more specific than T because they are direct
- // supertypes of T and return true if any of them are more specific than S.
- InterfaceType supertype = superclass;
- if (supertype != null && (supertype as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses, withDynamic, visitedTypePairs)) {
- return true;
- }
- for (InterfaceType interfaceType in interfaces) {
- if ((interfaceType as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses, withDynamic, visitedTypePairs)) {
- return true;
- }
- }
- for (InterfaceType mixinType in mixins) {
- if ((mixinType as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses, withDynamic, visitedTypePairs)) {
- return true;
- }
- }
- return false;
- }
+ @override
+ R visitTypeParameterElement(TypeParameterElement element) => null;
+}
- bool _isSubtypeOf(InterfaceType type, Set<ClassElement> visitedClasses, Set<TypeImpl_TypePair> visitedTypePairs) {
- InterfaceType typeT = this;
- InterfaceType typeS = type;
- ClassElement elementT = element;
- if (elementT == null || visitedClasses.contains(elementT)) {
- return false;
- }
- visitedClasses.add(elementT);
- if (typeT == typeS) {
- return true;
- } else if (elementT == typeS.element) {
- // For each of the type arguments return true if all type args from T is a subtype of all
- // types from S.
- List<DartType> typeTArgs = typeT.typeArguments;
- List<DartType> typeSArgs = typeS.typeArguments;
- if (typeTArgs.length != typeSArgs.length) {
- // This case covers the case where two objects are being compared that have a different
- // number of parameterized types.
- return false;
- }
- for (int i = 0; i < typeTArgs.length; i++) {
- // Recursively call isSubtypeOf the type arguments and return false if the T argument is not
- // a subtype of the S argument.
- if (!(typeTArgs[i] as TypeImpl).isSubtypeOf2(typeSArgs[i], visitedTypePairs)) {
- return false;
- }
- }
- return true;
- } else if (typeS.isDartCoreFunction && elementT.getMethod("call") != null) {
- return true;
- }
- InterfaceType supertype = superclass;
- // The type is Object, return false.
- if (supertype != null && (supertype as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, visitedTypePairs)) {
- return true;
- }
- List<InterfaceType> interfaceTypes = interfaces;
- for (InterfaceType interfaceType in interfaceTypes) {
- if ((interfaceType as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, visitedTypePairs)) {
- return true;
- }
- }
- List<InterfaceType> mixinTypes = mixins;
- for (InterfaceType mixinType in mixinTypes) {
- if ((mixinType as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, visitedTypePairs)) {
- return true;
- }
- }
- return false;
- }
+/**
+ * The interface `ToolkitObjectElement` defines the behavior of elements that represent a
+ * toolkit specific object, such as Angular controller or component. These elements are not based on
+ * the Dart syntax, but on some semantic agreement, such as a special annotation.
+ */
+abstract class ToolkitObjectElement implements Element {
+ /**
+ * An empty array of toolkit object elements.
+ */
+ static final List<ToolkitObjectElement> EMPTY_ARRAY = new List<ToolkitObjectElement>(0);
+}
+
+/**
+ * Instances of the class `ToolkitObjectElementImpl` implement a `ToolkitObjectElement`.
+ */
+abstract class ToolkitObjectElementImpl extends ElementImpl implements ToolkitObjectElement {
+ /**
+ * Initialize a newly created toolkit object element to have the given name.
+ *
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
+ */
+ ToolkitObjectElementImpl(String name, int nameOffset) : super(name, nameOffset);
+}
+
+/**
+ * The interface `TopLevelVariableElement` defines the behavior of elements representing a
+ * top-level variable.
+ */
+abstract class TopLevelVariableElement implements PropertyInducingElement {
+}
+
+/**
+ * Instances of the class `TopLevelVariableElementImpl` implement a
+ * `TopLevelVariableElement`.
+ */
+class TopLevelVariableElementImpl extends PropertyInducingElementImpl implements TopLevelVariableElement {
+ /**
+ * An empty array of top-level variable elements.
+ */
+ static List<TopLevelVariableElement> EMPTY_ARRAY = new List<TopLevelVariableElement>(0);
+
+ /**
+ * Initialize a newly created top-level variable element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ TopLevelVariableElementImpl.con1(Identifier name) : super.con1(name);
+
+ /**
+ * Initialize a newly created synthetic top-level variable element to have the given name.
+ *
+ * @param name the name of this element
+ */
+ TopLevelVariableElementImpl.con2(String name) : super.con2(name);
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);
+
+ @override
+ ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;
+
+ @override
+ bool get isStatic => true;
}
/**
@@ -10109,745 +10318,493 @@ class TypeImpl_TypePair {
}
/**
- * Instances of the class `TypeParameterTypeImpl` defines the behavior of objects representing
- * the type introduced by a type parameter.
- */
-class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
- /**
- * An empty array of type parameter types.
- */
- static List<TypeParameterType> EMPTY_ARRAY = new List<TypeParameterType>(0);
-
- /**
- * Return an array containing the type parameter types defined by the given array of type
- * parameter elements.
- *
- * @param typeParameters the type parameter elements defining the type parameter types to be
- * returned
- * @return the type parameter types defined by the type parameter elements
- */
- static List<TypeParameterType> getTypes(List<TypeParameterElement> typeParameters) {
- int count = typeParameters.length;
- if (count == 0) {
- return EMPTY_ARRAY;
- }
- List<TypeParameterType> types = new List<TypeParameterType>(count);
- for (int i = 0; i < count; i++) {
- types[i] = typeParameters[i].type;
- }
- return types;
- }
-
- /**
- * Initialize a newly created type parameter type to be declared by the given element and to have
- * the given name.
- *
- * @param element the element representing the declaration of the type parameter
- */
- TypeParameterTypeImpl(TypeParameterElement element) : super(element, element.name);
-
- @override
- bool operator ==(Object object) => object is TypeParameterTypeImpl && (element == object.element);
-
- @override
- TypeParameterElement get element => super.element as TypeParameterElement;
-
- @override
- int get hashCode => element.hashCode;
-
- @override
- DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
- int length = parameterTypes.length;
- for (int i = 0; i < length; i++) {
- if (parameterTypes[i] == this) {
- return argumentTypes[i];
- }
- }
- return this;
- }
-
- @override
- bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => this == object;
-
- @override
- bool internalIsMoreSpecificThan(DartType s, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
- //
- // A type T is more specific than a type S, written T << S, if one of the following conditions
- // is met:
- //
- // Reflexivity: T is S.
- //
- if (this == s) {
- return true;
- }
- // S is bottom.
- //
- if (s.isBottom) {
- return true;
- }
- // S is dynamic.
- //
- if (s.isDynamic) {
- return true;
- }
- return _isMoreSpecificThan(s, new Set<DartType>(), withDynamic, visitedTypePairs);
- }
-
- @override
- bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => isMoreSpecificThan2(type, true, new Set<TypeImpl_TypePair>());
-
- bool _isMoreSpecificThan(DartType s, Set<DartType> visitedTypes, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
- // T is a type parameter and S is the upper bound of T.
- //
- DartType bound = element.bound;
- if (s == bound) {
- return true;
- }
- // T is a type parameter and S is Object.
- //
- if (s.isObject) {
- return true;
- }
- // We need upper bound to continue.
- if (bound == null) {
- return false;
- }
- //
- // Transitivity: T << U and U << S.
- //
- if (bound is TypeParameterTypeImpl) {
- TypeParameterTypeImpl boundTypeParameter = bound;
- // First check for infinite loops
- if (visitedTypes.contains(bound)) {
- return false;
- }
- visitedTypes.add(bound);
- // Then check upper bound.
- return boundTypeParameter._isMoreSpecificThan(s, visitedTypes, withDynamic, visitedTypePairs);
- }
- // Check interface type.
- return (bound as TypeImpl).isMoreSpecificThan2(s, withDynamic, visitedTypePairs);
- }
-}
-
-/**
- * The unique instance of the class `VoidTypeImpl` implements the type `void`.
- */
-class VoidTypeImpl extends TypeImpl implements VoidType {
- /**
- * The unique instance of this class.
- */
- static VoidTypeImpl _INSTANCE = new VoidTypeImpl();
-
- /**
- * Return the unique instance of this class.
- *
- * @return the unique instance of this class
- */
- static VoidTypeImpl get instance => _INSTANCE;
-
- /**
- * Prevent the creation of instances of this class.
- */
- VoidTypeImpl() : super(null, Keyword.VOID.syntax);
-
- @override
- bool operator ==(Object object) => identical(object, this);
-
- @override
- int get hashCode => 2;
-
- @override
- bool get isVoid => true;
-
- @override
- VoidTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) => this;
-
- @override
- bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
-
- @override
- bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) => isSubtypeOf(type);
-
- @override
- bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => identical(type, this) || identical(type, DynamicTypeImpl.instance);
-}
-
-/**
- * The interface `FunctionType` defines the behavior common to objects representing the type
- * of a function, method, constructor, getter, or setter. Function types come in three variations:
- * <ol>
- * * The types of functions that only have required parameters. These have the general form
- * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T</i>.
- * * The types of functions with optional positional parameters. These have the general form
- * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, [T<sub>n+1</sub>, &hellip;, T<sub>n+k</sub>]) &rarr;
- * T</i>.
- * * The types of functions with named parameters. These have the general form <i>(T<sub>1</sub>,
- * &hellip;, T<sub>n</sub>, {T<sub>x1</sub> x1, &hellip;, T<sub>xk</sub> xk}) &rarr; T</i>.
- * </ol>
+ * The interface `TypeParameterElement` defines the behavior of elements representing a type
+ * parameter.
*/
-abstract class FunctionType implements ParameterizedType {
- /**
- * Return a map from the names of named parameters to the types of the named parameters of this
- * type of function. The entries in the map will be iterated in the same order as the order in
- * which the named parameters were defined. If there were no named parameters declared then the
- * map will be empty.
- *
- * @return a map from the name to the types of the named parameters of this type of function
- */
- Map<String, DartType> get namedParameterTypes;
-
- /**
- * Return an array containing the types of the normal parameters of this type of function. The
- * parameter types are in the same order as they appear in the declaration of the function.
- *
- * @return the types of the normal parameters of this type of function
- */
- List<DartType> get normalParameterTypes;
-
- /**
- * Return a map from the names of optional (positional) parameters to the types of the optional
- * parameters of this type of function. The entries in the map will be iterated in the same order
- * as the order in which the optional parameters were defined. If there were no optional
- * parameters declared then the map will be empty.
- *
- * @return a map from the name to the types of the optional parameters of this type of function
- */
- List<DartType> get optionalParameterTypes;
-
- /**
- * Return an array containing the parameters elements of this type of function. The parameter
- * types are in the same order as they appear in the declaration of the function.
- *
- * @return the parameters elements of this type of function
- */
- List<ParameterElement> get parameters;
-
- /**
- * Return the type of object returned by this type of function.
- *
- * @return the type of object returned by this type of function
- */
- DartType get returnType;
-
+abstract class TypeParameterElement implements Element {
/**
- * Return `true` if this type is a subtype of the given type.
- *
- * A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T</i> is a subtype of the
- * function type <i>(S<sub>1</sub>, &hellip;, S<sub>n</sub>) &rarr; S</i>, if all of the following
- * conditions are met:
- * * Either
- * * <i>S</i> is void, or
- * * <i>T &hArr; S</i>.
- *
- * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> &hArr; S<sub>i</sub></i>.
- * A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, [T<sub>n+1</sub>, &hellip;,
- * T<sub>n+k</sub>]) &rarr; T</i> is a subtype of the function type <i>(S<sub>1</sub>, &hellip;,
- * S<sub>n</sub>, [S<sub>n+1</sub>, &hellip;, S<sub>n+m</sub>]) &rarr; S</i>, if all of the
- * following conditions are met:
- * * Either
- * * <i>S</i> is void, or
- * * <i>T &hArr; S</i>.
- *
- * * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, <i>T<sub>i</sub>
- * &hArr; S<sub>i</sub></i>.
- * A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, {T<sub>x1</sub> x1, &hellip;,
- * T<sub>xk</sub> xk}) &rarr; T</i> is a subtype of the function type <i>(S<sub>1</sub>, &hellip;,
- * S<sub>n</sub>, {S<sub>y1</sub> y1, &hellip;, S<sub>ym</sub> ym}) &rarr; S</i>, if all of the
- * following conditions are met:
- * * Either
- * * <i>S</i> is void,
- * * or <i>T &hArr; S</i>.
- *
- * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> &hArr; S<sub>i</sub></i>.
- * * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, &hellip;,
- * x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>.
- * * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, &hellip;, y<sub>m</sub>}</i>,
- * <i>y<sub>i</sub> = x<sub>j</sub> => Tj &hArr; Si</i>.
- * In addition, the following subtype rules apply:
- *
- * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, []) &rarr; T <: (T<sub>1</sub>, &hellip;,
- * T<sub>n</sub>) &rarr; T.</i><br>
- * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T <: (T<sub>1</sub>, &hellip;,
- * T<sub>n</sub>, {}) &rarr; T.</i><br>
- * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, {}) &rarr; T <: (T<sub>1</sub>, &hellip;,
- * T<sub>n</sub>) &rarr; T.</i><br>
- * <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T <: (T<sub>1</sub>, &hellip;,
- * T<sub>n</sub>, []) &rarr; T.</i>
- *
- * All functions implement the class `Function`. However not all function types are a
- * subtype of `Function`. If an interface type <i>I</i> includes a method named
- * `call()`, and the type of `call()` is the function type <i>F</i>, then <i>I</i> is
- * considered to be a subtype of <i>F</i>.
+ * Return the type representing the bound associated with this parameter, or `null` if this
+ * parameter does not have an explicit bound.
*
- * @param type the type being compared with this type
- * @return `true` if this type is a subtype of the given type
+ * @return the type representing the bound associated with this parameter
*/
- @override
- bool isSubtypeOf(DartType type);
+ DartType get bound;
/**
- * Return the type resulting from substituting the given arguments for this type's parameters.
- * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`.
+ * Return the type defined by this type parameter.
*
- * @param argumentTypes the actual type arguments being substituted for the type parameters
- * @return the result of performing the substitution
+ * @return the type defined by this type parameter
*/
- FunctionType substitute3(List<DartType> argumentTypes);
-
- @override
- FunctionType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
+ TypeParameterType get type;
}
/**
- * The interface `InterfaceType` defines the behavior common to objects representing the type
- * introduced by either a class or an interface, or a reference to such a type.
+ * Instances of the class `TypeParameterElementImpl` implement a [TypeParameterElement].
*/
-abstract class InterfaceType implements ParameterizedType {
+class TypeParameterElementImpl extends ElementImpl implements TypeParameterElement {
/**
- * Return an array containing all of the accessors (getters and setters) declared in this type.
- *
- * @return the accessors declared in this type
+ * The type defined by this type parameter.
*/
- List<PropertyAccessorElement> get accessors;
-
- @override
- ClassElement get element;
+ TypeParameterType type;
/**
- * Return the element representing the getter with the given name that is declared in this class,
- * or `null` if this class does not declare a getter with the given name.
- *
- * @param getterName the name of the getter to be returned
- * @return the getter declared in this class with the given name
+ * The type representing the bound associated with this parameter, or `null` if this
+ * parameter does not have an explicit bound.
*/
- PropertyAccessorElement getGetter(String getterName);
+ DartType bound;
/**
- * Return an array containing all of the interfaces that are implemented by this interface. Note
- * that this is <b>not</b>, in general, equivalent to getting the interfaces from this type's
- * element because the types returned by this method will have had their type parameters replaced.
- *
- * @return the interfaces that are implemented by this type
+ * An empty array of type parameter elements.
*/
- List<InterfaceType> get interfaces;
+ static List<TypeParameterElement> EMPTY_ARRAY = new List<TypeParameterElement>(0);
/**
- * Return the least upper bound of this type and the given type, or `null` if there is no
- * least upper bound.
- *
- * Given two interfaces <i>I</i> and <i>J</i>, let <i>S<sub>I</sub></i> be the set of
- * superinterfaces of <i>I<i>, let <i>S<sub>J</sub></i> be the set of superinterfaces of <i>J</i>
- * and let <i>S = (I &cup; S<sub>I</sub>) &cap; (J &cup; S<sub>J</sub>)</i>. Furthermore, we
- * define <i>S<sub>n</sub> = {T | T &isin; S &and; depth(T) = n}</i> for any finite <i>n</i>,
- * where <i>depth(T)</i> is the number of steps in the longest inheritance path from <i>T</i> to
- * <i>Object</i>. Let <i>q</i> be the largest number such that <i>S<sub>q</sub></i> has
- * cardinality one. The least upper bound of <i>I</i> and <i>J</i> is the sole element of
- * <i>S<sub>q</sub></i>.
+ * Initialize a newly created type parameter element to have the given name.
*
- * @param type the other type used to compute the least upper bound
- * @return the least upper bound of this type and the given type
+ * @param name the name of this element
*/
+ TypeParameterElementImpl(Identifier name) : super.forNode(name);
+
@override
- DartType getLeastUpperBound(DartType type);
+ accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
- /**
- * Return the element representing the method with the given name that is declared in this class,
- * or `null` if this class does not declare a method with the given name.
- *
- * @param methodName the name of the method to be returned
- * @return the method declared in this class with the given name
- */
- MethodElement getMethod(String methodName);
+ @override
+ ElementKind get kind => ElementKind.TYPE_PARAMETER;
+
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(displayName);
+ if (bound != null) {
+ builder.append(" extends ");
+ builder.append(bound);
+ }
+ }
+}
+
+/**
+ * The interface `TypeParameterType` defines the behavior of objects representing the type
+ * introduced by a type parameter.
+ */
+abstract class TypeParameterType implements DartType {
+ @override
+ TypeParameterElement get element;
+}
+/**
+ * Instances of the class `TypeParameterTypeImpl` defines the behavior of objects representing
+ * the type introduced by a type parameter.
+ */
+class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
/**
- * Return an array containing all of the methods declared in this type.
- *
- * @return the methods declared in this type
+ * An empty array of type parameter types.
*/
- List<MethodElement> get methods;
+ static List<TypeParameterType> EMPTY_ARRAY = new List<TypeParameterType>(0);
/**
- * Return an array containing all of the mixins that are applied to the class being extended in
- * order to derive the superclass of this class. Note that this is <b>not</b>, in general,
- * equivalent to getting the mixins from this type's element because the types returned by this
- * method will have had their type parameters replaced.
+ * Return an array containing the type parameter types defined by the given array of type
+ * parameter elements.
*
- * @return the mixins that are applied to derive the superclass of this class
+ * @param typeParameters the type parameter elements defining the type parameter types to be
+ * returned
+ * @return the type parameter types defined by the type parameter elements
*/
- List<InterfaceType> get mixins;
+ static List<TypeParameterType> getTypes(List<TypeParameterElement> typeParameters) {
+ int count = typeParameters.length;
+ if (count == 0) {
+ return EMPTY_ARRAY;
+ }
+ List<TypeParameterType> types = new List<TypeParameterType>(count);
+ for (int i = 0; i < count; i++) {
+ types[i] = typeParameters[i].type;
+ }
+ return types;
+ }
/**
- * Return the element representing the setter with the given name that is declared in this class,
- * or `null` if this class does not declare a setter with the given name.
+ * Initialize a newly created type parameter type to be declared by the given element and to have
+ * the given name.
*
- * @param setterName the name of the setter to be returned
- * @return the setter declared in this class with the given name
+ * @param element the element representing the declaration of the type parameter
*/
- PropertyAccessorElement getSetter(String setterName);
+ TypeParameterTypeImpl(TypeParameterElement element) : super(element, element.name);
+
+ @override
+ bool operator ==(Object object) => object is TypeParameterTypeImpl && (element == object.element);
+
+ @override
+ TypeParameterElement get element => super.element as TypeParameterElement;
+
+ @override
+ int get hashCode => element.hashCode;
+
+ @override
+ DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) {
+ int length = parameterTypes.length;
+ for (int i = 0; i < length; i++) {
+ if (parameterTypes[i] == this) {
+ return argumentTypes[i];
+ }
+ }
+ return this;
+ }
+
+ @override
+ bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => this == object;
+
+ @override
+ bool internalIsMoreSpecificThan(DartType s, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // A type T is more specific than a type S, written T << S, if one of the following conditions
+ // is met:
+ //
+ // Reflexivity: T is S.
+ //
+ if (this == s) {
+ return true;
+ }
+ // S is bottom.
+ //
+ if (s.isBottom) {
+ return true;
+ }
+ // S is dynamic.
+ //
+ if (s.isDynamic) {
+ return true;
+ }
+ return _isMoreSpecificThan(s, new Set<DartType>(), withDynamic, visitedTypePairs);
+ }
+
+ @override
+ bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => isMoreSpecificThan2(type, true, new Set<TypeImpl_TypePair>());
+
+ bool _isMoreSpecificThan(DartType s, Set<DartType> visitedTypes, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // T is a type parameter and S is the upper bound of T.
+ //
+ DartType bound = element.bound;
+ if (s == bound) {
+ return true;
+ }
+ // T is a type parameter and S is Object.
+ //
+ if (s.isObject) {
+ return true;
+ }
+ // We need upper bound to continue.
+ if (bound == null) {
+ return false;
+ }
+ //
+ // Transitivity: T << U and U << S.
+ //
+ if (bound is TypeParameterTypeImpl) {
+ TypeParameterTypeImpl boundTypeParameter = bound;
+ // First check for infinite loops
+ if (visitedTypes.contains(bound)) {
+ return false;
+ }
+ visitedTypes.add(bound);
+ // Then check upper bound.
+ return boundTypeParameter._isMoreSpecificThan(s, visitedTypes, withDynamic, visitedTypePairs);
+ }
+ // Check interface type.
+ return (bound as TypeImpl).isMoreSpecificThan2(s, withDynamic, visitedTypePairs);
+ }
+}
- /**
- * Return the type representing the superclass of this type, or null if this type represents the
- * class 'Object'. Note that this is <b>not</b>, in general, equivalent to getting the superclass
- * from this type's element because the type returned by this method will have had it's type
- * parameters replaced.
- *
- * @return the superclass of this type
- */
- InterfaceType get superclass;
+/**
+ * The interface `UndefinedElement` defines the behavior of pseudo-elements that represent
+ * names that are undefined. This situation is not allowed by the language, so objects implementing
+ * this interface always represent an error. As a result, most of the normal operations on elements
+ * do not make sense and will return useless results.
+ */
+abstract class UndefinedElement implements Element {
+}
+/**
+ * The interface `UriReferencedElement` defines the behavior of objects included into a
+ * library using some URI.
+ */
+abstract class UriReferencedElement implements Element {
/**
- * Return `true` if this type is a direct supertype of the given type. The implicit
- * interface of class <i>I</i> is a direct supertype of the implicit interface of class <i>J</i>
- * iff:
- * * <i>I</i> is Object, and <i>J</i> has no extends clause.
- * * <i>I</i> is listed in the extends clause of <i>J</i>.
- * * <i>I</i> is listed in the implements clause of <i>J</i>.
- * * <i>I</i> is listed in the with clause of <i>J</i>.
- * * <i>J</i> is a mixin application of the mixin of <i>I</i>.
+ * Return the offset of the character immediately following the last character of this node's URI,
+ * or `-1` for synthetic import.
*
- * @param type the type being compared with this type
- * @return `true` if this type is a direct supertype of the given type
+ * @return the offset of the character just past the node's URI
*/
- bool isDirectSupertypeOf(InterfaceType type);
+ int get uriEnd;
/**
- * Return `true` if this type is more specific than the given type. An interface type
- * <i>T</i> is more specific than an interface type <i>S</i>, written <i>T &laquo; S</i>, if one
- * of the following conditions is met:
- * * Reflexivity: <i>T</i> is <i>S</i>.
- * * <i>T</i> is bottom.
- * * <i>S</i> is dynamic.
- * * Direct supertype: <i>S</i> is a direct supertype of <i>T</i>.
- * * <i>T</i> is a type parameter and <i>S</i> is the upper bound of <i>T</i>.
- * * Covariance: <i>T</i> is of the form <i>I&lt;T<sub>1</sub>, &hellip;, T<sub>n</sub>&gt;</i>
- * and S</i> is of the form <i>I&lt;S<sub>1</sub>, &hellip;, S<sub>n</sub>&gt;</i> and
- * <i>T<sub>i</sub> &laquo; S<sub>i</sub></i>, <i>1 <= i <= n</i>.
- * * Transitivity: <i>T &laquo; U</i> and <i>U &laquo; S</i>.
+ * Return the offset of the URI in the file, or `-1` if this element is synthetic.
*
- * @param type the type being compared with this type
- * @return `true` if this type is more specific than the given type
+ * @return the offset of the URI
*/
- @override
- bool isMoreSpecificThan(DartType type);
+ int get uriOffset;
/**
- * Return `true` if this type is a subtype of the given type. An interface type <i>T</i> is
- * a subtype of an interface type <i>S</i>, written <i>T</i> <: <i>S</i>, iff
- * <i>[bottom/dynamic]T</i> &laquo; <i>S</i> (<i>T</i> is more specific than <i>S</i>). If an
- * interface type <i>I</i> includes a method named <i>call()</i>, and the type of <i>call()</i> is
- * the function type <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>.
+ * Return the URI that is used to include this element into the enclosing library, or `null`
+ * if this is the defining compilation unit of a library.
*
- * @param type the type being compared with this type
- * @return `true` if this type is a subtype of the given type
+ * @return the URI that is used to include this element into the enclosing library
*/
- @override
- bool isSubtypeOf(DartType type);
+ String get uri;
+}
+/**
+ * Instances of the class `UriReferencedElementImpl` implement an [UriReferencedElement]
+ * .
+ */
+abstract class UriReferencedElementImpl extends ElementImpl implements UriReferencedElement {
/**
- * Return the element representing the constructor that results from looking up the given
- * constructor in this class with respect to the given library, or `null` if the look up
- * fails. The behavior of this method is defined by the Dart Language Specification in section
- * 12.11.1: <blockquote>If <i>e</i> is of the form <b>new</b> <i>T.id()</i> then let <i>q<i> be
- * the constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor <i>T<i>. Otherwise, if
- * <i>q</i> is not defined or not accessible, a NoSuchMethodException is thrown. </blockquote>
- *
- * @param constructorName the name of the constructor being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given constructor in this class with respect to the given
- * library
+ * The offset of the URI in the file, may be `-1` if synthetic.
*/
- ConstructorElement lookUpConstructor(String constructorName, LibraryElement library);
+ int uriOffset = -1;
/**
- * Return the element representing the getter that results from looking up the given getter in
- * this class with respect to the given library, or `null` if the look up fails. The
- * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
- * <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
- * with respect to library <i>L</i> is:
- * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
- * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
- * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
- * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.
- * </blockquote>
- *
- * @param getterName the name of the getter being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given getter in this class with respect to the given
- * library
+ * The offset of the character immediately following the last character of this node's URI, may be
+ * `-1` if synthetic.
*/
- PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library);
+ int uriEnd = -1;
/**
- * Return the element representing the getter that results from looking up the given getter in the
- * superclass of this class with respect to the given library, or `null` if the look up
- * fails. The behavior of this method is defined by the Dart Language Specification in section
- * 12.15.1: <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class
- * <i>C</i> with respect to library <i>L</i> is:
- * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
- * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
- * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
- * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.
- * </blockquote>
- *
- * @param getterName the name of the getter being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given getter in this class with respect to the given
- * library
+ * The URI that is specified by this directive.
*/
- PropertyAccessorElement lookUpGetterInSuperclass(String getterName, LibraryElement library);
+ String uri;
/**
- * Return the element representing the method that results from looking up the given method in
- * this class with respect to the given library, or `null` if the look up fails. The
- * behavior of this method is defined by the Dart Language Specification in section 12.15.1:
- * <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect to library
- * <i>L</i> is:
- * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
- * that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
- * the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
- * to <i>L</i>. Otherwise, we say that the lookup has failed.
- * </blockquote>
+ * Initialize a newly created import element.
*
- * @param methodName the name of the method being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given method in this class with respect to the given
- * library
+ * @param name the name of this element
+ * @param offset the directive offset, may be `-1` if synthetic.
*/
- MethodElement lookUpMethod(String methodName, LibraryElement library);
+ UriReferencedElementImpl(String name, int offset) : super(name, offset);
+}
+/**
+ * The interface `VariableElement` defines the behavior common to elements that represent a
+ * variable.
+ */
+abstract class VariableElement implements Element {
/**
- * Return the element representing the method that results from looking up the given method in the
- * superclass of this class with respect to the given library, or `null` if the look up
- * fails. The behavior of this method is defined by the Dart Language Specification in section
- * 12.15.1: <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect
- * to library <i>L</i> is:
- * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
- * that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
- * the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
- * to <i>L</i>. Otherwise, we say that the lookup has failed.
- * </blockquote>
+ * Return a synthetic function representing this variable's initializer, or `null` if this
+ * variable does not have an initializer. The function will have no parameters. The return type of
+ * the function will be the compile-time type of the initialization expression.
*
- * @param methodName the name of the method being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given method in this class with respect to the given
- * library
+ * @return a synthetic function representing this variable's initializer
*/
- MethodElement lookUpMethodInSuperclass(String methodName, LibraryElement library);
+ FunctionElement get initializer;
/**
- * Return the element representing the setter that results from looking up the given setter in
- * this class with respect to the given library, or `null` if the look up fails. The
- * behavior of this method is defined by the Dart Language Specification in section 12.16:
- * <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
- * with respect to library <i>L</i> is:
- * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
- * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
- * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
- * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.
- * </blockquote>
+ * Return the resolved [VariableDeclaration] node that declares this [VariableElement]
+ * .
*
- * @param setterName the name of the setter being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given setter in this class with respect to the given
- * library
- */
- PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library);
-
- /**
- * Return the element representing the setter that results from looking up the given setter in the
- * superclass of this class with respect to the given library, or `null` if the look up
- * fails. The behavior of this method is defined by the Dart Language Specification in section
- * 12.16: <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class
- * <i>C</i> with respect to library <i>L</i> is:
- * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
- * accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
- * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
- * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.
- * </blockquote>
+ * This method is expensive, because resolved AST might be evicted from cache, so parsing and
+ * resolving will be performed.
*
- * @param setterName the name of the setter being looked up
- * @param library the library with respect to which the lookup is being performed
- * @return the result of looking up the given setter in this class with respect to the given
- * library
+ * @return the resolved [VariableDeclaration], not `null`.
*/
- PropertyAccessorElement lookUpSetterInSuperclass(String setterName, LibraryElement library);
+ @override
+ VariableDeclaration get node;
/**
- * Return the type resulting from substituting the given arguments for this type's parameters.
- * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`.
+ * Return the declared type of this variable, or `null` if the variable did not have a
+ * declared type (such as if it was declared using the keyword 'var').
*
- * @param argumentTypes the actual type arguments being substituted for the type parameters
- * @return the result of performing the substitution
+ * @return the declared type of this variable
*/
- InterfaceType substitute4(List<DartType> argumentTypes);
-
- @override
- InterfaceType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
-}
+ DartType get type;
-/**
- * The interface `ParameterizedType` defines the behavior common to objects representing a
- * type with type parameters, such as a class or function type alias.
- */
-abstract class ParameterizedType implements DartType {
/**
- * Return an array containing the actual types of the type arguments. If this type's element does
- * not have type parameters, then the array should be empty (although it is possible for type
- * arguments to be erroneously declared). If the element has type parameters and the actual type
- * does not explicitly include argument values, then the type "dynamic" will be automatically
- * provided.
+ * Return `true` if this variable was declared with the 'const' modifier.
*
- * @return the actual types of the type arguments
+ * @return `true` if this variable was declared with the 'const' modifier
*/
- List<DartType> get typeArguments;
+ bool get isConst;
/**
- * Return an array containing all of the type parameters declared for this type.
+ * Return `true` if this variable was declared with the 'final' modifier. Variables that are
+ * declared with the 'const' modifier will return `false` even though they are implicitly
+ * final.
*
- * @return the type parameters declared for this type
+ * @return `true` if this variable was declared with the 'final' modifier
*/
- List<TypeParameterElement> get typeParameters;
+ bool get isFinal;
}
/**
- * The interface `Type` defines the behavior of objects representing the declared type of
- * elements in the element model.
+ * Instances of the class `VariableElementImpl` implement a `VariableElement`.
*/
-abstract class DartType {
+abstract class VariableElementImpl extends ElementImpl implements VariableElement {
/**
- * Return the name of this type as it should appear when presented to users in contexts such as
- * error messages.
- *
- * @return the name of this type
+ * The declared type of this variable.
*/
- String get displayName;
+ DartType type;
/**
- * Return the element representing the declaration of this type, or `null` if the type has
- * not, or cannot, be associated with an element. The former case will occur if the element model
- * is not yet complete; the latter case will occur if this object represents an undefined type.
- *
- * @return the element representing the declaration of this type
+ * A synthetic function representing this variable's initializer, or `null` if this variable
+ * does not have an initializer.
*/
- Element get element;
+ FunctionElement _initializer;
/**
- * Return the least upper bound of this type and the given type, or `null` if there is no
- * least upper bound.
- *
- * @param type the other type used to compute the least upper bound
- * @return the least upper bound of this type and the given type
+ * An empty array of variable elements.
*/
- DartType getLeastUpperBound(DartType type);
+ static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>(0);
/**
- * Return the name of this type, or `null` if the type does not have a name, such as when
- * the type represents the type of an unnamed function.
+ * Initialize a newly created variable element to have the given name.
*
- * @return the name of this type
+ * @param name the name of this element
*/
- String get name;
+ VariableElementImpl.forNode(Identifier name) : super.forNode(name);
/**
- * Return `true` if this type is assignable to the given type. A type <i>T</i> may be
- * assigned to a type <i>S</i>, written <i>T</i> &hArr; <i>S</i>, iff either <i>T</i> <: <i>S</i>
- * or <i>S</i> <: <i>T</i>.
+ * Initialize a newly created variable element to have the given name.
*
- * @param type the type being compared with this type
- * @return `true` if this type is assignable to the given type
+ * @param name the name of this element
+ * @param nameOffset the offset of the name of this element in the file that contains the
+ * declaration of this element
*/
- bool isAssignableTo(DartType type);
+ VariableElementImpl(String name, int nameOffset) : super(name, nameOffset);
/**
- * Return `true` if this type represents the bottom type.
+ * 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.
*
- * @return `true` if this type represents the bottom type
+ * @return the result of evaluating this variable's initializer
*/
- bool get isBottom;
+ EvaluationResultImpl get evaluationResult => null;
- /**
- * Return `true` if this type represents the type 'Function' defined in the dart:core
- * library.
- *
- * @return `true` if this type represents the type 'Function' defined in the dart:core
- * library
- */
- bool get isDartCoreFunction;
+ @override
+ FunctionElement get initializer => _initializer;
- /**
- * Return `true` if this type represents the type 'dynamic'.
- *
- * @return `true` if this type represents the type 'dynamic'
- */
- bool get isDynamic;
+ @override
+ VariableDeclaration get node => getNodeMatching((node) => node is VariableDeclaration);
+
+ @override
+ bool get isConst => hasModifier(Modifier.CONST);
+
+ @override
+ bool get isFinal => hasModifier(Modifier.FINAL);
/**
- * Return `true` if this type is more specific than the given type.
+ * Return `true` if this variable is potentially mutated somewhere in a closure. This
+ * information is only available for local variables (including parameters) and only after the
+ * compilation unit containing the variable has been resolved.
*
- * @param type the type being compared with this type
- * @return `true` if this type is more specific than the given type
+ * @return `true` if this variable is potentially mutated somewhere in closure
*/
- bool isMoreSpecificThan(DartType type);
+ bool get isPotentiallyMutatedInClosure => false;
/**
- * Return `true` if this type represents the type 'Object'.
+ * Return `true` if this variable is potentially mutated somewhere in its scope. This
+ * information is only available for local variables (including parameters) and only after the
+ * compilation unit containing the variable has been resolved.
*
- * @return `true` if this type represents the type 'Object'
+ * @return `true` if this variable is potentially mutated somewhere in its scope
*/
- bool get isObject;
+ bool get isPotentiallyMutatedInScope => false;
/**
- * Return `true` if this type is a subtype of the given type.
+ * Set whether this variable is const to correspond to the given value.
*
- * @param type the type being compared with this type
- * @return `true` if this type is a subtype of the given type
+ * @param isConst `true` if the variable is const
*/
- bool isSubtypeOf(DartType type);
+ void set const3(bool isConst) {
+ setModifier(Modifier.CONST, isConst);
+ }
/**
- * Return `true` if this type is a supertype of the given type. A type <i>S</i> is a
- * supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff <i>T</i> is a subtype of <i>S</i>.
+ * Set the result of evaluating this variable's initializer as a compile-time constant expression
+ * to the given result.
*
- * @param type the type being compared with this type
- * @return `true` if this type is a supertype of the given type
+ * @param result the result of evaluating this variable's initializer
*/
- bool isSupertypeOf(DartType type);
+ void set evaluationResult(EvaluationResultImpl result) {
+ throw new IllegalStateException("Invalid attempt to set a compile-time constant result");
+ }
/**
- * Return `true` if this type represents the type 'void'.
+ * Set whether this variable is final to correspond to the given value.
*
- * @return `true` if this type represents the type 'void'
+ * @param isFinal `true` if the variable is final
*/
- bool get isVoid;
+ void set final2(bool isFinal) {
+ setModifier(Modifier.FINAL, isFinal);
+ }
/**
- * Return the type resulting from substituting the given arguments for the given parameters in
- * this type. The specification defines this operation in section 2: <blockquote> The notation
- * <i>[x<sub>1</sub>, ..., x<sub>n</sub>/y<sub>1</sub>, ..., y<sub>n</sub>]E</i> denotes a copy of
- * <i>E</i> in which all occurrences of <i>y<sub>i</sub>, 1 <= i <= n</i> have been replaced with
- * <i>x<sub>i</sub></i>.</blockquote> Note that, contrary to the specification, this method will
- * not create a copy of this type if no substitutions were required, but will return this type
- * directly.
+ * Set the function representing this variable's initializer to the given function.
*
- * @param argumentTypes the actual type arguments being substituted for the parameters
- * @param parameterTypes the parameters to be replaced
- * @return the result of performing the substitution
+ * @param initializer the function representing this variable's initializer
*/
- DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
+ void set initializer(FunctionElement initializer) {
+ if (initializer != null) {
+ (initializer as FunctionElementImpl).enclosingElement = this;
+ }
+ this._initializer = initializer;
+ }
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ super.visitChildren(visitor);
+ safelyVisitChild(_initializer, visitor);
+ }
+
+ @override
+ void appendTo(JavaStringBuilder builder) {
+ builder.append(type);
+ builder.append(" ");
+ builder.append(displayName);
+ }
}
/**
- * The interface `TypeParameterType` defines the behavior of objects representing the type
- * introduced by a type parameter.
+ * The abstract class `VariableMember` defines the behavior common to members that represent a
+ * variable element defined in a parameterized type where the values of the type parameters are
+ * known.
*/
-abstract class TypeParameterType implements DartType {
+abstract class VariableMember extends Member implements VariableElement {
+ /**
+ * Initialize a newly created element to represent an executable element of the given
+ * parameterized type.
+ *
+ * @param baseElement the element on which the parameterized element was created
+ * @param definingType the type in which the element is defined
+ */
+ VariableMember(VariableElement baseElement, ParameterizedType definingType) : super(baseElement, definingType);
+
@override
- TypeParameterElement get element;
+ VariableElement get baseElement => super.baseElement as VariableElement;
+
+ @override
+ FunctionElement get initializer {
+ //
+ // Elements within this element should have type parameters substituted, just like this element.
+ //
+ throw new UnsupportedOperationException();
+ }
+
+ @override
+ VariableDeclaration get node => baseElement.node;
+
+ @override
+ DartType get type => substituteFor(baseElement.type);
+
+ @override
+ bool get isConst => baseElement.isConst;
+
+ @override
+ bool get isFinal => baseElement.isFinal;
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ // TODO(brianwilkerson) We need to finish implementing the accessors used below so that we can
+ // safely invoke them.
+ super.visitChildren(visitor);
+ safelyVisitChild(baseElement.initializer, visitor);
+ }
}
/**
@@ -10857,4 +10814,47 @@ abstract class TypeParameterType implements DartType {
abstract class VoidType implements DartType {
@override
VoidType substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes);
+}
+
+/**
+ * The unique instance of the class `VoidTypeImpl` implements the type `void`.
+ */
+class VoidTypeImpl extends TypeImpl implements VoidType {
+ /**
+ * The unique instance of this class.
+ */
+ static VoidTypeImpl _INSTANCE = new VoidTypeImpl();
+
+ /**
+ * Return the unique instance of this class.
+ *
+ * @return the unique instance of this class
+ */
+ static VoidTypeImpl get instance => _INSTANCE;
+
+ /**
+ * Prevent the creation of instances of this class.
+ */
+ VoidTypeImpl() : super(null, Keyword.VOID.syntax);
+
+ @override
+ bool operator ==(Object object) => identical(object, this);
+
+ @override
+ int get hashCode => 2;
+
+ @override
+ bool get isVoid => true;
+
+ @override
+ VoidTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parameterTypes) => this;
+
+ @override
+ bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
+
+ @override
+ bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) => isSubtypeOf(type);
+
+ @override
+ bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => identical(type, this) || identical(type, DynamicTypeImpl.instance);
}
« no previous file with comments | « pkg/analyzer/lib/src/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/error.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698