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

Unified Diff: sdk/lib/_internal/compiler/implementation/elements/modelx.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/elements/modelx.dart
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
deleted file mode 100644
index d435f4aa9c96e0acd7784ba785f71ee035330c3b..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ /dev/null
@@ -1,2721 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library elements.modelx;
-
-import 'elements.dart';
-import '../constants/expressions.dart';
-import '../helpers/helpers.dart'; // Included for debug helpers.
-import '../tree/tree.dart';
-import '../util/util.dart';
-import '../resolution/resolution.dart';
-import '../resolution/class_members.dart' show ClassMemberMixin;
-
-import '../dart2jslib.dart' show invariant,
- InterfaceType,
- DartType,
- TypeVariableType,
- TypedefType,
- DualKind,
- MessageKind,
- DiagnosticListener,
- Script,
- FunctionType,
- Selector,
- Constant,
- Compiler,
- Backend,
- isPrivateName;
-
-import '../dart_types.dart';
-
-import '../scanner/scannerlib.dart' show
- EOF_TOKEN,
- ErrorToken,
- Token;
-
-import '../ordered_typeset.dart' show OrderedTypeSet;
-
-import 'visitor.dart' show ElementVisitor;
-
-abstract class DeclarationSite {
-}
-
-abstract class ElementX extends Element {
- static int elementHashCode = 0;
-
- final String name;
- final ElementKind kind;
- final Element enclosingElement;
- final int hashCode = ++elementHashCode;
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
-
- ElementX(this.name, this.kind, this.enclosingElement) {
- assert(isErroneous || implementationLibrary != null);
- }
-
- Modifiers get modifiers => Modifiers.EMPTY;
-
- Node parseNode(DiagnosticListener listener) {
- listener.internalError(this,
- 'parseNode not implemented on $this.');
- return null;
- }
-
- DartType computeType(Compiler compiler) {
- compiler.internalError(this,
- "computeType not implemented on $this.");
- return null;
- }
-
- void addMetadata(MetadataAnnotationX annotation) {
- assert(annotation.annotatedElement == null);
- annotation.annotatedElement = this;
- addMetadataInternal(annotation);
- }
-
- void addMetadataInternal(MetadataAnnotation annotation) {
- metadata = metadata.prepend(annotation);
- }
-
- bool get isClosure => false;
- bool get isClassMember {
- // Check that this element is defined in the scope of a Class.
- return enclosingElement != null && enclosingElement.isClass;
- }
- bool get isInstanceMember => false;
- bool get isDeferredLoaderGetter => false;
-
- bool get isFactoryConstructor => modifiers.isFactory;
- bool get isConst => modifiers.isConst;
- bool get isFinal => modifiers.isFinal;
- bool get isStatic => modifiers.isStatic;
- bool get isOperator => Elements.isOperatorName(name);
- bool get impliesType => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
-
- bool get isPatched => false;
-
- bool get isPatch => false;
-
- bool get isImplementation => true;
-
- bool get isDeclaration => true;
-
- bool get isInjected => !isPatch && implementationLibrary.isPatch;
-
- Element get implementation => this;
-
- Element get declaration => this;
-
- Element get patch {
- throw new UnsupportedError('patch is not supported on $this');
- }
-
- Element get origin {
- throw new UnsupportedError('origin is not supported on $this');
- }
-
- bool get isSynthesized => false;
-
- bool get isForwardingConstructor => false;
-
- bool get isMixinApplication => false;
-
- bool get isLocal => false;
-
- // TODO(johnniwinther): This breaks for libraries (for which enclosing
- // elements are null) and is invalid for top level variable declarations for
- // which the enclosing element is a VariableDeclarations and not a compilation
- // unit.
- bool get isTopLevel {
- return enclosingElement != null && enclosingElement.isCompilationUnit;
- }
-
- bool get isAssignable {
- if (isFinal || isConst) return false;
- if (isFunction || isGenerativeConstructor) return false;
- return true;
- }
-
- Token get position => null;
-
- Token findMyName(Token token) {
- return findNameToken(token, isConstructor, name, enclosingElement.name);
- }
-
- static Token findNameToken(Token token, bool isConstructor, String name,
- String enclosingClassName) {
- // We search for the token that has the name of this element.
- // For constructors, that doesn't work because they may have
- // named formed out of multiple tokens (named constructors) so
- // for those we search for the class name instead.
- String needle = isConstructor ? enclosingClassName : name;
- // The unary '-' operator has a special element name (specified).
- if (needle == 'unary-') needle = '-';
- for (Token t = token; EOF_TOKEN != t.kind; t = t.next) {
- if (t is !ErrorToken && needle == t.value) return t;
- }
- return token;
- }
-
- CompilationUnitElement get compilationUnit {
- Element element = this;
- while (!element.isCompilationUnit) {
- element = element.enclosingElement;
- }
- return element;
- }
-
- LibraryElement get library => enclosingElement.library;
-
- LibraryElement get implementationLibrary {
- Element element = this;
- while (!identical(element.kind, ElementKind.LIBRARY)) {
- element = element.enclosingElement;
- }
- return element;
- }
-
- ClassElement get enclosingClass {
- for (Element e = this; e != null; e = e.enclosingElement) {
- if (e.isClass) return e;
- }
- return null;
- }
-
- Element get enclosingClassOrCompilationUnit {
- for (Element e = this; e != null; e = e.enclosingElement) {
- if (e.isClass || e.isCompilationUnit) return e;
- }
- return null;
- }
-
- Element get outermostEnclosingMemberOrTopLevel {
- // TODO(lrn): Why is this called "Outermost"?
- // TODO(johnniwinther): Clean up this method: This method does not return
- // the outermost for elements in closure classses, but some call-sites rely
- // on that behavior.
- for (Element e = this; e != null; e = e.enclosingElement) {
- if (e.isClassMember || e.isTopLevel) {
- return e;
- }
- }
- return null;
- }
-
- ClassElement get contextClass {
- ClassElement cls;
- for (Element e = this; e != null; e = e.enclosingElement) {
- if (e.isClass) {
- // Record [e] instead of returning it directly. We need the last class
- // in the chain since the first classes might be closure classes.
- cls = e.declaration;
- }
- }
- return cls;
- }
-
- /**
- * Creates the scope for this element.
- */
- Scope buildScope() => enclosingElement.buildScope();
-
- String toString() {
- // TODO(johnniwinther): Test for nullness of name, or make non-nullness an
- // invariant for all element types?
- var nameText = name != null ? name : '?';
- if (enclosingElement != null && !isTopLevel) {
- String holderName = enclosingElement.name != null
- ? enclosingElement.name
- : '${enclosingElement.kind}?';
- return '$kind($holderName#${nameText})';
- } else {
- return '$kind(${nameText})';
- }
- }
-
- String _fixedBackendName = null;
- bool _isNative = false;
- bool get isNative => _isNative;
- bool get hasFixedBackendName => _fixedBackendName != null;
- String get fixedBackendName => _fixedBackendName;
- // Marks this element as a native element.
- void setNative(String name) {
- _isNative = true;
- _fixedBackendName = name;
- }
- void setFixedBackendName(String name) {
- _fixedBackendName = name;
- }
-
- FunctionElement asFunctionElement() => null;
-
- bool get isAbstract => modifiers.isAbstract;
- bool isForeign(Backend backend) => backend.isForeign(this);
-
- void diagnose(Element context, DiagnosticListener listener) {}
-
- bool get hasTreeElements => analyzableElement.hasTreeElements;
-
- TreeElements get treeElements => analyzableElement.treeElements;
-
- AnalyzableElement get analyzableElement {
- Element element = outermostEnclosingMemberOrTopLevel;
- if (element.isAbstractField || element.isPrefix) return element.library;
- return element;
- }
-
- DeclarationSite get declarationSite => null;
-}
-
-class ErroneousElementX extends ElementX implements ErroneousElement {
- final MessageKind messageKind;
- final Map messageArguments;
-
- ErroneousElementX(this.messageKind, this.messageArguments,
- String name, Element enclosing)
- : super(name, ElementKind.ERROR, enclosing);
-
- bool get isTopLevel => false;
-
- bool get isSynthesized => true;
-
- AbstractFieldElement abstractField;
-
- unsupported() {
- throw 'unsupported operation on erroneous element';
- }
-
- get asyncMarker => AsyncMarker.SYNC;
- Link<MetadataAnnotation> get metadata => unsupported();
- bool get hasNode => false;
- get node => unsupported();
- get hasResolvedAst => false;
- get resolvedAst => unsupported();
- get type => unsupported();
- get cachedNode => unsupported();
- get functionSignature => unsupported();
- get patch => null;
- get origin => this;
- get immediateRedirectionTarget => unsupported();
- get nestedClosures => unsupported();
- get memberContext => unsupported();
- get executableContext => unsupported();
-
- bool get isRedirectingFactory => unsupported();
-
- computeSignature(compiler) => unsupported();
-
- bool get hasFunctionSignature => false;
-
- get effectiveTarget => this;
-
- computeEffectiveTargetType(InterfaceType newType) => unsupported();
-
- get definingConstructor => null;
-
- FunctionElement asFunctionElement() => this;
-
- String get message => '${messageKind.message(messageArguments)}';
-
- String toString() => '<$name: $message>';
-
- accept(ElementVisitor visitor) => visitor.visitErroneousElement(this);
-}
-
-/// A message attached to a [WarnOnUseElementX].
-class WrappedMessage {
- /// The message position. If [:null:] the position of the reference to the
- /// [WarnOnUseElementX] is used.
- final Spannable spannable;
-
- /**
- * The message to report on resolving a wrapped element.
- */
- final MessageKind messageKind;
-
- /**
- * The message arguments to report on resolving a wrapped element.
- */
- final Map messageArguments;
-
- WrappedMessage(this.spannable, this.messageKind, this.messageArguments);
-}
-
-class WarnOnUseElementX extends ElementX implements WarnOnUseElement {
- /// Warning to report on resolving this element.
- final WrappedMessage warning;
-
- /// Info to report on resolving this element.
- final WrappedMessage info;
-
- /// The element whose usage cause a warning.
- final Element wrappedElement;
-
- WarnOnUseElementX(WrappedMessage this.warning, WrappedMessage this.info,
- Element enclosingElement, Element wrappedElement)
- : this.wrappedElement = wrappedElement,
- super(wrappedElement.name, ElementKind.WARN_ON_USE, enclosingElement);
-
- Element unwrap(DiagnosticListener listener, Spannable usageSpannable) {
- var unwrapped = wrappedElement;
- if (warning != null) {
- Spannable spannable = warning.spannable;
- if (spannable == null) spannable = usageSpannable;
- listener.reportWarning(
- spannable, warning.messageKind, warning.messageArguments);
- }
- if (info != null) {
- Spannable spannable = info.spannable;
- if (spannable == null) spannable = usageSpannable;
- listener.reportInfo(
- spannable, info.messageKind, info.messageArguments);
- }
- if (unwrapped.isWarnOnUse) {
- unwrapped = unwrapped.unwrap(listener, usageSpannable);
- }
- return unwrapped;
- }
-
- accept(ElementVisitor visitor) => visitor.visitWarnOnUseElement(this);
-}
-
-class AmbiguousElementX extends ElementX implements AmbiguousElement {
- /**
- * The message to report on resolving this element.
- */
- final MessageKind messageKind;
-
- /**
- * The message arguments to report on resolving this element.
- */
- final Map messageArguments;
-
- /**
- * The first element that this ambiguous element might refer to.
- */
- final Element existingElement;
-
- /**
- * The second element that this ambiguous element might refer to.
- */
- final Element newElement;
-
- AmbiguousElementX(this.messageKind, this.messageArguments,
- Element enclosingElement, Element existingElement, Element newElement)
- : this.existingElement = existingElement,
- this.newElement = newElement,
- super(existingElement.name, ElementKind.AMBIGUOUS, enclosingElement);
-
- Setlet flatten() {
- Element element = this;
- var set = new Setlet();
- while (element.isAmbiguous) {
- AmbiguousElement ambiguous = element;
- set.add(ambiguous.newElement);
- element = ambiguous.existingElement;
- }
- set.add(element);
- return set;
- }
-
- void diagnose(Element context, DiagnosticListener listener) {
- Setlet ambiguousElements = flatten();
- MessageKind code = (ambiguousElements.length == 1)
- ? MessageKind.AMBIGUOUS_REEXPORT : MessageKind.AMBIGUOUS_LOCATION;
- LibraryElementX importer = context.library;
- for (Element element in ambiguousElements) {
- var arguments = {'name': element.name};
- listener.reportInfo(element, code, arguments);
- Link<Import> importers = importer.importers.getImports(element);
- listener.withCurrentElement(importer, () {
- for (; !importers.isEmpty; importers = importers.tail) {
- listener.reportInfo(
- importers.head, MessageKind.IMPORTED_HERE, arguments);
- }
- });
- }
- }
-
- accept(ElementVisitor visitor) => visitor.visitAmbiguousElement(this);
-
- bool get isTopLevel => false;
-}
-
-class ScopeX {
- final Map<String, Element> contents = new Map<String, Element>();
-
- bool get isEmpty => contents.isEmpty;
- Iterable<Element> get values => contents.values;
-
- Element lookup(String name) {
- return contents[name];
- }
-
- void add(Element element, DiagnosticListener listener) {
- String name = element.name;
- if (element.isAccessor) {
- addAccessor(element, contents[name], listener);
- } else {
- Element existing = contents.putIfAbsent(name, () => element);
- if (!identical(existing, element)) {
- listener.reportError(
- element, MessageKind.DUPLICATE_DEFINITION, {'name': name});
- listener.reportInfo(existing,
- MessageKind.EXISTING_DEFINITION, {'name': name});
- }
- }
- }
-
- /**
- * Adds a definition for an [accessor] (getter or setter) to a scope.
- * The definition binds to an abstract field that can hold both a getter
- * and a setter.
- *
- * The abstract field is added once, for the first getter or setter, and
- * reused if the other one is also added.
- * The abstract field should not be treated as a proper member of the
- * container, it's simply a way to return two results for one lookup.
- * That is, the getter or setter does not have the abstract field as enclosing
- * element, they are enclosed by the class or compilation unit, as is the
- * abstract field.
- */
- void addAccessor(FunctionElementX accessor,
- Element existing,
- DiagnosticListener listener) {
- void reportError(Element other) {
- listener.reportError(accessor,
- MessageKind.DUPLICATE_DEFINITION,
- {'name': accessor.name});
- // TODO(johnniwinther): Make this an info instead of a fatal error.
- listener.reportFatalError(other,
- MessageKind.EXISTING_DEFINITION,
- {'name': accessor.name});
- }
-
- if (existing != null) {
- if (!identical(existing.kind, ElementKind.ABSTRACT_FIELD)) {
- reportError(existing);
- } else {
- AbstractFieldElementX field = existing;
- accessor.abstractField = field;
- if (accessor.isGetter) {
- if (field.getter != null && field.getter != accessor) {
- reportError(field.getter);
- }
- field.getter = accessor;
- } else {
- assert(accessor.isSetter);
- if (field.setter != null && field.setter != accessor) {
- reportError(field.setter);
- }
- field.setter = accessor;
- }
- }
- } else {
- Element container = accessor.enclosingClassOrCompilationUnit;
- AbstractFieldElementX field =
- new AbstractFieldElementX(accessor.name, container);
- accessor.abstractField = field;
- if (accessor.isGetter) {
- field.getter = accessor;
- } else {
- field.setter = accessor;
- }
- add(field, listener);
- }
- }
-}
-
-class CompilationUnitElementX extends ElementX
- implements CompilationUnitElement {
- final Script script;
- PartOf partTag;
- Link<Element> localMembers = const Link<Element>();
-
- CompilationUnitElementX(Script script, LibraryElement library)
- : this.script = script,
- super(script.name,
- ElementKind.COMPILATION_UNIT,
- library) {
- library.addCompilationUnit(this);
- }
-
- void forEachLocalMember(f(Element element)) {
- localMembers.forEach(f);
- }
-
- void addMember(Element element, DiagnosticListener listener) {
- // Keep a list of top level members.
- localMembers = localMembers.prepend(element);
- // Provide the member to the library to build scope.
- if (enclosingElement.isPatch) {
- implementationLibrary.addMember(element, listener);
- } else {
- library.addMember(element, listener);
- }
- }
-
- void setPartOf(PartOf tag, DiagnosticListener listener) {
- LibraryElementX library = enclosingElement;
- if (library.entryCompilationUnit == this) {
- listener.reportError(tag, MessageKind.ILLEGAL_DIRECTIVE);
- return;
- }
- if (!localMembers.isEmpty) {
- listener.reportError(tag, MessageKind.BEFORE_TOP_LEVEL);
- return;
- }
- if (partTag != null) {
- listener.reportWarning(tag, MessageKind.DUPLICATED_PART_OF);
- return;
- }
- partTag = tag;
- LibraryName libraryTag = library.libraryTag;
- String actualName = tag.name.toString();
- if (libraryTag != null) {
- String expectedName = libraryTag.name.toString();
- if (expectedName != actualName) {
- listener.reportWarning(tag.name,
- MessageKind.LIBRARY_NAME_MISMATCH,
- {'libraryName': expectedName});
- }
- } else {
- listener.reportWarning(library,
- MessageKind.MISSING_LIBRARY_NAME,
- {'libraryName': actualName});
- listener.reportInfo(tag.name,
- MessageKind.THIS_IS_THE_PART_OF_TAG);
- }
- }
-
- bool get hasMembers => !localMembers.isEmpty;
-
- int compareTo(CompilationUnitElement other) {
- if (this == other) return 0;
- return '${script.readableUri}'.compareTo('${other.script.readableUri}');
- }
-
- Element get analyzableElement => library;
-
- accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this);
-}
-
-class Importers {
- Map<Element, Link<Import>> importers = new Map<Element, Link<Import>>();
-
- Link<Import> getImports(Element element) {
- Link<Import> imports = importers[element];
- return imports != null ? imports : const Link<Import>();
- }
-
- Import getImport(Element element) => getImports(element).head;
-
- void registerImport(Element element, Import import) {
- if (import == null) return;
-
- importers[element] =
- importers.putIfAbsent(element, () => const Link<Import>())
- .prepend(import);
- }
-}
-
-class ImportScope {
- /**
- * Map for elements imported through import declarations.
- *
- * Addition to the map is performed by [addImport]. Lookup is done trough
- * [find].
- */
- final Map<String, Element> importScope =
- new Map<String, Element>();
-
- /**
- * Adds [element] to the import scope of this library.
- *
- * If an element by the same name is already in the imported scope, an
- * [ErroneousElement] will be put in the imported scope, allowing for
- * detection of ambiguous uses of imported names.
- */
- void addImport(Element enclosingElement,
- Element element,
- Import import,
- DiagnosticListener listener) {
- LibraryElementX library = enclosingElement.library;
- Importers importers = library.importers;
-
- String name = element.name;
-
- // The loadLibrary function always shadows existing bindings to that name.
- if (element.isDeferredLoaderGetter) {
- importScope.remove(name);
- // TODO(sigurdm): Print a hint.
- }
- Element existing = importScope.putIfAbsent(name, () => element);
- importers.registerImport(element, import);
-
- void registerWarnOnUseElement(Import import,
- MessageKind messageKind,
- Element hidingElement,
- Element hiddenElement) {
- Uri hiddenUri = hiddenElement.library.canonicalUri;
- Uri hidingUri = hidingElement.library.canonicalUri;
- Element element = new WarnOnUseElementX(
- new WrappedMessage(
- null, // Report on reference to [hidingElement].
- messageKind,
- {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}),
- new WrappedMessage(
- listener.spanFromSpannable(import),
- MessageKind.IMPORTED_HERE,
- {'name': name}),
- enclosingElement, hidingElement);
- importScope[name] = element;
- importers.registerImport(element, import);
- }
-
- if (existing != element) {
- Import existingImport = importers.getImport(existing);
- Element newElement;
- if (existing.library.isPlatformLibrary &&
- !element.library.isPlatformLibrary) {
- // [existing] is implicitly hidden.
- registerWarnOnUseElement(
- import, MessageKind.HIDDEN_IMPORT, element, existing);
- } else if (!existing.library.isPlatformLibrary &&
- element.library.isPlatformLibrary) {
- // [element] is implicitly hidden.
- if (import == null) {
- // [element] is imported implicitly (probably through dart:core).
- registerWarnOnUseElement(
- existingImport, MessageKind.HIDDEN_IMPLICIT_IMPORT,
- existing, element);
- } else {
- registerWarnOnUseElement(
- import, MessageKind.HIDDEN_IMPORT, existing, element);
- }
- } else {
- Element ambiguousElement = new AmbiguousElementX(
- MessageKind.DUPLICATE_IMPORT, {'name': name},
- enclosingElement, existing, element);
- importScope[name] = ambiguousElement;
- importers.registerImport(ambiguousElement, import);
- importers.registerImport(ambiguousElement, existingImport);
- }
- }
- }
-
- Element operator [](String name) => importScope[name];
-}
-
-class LibraryElementX
- extends ElementX with AnalyzableElementX, PatchMixin<LibraryElementX>
- implements LibraryElement {
- final Uri canonicalUri;
- CompilationUnitElement entryCompilationUnit;
- Link<CompilationUnitElement> compilationUnits =
- const Link<CompilationUnitElement>();
- LinkBuilder<LibraryTag> tagsBuilder = new LinkBuilder<LibraryTag>();
- List<LibraryTag> tagsCache;
- LibraryName libraryTag;
- bool canUseNative = false;
- Link<Element> localMembers = const Link<Element>();
- final ScopeX localScope = new ScopeX();
- final ImportScope importScope = new ImportScope();
-
- /// A mapping from an imported element to the "import" tag.
- final Importers importers = new Importers();
-
- /**
- * Link for elements exported either through export declarations or through
- * declaration. This field should not be accessed directly but instead through
- * the [exports] getter.
- *
- * [LibraryDependencyHandler] sets this field through [setExports] when the
- * library is loaded.
- */
- Link<Element> slotForExports;
-
- final Map<LibraryDependency, LibraryElement> tagMapping =
- new Map<LibraryDependency, LibraryElement>();
-
- LibraryElementX(Script script,
- [Uri canonicalUri, LibraryElementX origin])
- : this.canonicalUri =
- ((canonicalUri == null) ? script.readableUri : canonicalUri),
- super(script.name, ElementKind.LIBRARY, null) {
- entryCompilationUnit = new CompilationUnitElementX(script, this);
- if (origin != null) {
- origin.applyPatch(this);
- }
- }
-
- bool get isDartCore => canonicalUri == Compiler.DART_CORE;
-
- Link<MetadataAnnotation> get metadata {
- return (libraryTag == null) ? super.metadata : libraryTag.metadata;
- }
-
- set metadata(value) {
- // The metadata is stored on [libraryTag].
- throw new SpannableAssertionFailure(this, 'Cannot set metadata on Library');
- }
-
- CompilationUnitElement get compilationUnit => entryCompilationUnit;
-
- Element get analyzableElement => this;
-
- void addCompilationUnit(CompilationUnitElement element) {
- compilationUnits = compilationUnits.prepend(element);
- }
-
- void addTag(LibraryTag tag, DiagnosticListener listener) {
- if (tagsCache != null) {
- listener.internalError(tag,
- "Library tags for $this have already been computed.");
- }
- tagsBuilder.addLast(tag);
- }
-
- Iterable<LibraryTag> get tags {
- if (tagsCache == null) {
- tagsCache = tagsBuilder.toList();
- tagsBuilder = null;
- }
- return tagsCache;
- }
-
- void recordResolvedTag(LibraryDependency tag, LibraryElement library) {
- assert(tagMapping[tag] == null);
- tagMapping[tag] = library;
- }
-
- LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag];
-
- /**
- * Adds [element] to the import scope of this library.
- *
- * If an element by the same name is already in the imported scope, an
- * [ErroneousElement] will be put in the imported scope, allowing for
- * detection of ambiguous uses of imported names.
- */
- void addImport(Element element, Import import, DiagnosticListener listener) {
- importScope.addImport(this, element, import, listener);
- }
-
- void addMember(Element element, DiagnosticListener listener) {
- localMembers = localMembers.prepend(element);
- addToScope(element, listener);
- }
-
- void addToScope(Element element, DiagnosticListener listener) {
- localScope.add(element, listener);
- }
-
- Element localLookup(String elementName) {
- Element result = localScope.lookup(elementName);
- if (result == null && isPatch) {
- result = origin.localLookup(elementName);
- }
- return result;
- }
-
- /**
- * Returns [:true:] if the export scope has already been computed for this
- * library.
- */
- bool get exportsHandled => slotForExports != null;
-
- Link<Element> get exports {
- assert(invariant(this, exportsHandled,
- message: 'Exports not handled on $this'));
- return slotForExports;
- }
-
- /**
- * Sets the export scope of this library. This method can only be called once.
- */
- void setExports(Iterable<Element> exportedElements) {
- assert(invariant(this, !exportsHandled,
- message: 'Exports already set to $slotForExports on $this'));
- assert(invariant(this, exportedElements != null));
- var builder = new LinkBuilder<Element>();
- for (Element export in exportedElements) {
- builder.addLast(export);
- }
- slotForExports = builder.toLink();
- }
-
- LibraryElement get library => isPatch ? origin : this;
-
- /**
- * Look up a top-level element in this library. The element could
- * potentially have been imported from another library. Returns
- * null if no such element exist and an [ErroneousElement] if multiple
- * elements have been imported.
- */
- Element find(String elementName) {
- Element result = localScope.lookup(elementName);
- if (result != null) return result;
- if (origin != null) {
- result = origin.localScope.lookup(elementName);
- if (result != null) return result;
- }
- result = importScope[elementName];
- if (result != null) return result;
- if (origin != null) {
- result = origin.importScope[elementName];
- if (result != null) return result;
- }
- return null;
- }
-
- /** Look up a top-level element in this library, but only look for
- * non-imported elements. Returns null if no such element exist. */
- Element findLocal(String elementName) {
- // TODO(johnniwinther): How to handle injected elements in the patch
- // library?
- Element result = localScope.lookup(elementName);
- if (result == null || result.library != this) return null;
- return result;
- }
-
- Element findExported(String elementName) {
- for (Link link = exports; !link.isEmpty; link = link.tail) {
- Element element = link.head;
- if (element.name == elementName) return element;
- }
- return null;
- }
-
- void forEachExport(f(Element element)) {
- exports.forEach((Element e) => f(e));
- }
-
- Link<Import> getImportsFor(Element element) => importers.getImports(element);
-
- void forEachLocalMember(f(Element element)) {
- if (isPatch) {
- // Patch libraries traverse both origin and injected members.
- origin.localMembers.forEach(f);
-
- void filterPatch(Element element) {
- if (!element.isPatch) {
- // Do not traverse the patch members.
- f(element);
- }
- }
- localMembers.forEach(filterPatch);
- } else {
- localMembers.forEach(f);
- }
- }
-
- Iterable<Element> getNonPrivateElementsInScope() {
- return localScope.values.where((Element element) {
- // At this point [localScope] only contains members so we don't need
- // to check for foreign or prefix elements.
- return !isPrivateName(element.name);
- });
- }
-
- bool hasLibraryName() => libraryTag != null;
-
- /**
- * Returns the library name, which is either the name given in the library tag
- * or the empty string if there is no library tag.
- */
- String getLibraryName() {
- if (libraryTag == null) return '';
- return libraryTag.name.toString();
- }
-
- /**
- * Returns the library name (as defined by the library tag) or for script
- * (which have no library tag) the script file name. The latter case is used
- * to private 'library name' for scripts to use for instance in dartdoc.
- *
- * Note: the returned filename will still be escaped ("a%20b.dart" instead of
- * "a b.dart").
- */
- String getLibraryOrScriptName() {
- if (libraryTag != null) {
- return libraryTag.name.toString();
- } else {
- // Use the file name as script name.
- String path = canonicalUri.path;
- return path.substring(path.lastIndexOf('/') + 1);
- }
- }
-
- Scope buildScope() => new LibraryScope(this);
-
- bool get isPlatformLibrary => canonicalUri.scheme == 'dart';
-
- bool get isPackageLibrary => canonicalUri.scheme == 'package';
-
- bool get isInternalLibrary =>
- isPlatformLibrary && canonicalUri.path.startsWith('_');
-
- String toString() {
- if (origin != null) {
- return 'patch library(${canonicalUri})';
- } else if (patch != null) {
- return 'origin library(${canonicalUri})';
- } else {
- return 'library(${canonicalUri})';
- }
- }
-
- int compareTo(LibraryElement other) {
- if (this == other) return 0;
- return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName());
- }
-
- accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);
-
- // TODO(johnniwinther): Remove these when issue 18630 is fixed.
- LibraryElementX get patch => super.patch;
- LibraryElementX get origin => super.origin;
-}
-
-class PrefixElementX extends ElementX implements PrefixElement {
- Token firstPosition;
-
- final ImportScope importScope = new ImportScope();
-
- bool get isDeferred => _deferredImport != null;
-
- // Only needed for deferred imports.
- Import _deferredImport;
- Import get deferredImport => _deferredImport;
-
- PrefixElementX(String prefix, Element enclosing, this.firstPosition)
- : super(prefix, ElementKind.PREFIX, enclosing);
-
- bool get isTopLevel => false;
-
- Element lookupLocalMember(String memberName) => importScope[memberName];
-
- DartType computeType(Compiler compiler) => const DynamicType();
-
- Token get position => firstPosition;
-
- void addImport(Element element, Import import, DiagnosticListener listener) {
- importScope.addImport(this, element, import, listener);
- }
-
- accept(ElementVisitor visitor) => visitor.visitPrefixElement(this);
-
- void markAsDeferred(Import deferredImport) {
- _deferredImport = deferredImport;
- }
-}
-
-class TypedefElementX extends ElementX
- with AstElementMixin,
- AnalyzableElementX,
- TypeDeclarationElementX<TypedefType>
- implements TypedefElement {
- Typedef cachedNode;
-
- /**
- * The type annotation which defines this typedef.
- */
- DartType alias;
-
- /// [:true:] if the typedef has been checked for cyclic reference.
- bool hasBeenCheckedForCycles = false;
-
- int resolutionState = STATE_NOT_STARTED;
-
- TypedefElementX(String name, Element enclosing)
- : super(name, ElementKind.TYPEDEF, enclosing);
-
- bool get hasNode => cachedNode != null;
-
- Typedef get node {
- assert(invariant(this, cachedNode != null,
- message: "Node has not been computed for $this."));
- return cachedNode;
- }
-
- /**
- * Function signature for a typedef of a function type. The signature is
- * kept to provide full information about parameter names through the mirror
- * system.
- *
- * The [functionSignature] is not available until the typedef element has been
- * resolved.
- */
- FunctionSignature functionSignature;
-
- TypedefType computeType(Compiler compiler) {
- if (thisTypeCache != null) return thisTypeCache;
- Typedef node = parseNode(compiler);
- setThisAndRawTypes(compiler, createTypeVariables(node.typeParameters));
- ensureResolved(compiler);
- return thisTypeCache;
- }
-
- void ensureResolved(Compiler compiler) {
- if (resolutionState == STATE_NOT_STARTED) {
- compiler.resolver.resolve(this);
- }
- }
-
- TypedefType createType(List<DartType> typeArguments) {
- return new TypedefType(this, typeArguments);
- }
-
- Scope buildScope() {
- return new TypeDeclarationScope(enclosingElement.buildScope(), this);
- }
-
- void checkCyclicReference(Compiler compiler) {
- if (hasBeenCheckedForCycles) return;
- var visitor = new TypedefCyclicVisitor(compiler, this);
- computeType(compiler).accept(visitor, null);
- hasBeenCheckedForCycles = true;
- }
-
- accept(ElementVisitor visitor) => visitor.visitTypedefElement(this);
-
- // A typedef cannot be patched therefore defines itself.
- AstElement get definingElement => this;
-}
-
-// This class holds common information for a list of variable or field
-// declarations. It contains the node, and the type. A [VariableElementX]
-// forwards its [computeType] and [parseNode] methods to this class.
-class VariableList implements DeclarationSite {
- VariableDefinitions definitions;
- DartType type;
- final Modifiers modifiers;
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
-
- VariableList(Modifiers this.modifiers);
-
- VariableList.node(VariableDefinitions node, this.type)
- : this.definitions = node,
- this.modifiers = node.modifiers {
- assert(modifiers != null);
- }
-
- VariableDefinitions parseNode(Element element, DiagnosticListener listener) {
- return definitions;
- }
-
- DartType computeType(Element element, Compiler compiler) => type;
-}
-
-abstract class VariableElementX extends ElementX with AstElementMixin
- implements VariableElement {
- final Token token;
- final VariableList variables;
- VariableDefinitions definitionsCache;
- Expression initializerCache;
-
- Modifiers get modifiers => variables.modifiers;
-
- VariableElementX(String name,
- ElementKind kind,
- Element enclosingElement,
- VariableList variables,
- this.token)
- : this.variables = variables,
- super(name, kind, enclosingElement);
-
- // TODO(johnniwinther): Ensure that the [TreeElements] for this variable hold
- // the mappings for all its metadata.
- Link<MetadataAnnotation> get metadata => variables.metadata;
-
- void addMetadataInternal(MetadataAnnotation annotation) {
- variables.metadata = variables.metadata.prepend(annotation);
- }
-
- // A variable cannot be patched therefore defines itself.
- AstElement get definingElement => this;
-
- bool get hasNode => definitionsCache != null;
-
- VariableDefinitions get node {
- assert(invariant(this, definitionsCache != null,
- message: "Node has not been computed for $this."));
- return definitionsCache;
- }
-
- Expression get initializer {
- assert(invariant(this, definitionsCache != null,
- message: "Initializer has not been computed for $this."));
- return initializerCache;
- }
-
- Node parseNode(DiagnosticListener listener) {
- if (definitionsCache != null) return definitionsCache;
-
- VariableDefinitions definitions = variables.parseNode(this, listener);
- createDefinitions(definitions);
- return definitionsCache;
- }
-
- void createDefinitions(VariableDefinitions definitions) {
- assert(invariant(this, definitionsCache == null,
- message: "VariableDefinitions has already been computed for $this."));
- Expression node;
- int count = 0;
- for (Link<Node> link = definitions.definitions.nodes;
- !link.isEmpty; link = link.tail) {
- Expression initializedIdentifier = link.head;
- Identifier identifier = initializedIdentifier.asIdentifier();
- if (identifier == null) {
- SendSet sendSet = initializedIdentifier.asSendSet();
- identifier = sendSet.selector.asIdentifier();
- if (identical(name, identifier.source)) {
- node = initializedIdentifier;
- initializerCache = sendSet.arguments.first;
- }
- } else if (identical(name, identifier.source)) {
- node = initializedIdentifier;
- }
- count++;
- }
- invariant(definitions, node != null, message: "Could not find '$name'.");
- if (count == 1) {
- definitionsCache = definitions;
- } else {
- // Create a [VariableDefinitions] node for the single definition of
- // [node].
- definitionsCache = new VariableDefinitions(definitions.type,
- definitions.modifiers, new NodeList(
- definitions.definitions.beginToken,
- const Link<Node>().prepend(node),
- definitions.definitions.endToken));
- }
- }
-
- DartType computeType(Compiler compiler) {
- if (variables.type != null) return variables.type;
- // Call [parseNode] to ensure that [definitionsCache] and [initializerCache]
- // are set as a consequence of calling [computeType].
- return compiler.withCurrentElement(this, () {
- parseNode(compiler);
- return variables.computeType(this, compiler);
- });
- }
-
- DartType get type {
- assert(invariant(this, variables.type != null,
- message: "Type has not been computed for $this."));
- return variables.type;
- }
-
- bool get isInstanceMember => isClassMember && !isStatic;
-
- // Note: cachedNode.beginToken will not be correct in all
- // cases, for example, for function typed parameters.
- Token get position => token;
-
- accept(ElementVisitor visitor) => visitor.visitVariableElement(this);
-
- DeclarationSite get declarationSite => variables;
-}
-
-class LocalVariableElementX extends VariableElementX
- implements LocalVariableElement {
- LocalVariableElementX(String name,
- ExecutableElement enclosingElement,
- VariableList variables,
- Token token)
- : super(name, ElementKind.VARIABLE, enclosingElement, variables, token) {
- createDefinitions(variables.definitions);
- }
-
- ExecutableElement get executableContext => enclosingElement;
-
- ExecutableElement get memberContext => executableContext.memberContext;
-
- bool get isLocal => true;
-}
-
-class FieldElementX extends VariableElementX
- with AnalyzableElementX implements FieldElement {
- List<FunctionElement> nestedClosures = new List<FunctionElement>();
-
- FieldElementX(Identifier name,
- Element enclosingElement,
- VariableList variables)
- : super(name.source, ElementKind.FIELD, enclosingElement,
- variables, name.token);
-
- accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
-
- MemberElement get memberContext => this;
-
- void reuseElement() {
- super.reuseElement();
- nestedClosures.clear();
- }
-}
-
-/// [Element] for a parameter-like element.
-class FormalElementX extends ElementX
- with AstElementMixin
- implements FormalElement {
- final VariableDefinitions definitions;
- final Identifier identifier;
- DartType typeCache;
-
- /**
- * Function signature for a variable with a function type. The signature is
- * kept to provide full information about parameter names through the mirror
- * system.
- */
- FunctionSignature functionSignatureCache;
-
- FormalElementX(ElementKind elementKind,
- FunctionTypedElement enclosingElement,
- this.definitions,
- Identifier identifier)
- : this.identifier = identifier,
- super(identifier.source, elementKind, enclosingElement);
-
- FunctionTypedElement get functionDeclaration => enclosingElement;
-
- Modifiers get modifiers => definitions.modifiers;
-
- Token get position => identifier.getBeginToken();
-
- Node parseNode(DiagnosticListener listener) => definitions;
-
- DartType computeType(Compiler compiler) {
- assert(invariant(this, type != null,
- message: "Parameter type has not been set for $this."));
- return type;
- }
-
- DartType get type {
- assert(invariant(this, typeCache != null,
- message: "Parameter type has not been set for $this."));
- return typeCache;
- }
-
- FunctionSignature get functionSignature {
- assert(invariant(this, typeCache != null,
- message: "Parameter signature has not been set for $this."));
- return functionSignatureCache;
- }
-
- bool get hasNode => true;
-
- VariableDefinitions get node => definitions;
-
- FunctionType get functionType => type;
-
- accept(ElementVisitor visitor) => visitor.visitFormalElement(this);
-
- // A parameter is defined by the declaration element.
- AstElement get definingElement => declaration;
-}
-
-/// [Element] for a formal parameter.
-///
-/// A [ParameterElementX] can be patched. A parameter of an external method is
-/// patched with the corresponding parameter of the patch method. This is done
-/// to ensure that default values on parameters are computed once (on the
-/// origin parameter) but can be found through both the origin and the patch.
-abstract class ParameterElementX extends FormalElementX
- with PatchMixin<ParameterElement> implements ParameterElement {
- final Expression initializer;
-
- ParameterElementX(ElementKind elementKind,
- FunctionElement functionDeclaration,
- VariableDefinitions definitions,
- Identifier identifier,
- this.initializer)
- : super(elementKind, functionDeclaration, definitions, identifier);
-
- FunctionElement get functionDeclaration => enclosingElement;
-
- ExecutableElement get executableContext => enclosingElement;
-
- MemberElement get memberContext => executableContext.memberContext;
-
- accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
-
- bool get isLocal => true;
-}
-
-class LocalParameterElementX extends ParameterElementX
- implements LocalParameterElement {
- LocalParameterElementX(FunctionElement functionDeclaration,
- VariableDefinitions definitions,
- Identifier identifier,
- Expression initializer)
- : super(ElementKind.PARAMETER, functionDeclaration,
- definitions, identifier, initializer);
-}
-
-/// Parameters in constructors that directly initialize fields. For example:
-/// `A(this.field)`.
-class InitializingFormalElementX extends ParameterElementX
- implements InitializingFormalElement {
- FieldElement fieldElement;
-
- InitializingFormalElementX(ConstructorElement constructorDeclaration,
- VariableDefinitions variables,
- Identifier identifier,
- Expression initializer,
- this.fieldElement)
- : super(ElementKind.INITIALIZING_FORMAL, constructorDeclaration,
- variables, identifier, initializer);
-
- accept(ElementVisitor visitor) => visitor.visitFieldParameterElement(this);
-
- MemberElement get memberContext => enclosingElement;
-
- bool get isLocal => false;
-}
-
-
-class AbstractFieldElementX extends ElementX implements AbstractFieldElement {
- FunctionElementX getter;
- FunctionElementX setter;
-
- AbstractFieldElementX(String name, Element enclosing)
- : super(name, ElementKind.ABSTRACT_FIELD, enclosing);
-
- DartType computeType(Compiler compiler) {
- throw "internal error: AbstractFieldElement has no type";
- }
-
- Node parseNode(DiagnosticListener listener) {
- throw "internal error: AbstractFieldElement has no node";
- }
-
- Token get position {
- // The getter and setter may be defined in two different
- // compilation units. However, we know that one of them is
- // non-null and defined in the same compilation unit as the
- // abstract element.
- // TODO(lrn): No we don't know that if the element from the same
- // compilation unit is patched.
- //
- // We need to make sure that the position returned is relative to
- // the compilation unit of the abstract element.
- if (getter != null
- && identical(getter.compilationUnit, compilationUnit)) {
- return getter.position;
- } else {
- return setter.position;
- }
- }
-
- Modifiers get modifiers {
- // The resolver ensures that the flags match (ignoring abstract).
- if (getter != null) {
- return new Modifiers.withFlags(
- getter.modifiers.nodes,
- getter.modifiers.flags | Modifiers.FLAG_ABSTRACT);
- } else {
- return new Modifiers.withFlags(
- setter.modifiers.nodes,
- setter.modifiers.flags | Modifiers.FLAG_ABSTRACT);
- }
- }
-
- bool get isInstanceMember {
- return isClassMember && !isStatic;
- }
-
- accept(ElementVisitor visitor) => visitor.visitAbstractFieldElement(this);
-
- bool get isAbstract {
- return getter != null && getter.isAbstract
- || setter != null && setter.isAbstract;
- }
-}
-
-// TODO(johnniwinther): [FunctionSignature] should be merged with
-// [FunctionType].
-// TODO(karlklose): all these lists should have element type [FormalElement].
-class FunctionSignatureX implements FunctionSignature {
- final Link<Element> requiredParameters;
- final Link<Element> optionalParameters;
- final int requiredParameterCount;
- final int optionalParameterCount;
- final bool optionalParametersAreNamed;
- final List<Element> orderedOptionalParameters;
- final FunctionType type;
- final bool hasOptionalParameters;
-
- FunctionSignatureX(this.requiredParameters,
- Link<Element> optionalParameters,
- this.requiredParameterCount,
- this.optionalParameterCount,
- this.optionalParametersAreNamed,
- this.orderedOptionalParameters,
- this.type)
- : optionalParameters = optionalParameters,
- hasOptionalParameters = !optionalParameters.isEmpty;
-
- void forEachRequiredParameter(void function(Element parameter)) {
- for (Link<Element> link = requiredParameters;
- !link.isEmpty;
- link = link.tail) {
- function(link.head);
- }
- }
-
- void forEachOptionalParameter(void function(Element parameter)) {
- for (Link<Element> link = optionalParameters;
- !link.isEmpty;
- link = link.tail) {
- function(link.head);
- }
- }
-
- Element get firstOptionalParameter => optionalParameters.head;
-
- void forEachParameter(void function(Element parameter)) {
- forEachRequiredParameter(function);
- forEachOptionalParameter(function);
- }
-
- void orderedForEachParameter(void function(Element parameter)) {
- forEachRequiredParameter(function);
- orderedOptionalParameters.forEach(function);
- }
-
- int get parameterCount => requiredParameterCount + optionalParameterCount;
-
- /**
- * Check whether a function with this signature can be used instead of a
- * function with signature [signature] without causing a `noSuchMethod`
- * exception/call.
- */
- bool isCompatibleWith(FunctionSignature signature) {
- if (optionalParametersAreNamed) {
- if (!signature.optionalParametersAreNamed) {
- return requiredParameterCount == signature.parameterCount;
- }
- // If both signatures have named parameters, then they must have
- // the same number of required parameters, and the names in
- // [signature] must all be in [:this:].
- if (requiredParameterCount != signature.requiredParameterCount) {
- return false;
- }
- Set<String> names = optionalParameters.mapToSet(
- (Element element) => element.name);
- for (Element namedParameter in signature.optionalParameters) {
- if (!names.contains(namedParameter.name)) {
- return false;
- }
- }
- } else {
- if (signature.optionalParametersAreNamed) return false;
- // There must be at least as many arguments as in the other signature, but
- // this signature must not have more required parameters. Having more
- // optional parameters is not a problem, they simply are never provided
- // by call sites of a call to a method with the other signature.
- int otherTotalCount = signature.parameterCount;
- return requiredParameterCount <= otherTotalCount
- && parameterCount >= otherTotalCount;
- }
- return true;
- }
-}
-
-abstract class BaseFunctionElementX
- extends ElementX with PatchMixin<FunctionElement>, AstElementMixin
- implements FunctionElement {
- DartType typeCache;
- final Modifiers modifiers;
-
- List<FunctionElement> nestedClosures = new List<FunctionElement>();
-
- FunctionSignature functionSignatureCache;
-
- final bool _hasNoBody;
-
- AbstractFieldElement abstractField;
-
- AsyncMarker asyncMarker = AsyncMarker.SYNC;
-
- BaseFunctionElementX(String name,
- ElementKind kind,
- Modifiers this.modifiers,
- Element enclosing,
- bool hasNoBody)
- : super(name, kind, enclosing),
- _hasNoBody = hasNoBody {
- assert(modifiers != null);
- }
-
- bool get isInstanceMember {
- return isClassMember
- && !isConstructor
- && !isStatic;
- }
-
- bool get hasFunctionSignature => functionSignatureCache != null;
-
- FunctionSignature computeSignature(Compiler compiler) {
- if (functionSignatureCache != null) return functionSignatureCache;
- compiler.withCurrentElement(this, () {
- functionSignatureCache = compiler.resolver.resolveSignature(this);
- });
- return functionSignatureCache;
- }
-
- FunctionSignature get functionSignature {
- assert(invariant(this, functionSignatureCache != null,
- message: "Function signature has not been computed for $this."));
- return functionSignatureCache;
- }
-
- FunctionType computeType(Compiler compiler) {
- if (typeCache != null) return typeCache;
- typeCache = computeSignature(compiler).type;
- return typeCache;
- }
-
- FunctionType get type {
- assert(invariant(this, typeCache != null,
- message: "Type has not been computed for $this."));
- return typeCache;
- }
-
- FunctionElement asFunctionElement() => this;
-
- String toString() {
- if (isPatch) {
- return 'patch ${super.toString()}';
- } else if (isPatched) {
- return 'origin ${super.toString()}';
- } else {
- return super.toString();
- }
- }
-
- bool get isAbstract {
- return !modifiers.isExternal &&
- (isFunction || isAccessor) &&
- _hasNoBody;
- }
-
- accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
-
- // A function is defined by the implementation element.
- AstElement get definingElement => implementation;
-}
-
-abstract class FunctionElementX extends BaseFunctionElementX
- with AnalyzableElementX implements MemberElement {
- FunctionElementX(String name,
- ElementKind kind,
- Modifiers modifiers,
- Element enclosing,
- bool hasNoBody)
- : super(name, kind, modifiers, enclosing, hasNoBody);
-
- MemberElement get memberContext => this;
-
- void reuseElement() {
- super.reuseElement();
- nestedClosures.clear();
- functionSignatureCache = null;
- typeCache = null;
- }
-}
-
-class LocalFunctionElementX extends BaseFunctionElementX
- implements LocalFunctionElement {
- final FunctionExpression node;
-
- LocalFunctionElementX(String name,
- FunctionExpression this.node,
- ElementKind kind,
- Modifiers modifiers,
- ExecutableElement enclosing)
- : super(name, kind, modifiers, enclosing, false);
-
- ExecutableElement get executableContext => enclosingElement;
-
- MemberElement get memberContext => executableContext.memberContext;
-
- bool get hasNode => true;
-
- FunctionExpression parseNode(DiagnosticListener listener) => node;
-
- Token get position {
- // Use the name as position if this is not an unnamed closure.
- if (node.name != null) {
- return node.name.getBeginToken();
- } else {
- return node.getBeginToken();
- }
- }
-
- bool get isLocal => true;
-}
-
-abstract class ConstructorElementX extends FunctionElementX
- implements ConstructorElement {
-
- ConstructorElementX(String name,
- ElementKind kind,
- Modifiers modifiers,
- Element enclosing)
- : super(name, kind, modifiers, enclosing, false);
-
- FunctionElement immediateRedirectionTarget;
-
- bool get isRedirectingFactory => immediateRedirectionTarget != null;
-
- /// This field is set by the post process queue when checking for cycles.
- ConstructorElement internalEffectiveTarget;
- DartType effectiveTargetType;
-
- void set effectiveTarget(ConstructorElement constructor) {
- assert(constructor != null && internalEffectiveTarget == null);
- internalEffectiveTarget = constructor;
- }
-
- ConstructorElement get effectiveTarget {
- if (Elements.isErroneousElement(immediateRedirectionTarget)) {
- return immediateRedirectionTarget;
- }
- assert(!isRedirectingFactory || internalEffectiveTarget != null);
- return isRedirectingFactory ? internalEffectiveTarget : this;
- }
-
- InterfaceType computeEffectiveTargetType(InterfaceType newType) {
- if (!isRedirectingFactory) return newType;
- assert(invariant(this, effectiveTargetType != null,
- message: 'Redirection target type has not yet been computed for '
- '$this.'));
- return effectiveTargetType.substByContext(newType);
- }
-
- ConstructorElement get definingConstructor => null;
-
- ClassElement get enclosingClass => enclosingElement;
-}
-
-class DeferredLoaderGetterElementX extends FunctionElementX {
- final PrefixElement prefix;
-
- DeferredLoaderGetterElementX(PrefixElement prefix)
- : this.prefix = prefix,
- super("loadLibrary",
- ElementKind.FUNCTION,
- Modifiers.EMPTY,
- prefix, true);
-
- FunctionSignature computeSignature(Compiler compiler) {
- if (functionSignatureCache != null) return functionSignature;
- compiler.withCurrentElement(this, () {
- DartType inner = new FunctionType(this);
- functionSignatureCache = new FunctionSignatureX(const Link(),
- const Link(), 0, 0, false, [], inner);
- });
- return functionSignatureCache;
- }
-
- bool get isClassMember => false;
-
- bool isForeign(Backend backend) => true;
-
- bool get isSynthesized => true;
-
- bool get isFunction => false;
-
- bool get isDeferredLoaderGetter => true;
-
- bool get isGetter => true;
-
- bool get isTopLevel => true;
- // By having position null, the enclosing elements location is printed in
- // error messages.
- Token get position => null;
-
- FunctionExpression parseNode(DiagnosticListener listener) => null;
-
- bool get hasNode => false;
-
- FunctionExpression get node => null;
-}
-
-class ConstructorBodyElementX extends BaseFunctionElementX
- implements ConstructorBodyElement {
- ConstructorElement constructor;
-
- ConstructorBodyElementX(FunctionElement constructor)
- : this.constructor = constructor,
- super(constructor.name,
- ElementKind.GENERATIVE_CONSTRUCTOR_BODY,
- Modifiers.EMPTY,
- constructor.enclosingElement, false) {
- functionSignatureCache = constructor.functionSignature;
- }
-
- bool get hasNode => constructor.hasNode;
-
- FunctionExpression get node => constructor.node;
-
- bool get isInstanceMember => true;
-
- FunctionType computeType(Compiler compiler) {
- compiler.internalError(this, '$this.computeType.');
- return null;
- }
-
- Token get position => constructor.position;
-
- Element get outermostEnclosingMemberOrTopLevel => constructor;
-
- Element get analyzableElement => constructor.analyzableElement;
-
- accept(ElementVisitor visitor) => visitor.visitConstructorBodyElement(this);
-
- MemberElement get memberContext => constructor;
-}
-
-/**
- * A constructor that is not defined in the source code but rather implied by
- * the language semantics.
- *
- * This class is used to represent default constructors and forwarding
- * constructors for mixin applications.
- */
-class SynthesizedConstructorElementX extends ConstructorElementX {
- final ConstructorElement definingConstructor;
- final bool isDefaultConstructor;
-
- SynthesizedConstructorElementX(String name,
- this.definingConstructor,
- Element enclosing,
- this.isDefaultConstructor)
- : super(name,
- ElementKind.GENERATIVE_CONSTRUCTOR,
- Modifiers.EMPTY,
- enclosing);
-
- SynthesizedConstructorElementX.forDefault(superMember, Element enclosing)
- : this('', superMember, enclosing, true);
-
- FunctionExpression parseNode(DiagnosticListener listener) => null;
-
- bool get hasNode => false;
-
- FunctionExpression get node => null;
-
- Token get position => enclosingElement.position;
-
- bool get isSynthesized => true;
-
- FunctionSignature computeSignature(compiler) {
- if (functionSignatureCache != null) return functionSignatureCache;
- if (isDefaultConstructor) {
- return functionSignatureCache = new FunctionSignatureX(
- const Link<Element>(), const Link<Element>(), 0, 0, false,
- const <Element>[],
- new FunctionType(this, enclosingClass.thisType));
- }
- if (definingConstructor.isErroneous) {
- return functionSignatureCache =
- compiler.objectClass.localLookup('').computeSignature(compiler);
- }
- // TODO(johnniwinther): Ensure that the function signature (and with it the
- // function type) substitutes type variables correctly.
- return functionSignatureCache =
- definingConstructor.computeSignature(compiler);
- }
-
- accept(ElementVisitor visitor) {
- return visitor.visitFunctionElement(this);
- }
-}
-
-abstract class TypeDeclarationElementX<T extends GenericType>
- implements TypeDeclarationElement {
- /**
- * The `this type` for this type declaration.
- *
- * The type of [:this:] is the generic type based on this element in which
- * the type arguments are the declared type variables. For instance,
- * [:List<E>:] for [:List:] and [:Map<K,V>:] for [:Map:].
- *
- * For a class declaration this is the type of [:this:].
- *
- * This type is computed in [computeType].
- */
- T thisTypeCache;
-
- /**
- * The raw type for this type declaration.
- *
- * The raw type is the generic type base on this element in which the type
- * arguments are all [dynamic]. For instance [:List<dynamic>:] for [:List:]
- * and [:Map<dynamic,dynamic>:] for [:Map:]. For non-generic classes [rawType]
- * is the same as [thisType].
- *
- * The [rawType] field is a canonicalization of the raw type and should be
- * used to distinguish explicit and implicit uses of the [dynamic]
- * type arguments. For instance should [:List:] be the [rawType] of the
- * [:List:] class element whereas [:List<dynamic>:] should be its own
- * instantiation of [InterfaceType] with [:dynamic:] as type argument. Using
- * this distinction, we can print the raw type with type arguments only when
- * the input source has used explicit type arguments.
- *
- * This type is computed together with [thisType] in [computeType].
- */
- T rawTypeCache;
-
- T get thisType {
- assert(invariant(this, thisTypeCache != null,
- message: 'This type has not been computed for $this'));
- return thisTypeCache;
- }
-
- T get rawType {
- assert(invariant(this, rawTypeCache != null,
- message: 'Raw type has not been computed for $this'));
- return rawTypeCache;
- }
-
- T createType(List<DartType> typeArguments);
-
- void setThisAndRawTypes(Compiler compiler, List<DartType> typeParameters) {
- assert(invariant(this, thisTypeCache == null,
- message: "This type has already been set on $this."));
- assert(invariant(this, rawTypeCache == null,
- message: "Raw type has already been set on $this."));
- thisTypeCache = createType(typeParameters);
- if (typeParameters.isEmpty) {
- rawTypeCache = thisTypeCache;
- } else {
- List<DartType> dynamicParameters =
- new List.filled(typeParameters.length, const DynamicType());
- rawTypeCache = createType(dynamicParameters);
- }
- }
-
- List<DartType> get typeVariables => thisType.typeArguments;
-
- /**
- * Creates the type variables, their type and corresponding element, for the
- * type variables declared in [parameter] on [element]. The bounds of the type
- * variables are not set until [element] has been resolved.
- */
- List<DartType> createTypeVariables(NodeList parameters) {
- if (parameters == null) return const <DartType>[];
-
- // Create types and elements for type variable.
- Link<Node> nodes = parameters.nodes;
- List<DartType> arguments =
- new List.generate(nodes.slowLength(), (_) {
- TypeVariable node = nodes.head;
- String variableName = node.name.source;
- nodes = nodes.tail;
- TypeVariableElementX variableElement =
- new TypeVariableElementX(variableName, this, node);
- TypeVariableType variableType = new TypeVariableType(variableElement);
- variableElement.typeCache = variableType;
- return variableType;
- }, growable: false);
- return arguments;
- }
-
- bool get isResolved => resolutionState == STATE_DONE;
-}
-
-abstract class BaseClassElementX extends ElementX
- with AstElementMixin,
- AnalyzableElementX,
- TypeDeclarationElementX<InterfaceType>,
- PatchMixin<ClassElement>,
- ClassMemberMixin
- implements ClassElement {
- final int id;
-
- DartType supertype;
- Link<DartType> interfaces;
- String nativeTagInfo;
- int supertypeLoadState;
- int resolutionState;
- bool isProxy = false;
- bool hasIncompleteHierarchy = false;
-
- // backendMembers are members that have been added by the backend to simplify
- // compilation. They don't have any user-side counter-part.
- Link<Element> backendMembers = const Link<Element>();
-
- OrderedTypeSet allSupertypesAndSelf;
-
- Link<DartType> get allSupertypes => allSupertypesAndSelf.supertypes;
-
- int get hierarchyDepth => allSupertypesAndSelf.maxDepth;
-
- BaseClassElementX(String name,
- Element enclosing,
- this.id,
- int initialState)
- : supertypeLoadState = initialState,
- resolutionState = initialState,
- super(name, ElementKind.CLASS, enclosing);
-
- int get hashCode => id;
-
- bool get hasBackendMembers => !backendMembers.isEmpty;
-
- bool get isUnnamedMixinApplication => false;
-
- InterfaceType computeType(Compiler compiler) {
- if (thisTypeCache == null) {
- computeThisAndRawType(compiler, computeTypeParameters(compiler));
- }
- return thisTypeCache;
- }
-
- void computeThisAndRawType(Compiler compiler, List<DartType> typeVariables) {
- if (thisTypeCache == null) {
- if (origin == null) {
- setThisAndRawTypes(compiler, typeVariables);
- } else {
- thisTypeCache = origin.computeType(compiler);
- rawTypeCache = origin.rawType;
- }
- }
- }
-
- InterfaceType createType(List<DartType> typeArguments) {
- return new InterfaceType(this, typeArguments);
- }
-
- List<DartType> computeTypeParameters(Compiler compiler);
-
- InterfaceType asInstanceOf(ClassElement cls) {
- if (cls == this) return thisType;
- return allSupertypesAndSelf.asInstanceOf(cls);
- }
-
- bool get isObject {
- assert(invariant(this, isResolved,
- message: "isObject has not been computed for $this."));
- return supertype == null;
- }
-
- void ensureResolved(Compiler compiler) {
- if (resolutionState == STATE_NOT_STARTED) {
- compiler.resolver.resolveClass(this);
- }
- }
-
- void setDefaultConstructor(FunctionElement constructor, Compiler compiler);
-
- void addBackendMember(Element member) {
- // TODO(ngeoffray): Deprecate this method.
- assert(member.isGenerativeConstructorBody);
- backendMembers = backendMembers.prepend(member);
- }
-
- void reverseBackendMembers() {
- backendMembers = backendMembers.reverse();
- }
-
- /**
- * Lookup local members in the class. This will ignore constructors.
- */
- Element lookupLocalMember(String memberName) {
- var result = localLookup(memberName);
- if (result != null && result.isConstructor) return null;
- return result;
- }
-
- /// Lookup a synthetic element created by the backend.
- Element lookupBackendMember(String memberName) {
- for (Element element in backendMembers) {
- if (element.name == memberName) {
- return element;
- }
- }
- return null;
- }
- /**
- * Lookup super members for the class. This will ignore constructors.
- */
- Element lookupSuperMember(String memberName) {
- return lookupSuperMemberInLibrary(memberName, library);
- }
-
- /**
- * Lookup super members for the class that is accessible in [library].
- * This will ignore constructors.
- */
- Element lookupSuperMemberInLibrary(String memberName,
- LibraryElement library) {
- bool isPrivate = isPrivateName(memberName);
- for (ClassElement s = superclass; s != null; s = s.superclass) {
- // Private members from a different library are not visible.
- if (isPrivate && !identical(library, s.library)) continue;
- Element e = s.lookupLocalMember(memberName);
- if (e == null) continue;
- // Static members are not inherited.
- if (e.isStatic) continue;
- return e;
- }
- return null;
- }
-
- /**
- * Find the first member in the class chain with the given [selector].
- *
- * This method is NOT to be used for resolving
- * unqualified sends because it does not implement the scoping
- * rules, where library scope comes before superclass scope.
- *
- * When called on the implementation element both members declared in the
- * origin and the patch class are returned.
- */
- Element lookupSelector(Selector selector) {
- return internalLookupSelector(selector, false);
- }
-
- Element lookupSuperSelector(Selector selector) {
- return internalLookupSelector(selector, true);
- }
-
- Element internalLookupSelector(Selector selector,
- bool isSuperLookup) {
- String name = selector.name;
- bool isPrivate = isPrivateName(name);
- LibraryElement library = selector.library;
- for (ClassElement current = isSuperLookup ? superclass : this;
- current != null;
- current = current.superclass) {
- Element member = current.lookupLocalMember(name);
- if (member == null && current.isPatched) {
- // Doing lookups on selectors is done after resolution, so it
- // is safe to look in the patch class.
- member = current.patch.lookupLocalMember(name);
- }
- if (member == null) continue;
- // Private members from a different library are not visible.
- if (isPrivate && !identical(library, member.library)) continue;
- // Static members are not inherited.
- if (member.isStatic && !identical(this, current)) continue;
- // If we find an abstract field we have to make sure that it has
- // the getter or setter part we're actually looking
- // for. Otherwise, we continue up the superclass chain.
- if (member.isAbstractField) {
- AbstractFieldElement field = member;
- FunctionElement getter = field.getter;
- FunctionElement setter = field.setter;
- if (selector.isSetter) {
- // Abstract members can be defined in a super class.
- if (setter != null && !setter.isAbstract) return setter;
- } else {
- assert(selector.isGetter || selector.isCall);
- if (getter != null && !getter.isAbstract) return getter;
- }
- // Abstract members can be defined in a super class.
- } else if (!member.isAbstract) {
- return member;
- }
- }
- return null;
- }
-
- /**
- * Find the first member in the class chain with the given
- * [memberName]. This method is NOT to be used for resolving
- * unqualified sends because it does not implement the scoping
- * rules, where library scope comes before superclass scope.
- */
- Element lookupMember(String memberName) {
- Element localMember = lookupLocalMember(memberName);
- return localMember == null ? lookupSuperMember(memberName) : localMember;
- }
-
- /**
- * Returns true if the [fieldMember] shadows another field. The given
- * [fieldMember] must be a member of this class, i.e. if there is a field of
- * the same name in the superclass chain.
- *
- * This method also works if the [fieldMember] is private.
- */
- bool hasFieldShadowedBy(Element fieldMember) {
- assert(fieldMember.isField);
- String fieldName = fieldMember.name;
- bool isPrivate = isPrivateName(fieldName);
- LibraryElement memberLibrary = fieldMember.library;
- ClassElement lookupClass = this.superclass;
- while (lookupClass != null) {
- Element foundMember = lookupClass.lookupLocalMember(fieldName);
- if (foundMember != null) {
- if (foundMember.isField) {
- if (!isPrivate || memberLibrary == foundMember.library) {
- // Private fields can only be shadowed by a field declared in the
- // same library.
- return true;
- }
- }
- }
- lookupClass = lookupClass.superclass;
- }
- return false;
- }
-
- Element validateConstructorLookupResults(Selector selector,
- Element result,
- Element noMatch(Element)) {
- if (result == null
- || !result.isConstructor
- || (isPrivateName(selector.name)
- && result.library != selector.library)) {
- result = noMatch != null ? noMatch(result) : null;
- }
- return result;
- }
-
- // TODO(aprelev@gmail.com): Peter believes that it would be great to
- // make noMatch a required argument. Peter's suspicion is that most
- // callers of this method would benefit from using the noMatch method.
- Element lookupConstructor(Selector selector, [Element noMatch(Element)]) {
- Element result = localLookup(selector.name);
- return validateConstructorLookupResults(selector, result, noMatch);
- }
-
- Link<Element> get constructors {
- // TODO(ajohnsen): See if we can avoid this method at some point.
- Link<Element> result = const Link<Element>();
- // TODO(johnniwinther): Should we include injected constructors?
- forEachMember((_, Element member) {
- if (member.isConstructor) result = result.prepend(member);
- });
- return result;
- }
-
- /**
- * Returns the super class, if any.
- *
- * The returned element may not be resolved yet.
- */
- ClassElement get superclass {
- assert(supertypeLoadState == STATE_DONE);
- return supertype == null ? null : supertype.element;
- }
-
- /**
- * Runs through all members of this class.
- *
- * The enclosing class is passed to the callback. This is useful when
- * [includeSuperAndInjectedMembers] is [:true:].
- *
- * When called on an implementation element both the members in the origin
- * and patch class are included.
- */
- // TODO(johnniwinther): Clean up lookup to get rid of the include predicates.
- void forEachMember(void f(ClassElement enclosingClass, Element member),
- {includeBackendMembers: false,
- includeSuperAndInjectedMembers: false}) {
- bool includeInjectedMembers = includeSuperAndInjectedMembers || isPatch;
- ClassElement classElement = declaration;
- do {
- // Iterate through the members in textual order, which requires
- // to reverse the data structure [localMembers] we created.
- // Textual order may be important for certain operations, for
- // example when emitting the initializers of fields.
- classElement.forEachLocalMember((e) => f(classElement, e));
- if (includeBackendMembers) {
- classElement.forEachBackendMember((e) => f(classElement, e));
- }
- if (includeInjectedMembers) {
- if (classElement.patch != null) {
- classElement.patch.forEachLocalMember((e) {
- if (!e.isPatch) f(classElement, e);
- });
- }
- }
- classElement = includeSuperAndInjectedMembers
- ? classElement.superclass
- : null;
- } while (classElement != null);
- }
-
- /**
- * Runs through all instance-field members of this class.
- *
- * The enclosing class is passed to the callback. This is useful when
- * [includeSuperAndInjectedMembers] is [:true:].
- *
- * When called on the implementation element both the fields declared in the
- * origin and in the patch are included.
- */
- void forEachInstanceField(void f(ClassElement enclosingClass,
- FieldElement field),
- {bool includeSuperAndInjectedMembers: false}) {
- // Filters so that [f] is only invoked with instance fields.
- void fieldFilter(ClassElement enclosingClass, Element member) {
- if (member.isInstanceMember && member.kind == ElementKind.FIELD) {
- f(enclosingClass, member);
- }
- }
-
- forEachMember(fieldFilter,
- includeSuperAndInjectedMembers: includeSuperAndInjectedMembers);
- }
-
- /// Similar to [forEachInstanceField] but visits static fields.
- void forEachStaticField(void f(ClassElement enclosingClass, Element field)) {
- // Filters so that [f] is only invoked with static fields.
- void fieldFilter(ClassElement enclosingClass, Element member) {
- if (!member.isInstanceMember && member.kind == ElementKind.FIELD) {
- f(enclosingClass, member);
- }
- }
-
- forEachMember(fieldFilter);
- }
-
- void forEachBackendMember(void f(Element member)) {
- backendMembers.forEach(f);
- }
-
- bool implementsInterface(ClassElement intrface) {
- for (DartType implementedInterfaceType in allSupertypes) {
- ClassElement implementedInterface = implementedInterfaceType.element;
- if (identical(implementedInterface, intrface)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns true if [this] is a subclass of [cls].
- *
- * This method is not to be used for checking type hierarchy and
- * assignments, because it does not take parameterized types into
- * account.
- */
- bool isSubclassOf(ClassElement cls) {
- // Use [declaration] for both [this] and [cls], because
- // declaration classes hold the superclass hierarchy.
- cls = cls.declaration;
- for (ClassElement s = declaration; s != null; s = s.superclass) {
- if (identical(s, cls)) return true;
- }
- return false;
- }
-
- bool get isNative => nativeTagInfo != null;
-
- void setNative(String name) {
- // TODO(johnniwinther): Assert that this is only called once. The memory
- // compiler copies pre-processed elements into a new compiler through
- // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
- // method.
- assert(invariant(this, nativeTagInfo == null || nativeTagInfo == name,
- message: "Native tag info set inconsistently on $this: "
- "Existing name '$nativeTagInfo', new name '$name'."));
- nativeTagInfo = name;
- }
-
- FunctionType get callType {
- MemberSignature member =
- lookupInterfaceMember(const PublicName(Compiler.CALL_OPERATOR_NAME));
- return member != null && member.isMethod ? member.type : null;
- }
-
- // TODO(johnniwinther): Remove these when issue 18630 is fixed.
- ClassElement get patch => super.patch;
- ClassElement get origin => super.origin;
-
- // A class declaration is defined by the declaration element.
- AstElement get definingElement => declaration;
-}
-
-abstract class ClassElementX extends BaseClassElementX {
- Link<Element> localMembersReversed = const Link<Element>();
- final ScopeX localScope = new ScopeX();
-
- Link<Element> localMembersCache;
-
- Link<Element> get localMembers {
- if (localMembersCache == null) {
- localMembersCache = localMembersReversed.reverse();
- }
- return localMembersCache;
- }
-
- ClassElementX(String name, Element enclosing, int id, int initialState)
- : super(name, enclosing, id, initialState);
-
- ClassNode parseNode(Compiler compiler);
-
- bool get isMixinApplication => false;
- bool get hasLocalScopeMembers => !localScope.isEmpty;
-
- void addMember(Element element, DiagnosticListener listener) {
- localMembersCache = null;
- localMembersReversed = localMembersReversed.prepend(element);
- addToScope(element, listener);
- }
-
- void addToScope(Element element, DiagnosticListener listener) {
- if (element.isField && element.name == name) {
- listener.reportError(element, MessageKind.MEMBER_USES_CLASS_NAME);
- }
- localScope.add(element, listener);
- }
-
- Element localLookup(String elementName) {
- Element result = localScope.lookup(elementName);
- if (result == null && isPatch) {
- result = origin.localLookup(elementName);
- }
- return result;
- }
-
- void forEachLocalMember(void f(Element member)) {
- localMembers.forEach(f);
- }
-
- bool get hasConstructor {
- // Search in scope to be sure we search patched constructors.
- for (var element in localScope.values) {
- if (element.isConstructor) return true;
- }
- return false;
- }
-
- void setDefaultConstructor(FunctionElement constructor, Compiler compiler) {
- // The default constructor, although synthetic, is part of a class' API.
- addMember(constructor, compiler);
- }
-
- List<DartType> computeTypeParameters(Compiler compiler) {
- ClassNode node = parseNode(compiler);
- return createTypeVariables(node.typeParameters);
- }
-
- Scope buildScope() => new ClassScope(enclosingElement.buildScope(), this);
-
- String toString() {
- if (origin != null) {
- return 'patch ${super.toString()}';
- } else if (patch != null) {
- return 'origin ${super.toString()}';
- } else {
- return super.toString();
- }
- }
-}
-
-class MixinApplicationElementX extends BaseClassElementX
- implements MixinApplicationElement {
- final Node node;
- final Modifiers modifiers;
-
- Link<FunctionElement> constructors = new Link<FunctionElement>();
-
- InterfaceType mixinType;
-
- MixinApplicationElementX(String name, Element enclosing, int id,
- this.node, this.modifiers)
- : super(name, enclosing, id, STATE_NOT_STARTED);
-
- ClassElement get mixin => mixinType != null ? mixinType.element : null;
-
- bool get isMixinApplication => true;
- bool get isUnnamedMixinApplication => node is! NamedMixinApplication;
- bool get hasConstructor => !constructors.isEmpty;
- bool get hasLocalScopeMembers => !constructors.isEmpty;
-
- get patch => null;
- get origin => null;
-
- bool get hasNode => true;
-
- Token get position => node.getBeginToken();
-
- Node parseNode(DiagnosticListener listener) => node;
-
- FunctionElement lookupLocalConstructor(String name) {
- for (Link<Element> link = constructors;
- !link.isEmpty;
- link = link.tail) {
- if (link.head.name == name) return link.head;
- }
- return null;
- }
-
- Element localLookup(String name) {
- Element constructor = lookupLocalConstructor(name);
- if (constructor != null) return constructor;
- if (mixin == null) return null;
- Element mixedInElement = mixin.localLookup(name);
- if (mixedInElement == null) return null;
- return mixedInElement.isInstanceMember ? mixedInElement : null;
- }
-
- void forEachLocalMember(void f(Element member)) {
- constructors.forEach(f);
- if (mixin != null) mixin.forEachLocalMember((Element mixedInElement) {
- if (mixedInElement.isInstanceMember) f(mixedInElement);
- });
- }
-
- void addMember(Element element, DiagnosticListener listener) {
- throw new UnsupportedError("Cannot add member to $this.");
- }
-
- void addToScope(Element element, DiagnosticListener listener) {
- listener.internalError(this, 'Cannot add to scope of $this.');
- }
-
- void addConstructor(FunctionElement constructor) {
- constructors = constructors.prepend(constructor);
- }
-
- void setDefaultConstructor(FunctionElement constructor, Compiler compiler) {
- assert(!hasConstructor);
- addConstructor(constructor);
- }
-
- List<DartType> computeTypeParameters(Compiler compiler) {
- NamedMixinApplication named = node.asNamedMixinApplication();
- if (named == null) {
- throw new SpannableAssertionFailure(node,
- "Type variables on unnamed mixin applications must be set on "
- "creation.");
- }
- return createTypeVariables(named.typeParameters);
- }
-
- accept(ElementVisitor visitor) => visitor.visitMixinApplicationElement(this);
-}
-
-class LabelDefinitionX implements LabelDefinition {
- final Label label;
- final String labelName;
- final JumpTarget target;
- bool isBreakTarget = false;
- bool isContinueTarget = false;
-
- LabelDefinitionX(Label label, String labelName, this.target)
- : this.label = label,
- this.labelName = labelName;
-
- // In case of a synthetic label, just use [labelName] for identifying the
- // label.
- String get name => label == null ? labelName : label.identifier.source;
-
- void setBreakTarget() {
- isBreakTarget = true;
- target.isBreakTarget = true;
- }
-
- void setContinueTarget() {
- isContinueTarget = true;
- target.isContinueTarget = true;
- }
-
- bool get isTarget => isBreakTarget || isContinueTarget;
-
- String toString() => 'Label:${name}';
-}
-
-class JumpTargetX implements JumpTarget {
- final ExecutableElement executableContext;
- final Node statement;
- final int nestingLevel;
- Link<LabelDefinition> labels = const Link<LabelDefinition>();
- bool isBreakTarget = false;
- bool isContinueTarget = false;
-
- JumpTargetX(this.statement, this.nestingLevel, this.executableContext);
-
- String get name => "target";
-
- bool get isTarget => isBreakTarget || isContinueTarget;
-
- LabelDefinition addLabel(Label label, String labelName) {
- LabelDefinition result = new LabelDefinitionX(label, labelName, this);
- labels = labels.prepend(result);
- return result;
- }
-
- bool get isSwitch => statement is SwitchStatement;
-
- String toString() => 'Target:$statement';
-}
-
-class TypeVariableElementX extends ElementX with AstElementMixin
- implements TypeVariableElement {
- final Node node;
- TypeVariableType typeCache;
- DartType boundCache;
-
- TypeVariableElementX(String name, TypeDeclarationElement enclosing, this.node)
- : super(name, ElementKind.TYPE_VARIABLE, enclosing);
-
- TypeDeclarationElement get typeDeclaration => enclosingElement;
-
- TypeVariableType computeType(compiler) => type;
-
- TypeVariableType get type {
- assert(invariant(this, typeCache != null,
- message: "Type has not been set on $this."));
- return typeCache;
- }
-
- DartType get bound {
- assert(invariant(this, boundCache != null,
- message: "Bound has not been set on $this."));
- return boundCache;
- }
-
- bool get hasNode => true;
-
- Node parseNode(compiler) => node;
-
- String toString() => "${enclosingElement.toString()}.${name}";
-
- Token get position => node.getBeginToken();
-
- accept(ElementVisitor visitor) => visitor.visitTypeVariableElement(this);
-
- // A type variable cannot be patched therefore defines itself.
- AstElement get definingElement => this;
-}
-
-/**
- * A single metadata annotation.
- *
- * For example, consider:
- *
- * class Data {
- * const Data();
- * }
- *
- * const data = const Data();
- *
- * @data
- * class Foo {}
- *
- * @data @data
- * class Bar {}
- *
- * In this example, there are three instances of [MetadataAnnotation]
- * and they correspond each to a location in the source code where
- * there is an at-sign, '@'. The [constant] of each of these instances
- * are the same compile-time constant, [: const Data() :].
- *
- * The mirror system does not have a concept matching this class.
- */
-abstract class MetadataAnnotationX implements MetadataAnnotation {
- /**
- * The compile-time constant which this annotation resolves to.
- * In the mirror system, this would be an object mirror.
- */
- ConstantExpression constant;
- Element annotatedElement;
- int resolutionState;
-
- /**
- * The beginning token of this annotation, or [:null:] if it is synthetic.
- */
- Token get beginToken;
-
- MetadataAnnotationX([this.resolutionState = STATE_NOT_STARTED]);
-
- MetadataAnnotation ensureResolved(Compiler compiler) {
- if (annotatedElement.isClass || annotatedElement.isTypedef) {
- TypeDeclarationElement typeDeclaration = annotatedElement;
- typeDeclaration.ensureResolved(compiler);
- }
- if (resolutionState == STATE_NOT_STARTED) {
- compiler.resolver.resolveMetadataAnnotation(this);
- }
- return this;
- }
-
- Node parseNode(DiagnosticListener listener);
-
- String toString() => 'MetadataAnnotation($constant, $resolutionState)';
-}
-
-/// Metadata annotation on a parameter.
-class ParameterMetadataAnnotation extends MetadataAnnotationX {
- final Metadata metadata;
-
- ParameterMetadataAnnotation(Metadata this.metadata);
-
- Node parseNode(DiagnosticListener listener) => metadata.expression;
-
- Token get beginToken => metadata.getBeginToken();
-
- Token get endToken => metadata.getEndToken();
-
- bool get hasNode => true;
-
- Metadata get node => metadata;
-}
-
-/// Mixin for the implementation of patched elements.
-///
-/// See [:patch_parser.dart:] for a description of the terminology.
-abstract class PatchMixin<E extends Element> implements Element {
- // TODO(johnniwinther): Use type variables when issue 18630 is fixed.
- Element/*E*/ patch = null;
- Element/*E*/ origin = null;
-
- bool get isPatch => origin != null;
- bool get isPatched => patch != null;
-
- bool get isImplementation => !isPatched;
- bool get isDeclaration => !isPatch;
-
- Element/*E*/ get implementation => isPatched ? patch : this;
- Element/*E*/ get declaration => isPatch ? origin : this;
-
- /// Applies a patch to this element. This method must be called at most once.
- void applyPatch(PatchMixin<E> patch) {
- assert(invariant(this, this.patch == null,
- message: "Element is patched twice."));
- assert(invariant(this, this.origin == null,
- message: "Origin element is a patch."));
- assert(invariant(patch, patch.origin == null,
- message: "Element is patched twice."));
- assert(invariant(patch, patch.patch == null,
- message: "Patch element is patched."));
- this.patch = patch;
- patch.origin = this;
- }
-}
-
-/// Abstract implementation of the [AstElement] interface.
-abstract class AstElementMixin implements AstElement {
- /// The element whose node defines this element.
- ///
- /// For patched functions the defining element is the patch element found
- /// through [implementation] since its node define the implementation of the
- /// function. For patched classes the defining element is the origin element
- /// found through [declaration] since its node define the inheritance relation
- /// for the class. For unpatched elements the defining element is the element
- /// itself.
- AstElement get definingElement;
-
- bool get hasResolvedAst => definingElement.hasTreeElements;
-
- ResolvedAst get resolvedAst {
- return new ResolvedAst(declaration,
- definingElement.node, definingElement.treeElements);
- }
-
-}

Powered by Google App Engine
This is Rietveld 408576698