| Index: pkg/compiler/lib/src/elements/modelx.dart
|
| diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
|
| index 8cf86c932c769ff3dd880bc266c86bf4ae06379c..de3c11fc4fd925c2a20485751da47d9a9d57ed2f 100644
|
| --- a/pkg/compiler/lib/src/elements/modelx.dart
|
| +++ b/pkg/compiler/lib/src/elements/modelx.dart
|
| @@ -560,11 +560,10 @@ class AmbiguousImportX extends AmbiguousElementX {
|
| 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) {
|
| + for (ImportElement import in importer.importers.getImports(element)) {
|
| listener.reportInfo(
|
| - importers.head, MessageKind.IMPORTED_HERE, arguments);
|
| + import, MessageKind.IMPORTED_HERE, arguments);
|
| }
|
| });
|
| }
|
| @@ -762,22 +761,26 @@ class CompilationUnitElementX extends ElementX
|
| }
|
| }
|
|
|
| +/// Map from [Element] to the [ImportElement]s throught which it was imported.
|
| +///
|
| +/// This is used for error reporting and deferred loading.
|
| class Importers {
|
| - Map<Element, Link<Import>> importers = new Map<Element, Link<Import>>();
|
| + Map<Element, List<ImportElement>> importers =
|
| + new Map<Element, List<ImportElement>>();
|
|
|
| - Link<Import> getImports(Element element) {
|
| - Link<Import> imports = importers[element];
|
| - return imports != null ? imports : const Link<Import>();
|
| + /// Returns the the list of [ImportElement]s through which [element] was
|
| + /// imported.
|
| + List<ImportElement> getImports(Element element) {
|
| + List<ImportElement> imports = importers[element];
|
| + return imports != null ? imports : const <ImportElement>[];
|
| }
|
|
|
| - Import getImport(Element element) => getImports(element).head;
|
| -
|
| - void registerImport(Element element, Import import) {
|
| - if (import == null) return;
|
| + /// Returns the first [ImportElement] through which [element] was imported.
|
| + ImportElement getImport(Element element) => getImports(element).first;
|
|
|
| - importers[element] =
|
| - importers.putIfAbsent(element, () => const Link<Import>())
|
| - .prepend(import);
|
| + /// Register [element] as imported through [import];
|
| + void registerImport(Element element, ImportElement import) {
|
| + importers.putIfAbsent(element, () => <ImportElement>[]).add(import);
|
| }
|
| }
|
|
|
| @@ -800,7 +803,7 @@ class ImportScope {
|
| */
|
| void addImport(Element enclosingElement,
|
| Element element,
|
| - Import import,
|
| + ImportElement import,
|
| DiagnosticListener listener) {
|
| LibraryElementX library = enclosingElement.library;
|
| Importers importers = library.importers;
|
| @@ -815,7 +818,7 @@ class ImportScope {
|
| Element existing = importScope.putIfAbsent(name, () => element);
|
| importers.registerImport(element, import);
|
|
|
| - void registerWarnOnUseElement(Import import,
|
| + void registerWarnOnUseElement(ImportElement import,
|
| MessageKind messageKind,
|
| Element hidingElement,
|
| Element hiddenElement) {
|
| @@ -836,7 +839,7 @@ class ImportScope {
|
| }
|
|
|
| if (existing != element) {
|
| - Import existingImport = importers.getImport(existing);
|
| + ImportElement existingImport = importers.getImport(existing);
|
| if (existing.library.isPlatformLibrary &&
|
| !element.library.isPlatformLibrary) {
|
| // [existing] is implicitly hidden.
|
| @@ -845,7 +848,7 @@ class ImportScope {
|
| } else if (!existing.library.isPlatformLibrary &&
|
| element.library.isPlatformLibrary) {
|
| // [element] is implicitly hidden.
|
| - if (import == null) {
|
| + if (import.isSynthesized) {
|
| // [element] is imported implicitly (probably through dart:core).
|
| registerWarnOnUseElement(
|
| existingImport, MessageKind.HIDDEN_IMPLICIT_IMPORT,
|
| @@ -866,6 +869,94 @@ class ImportScope {
|
| }
|
|
|
| Element operator [](String name) => importScope[name];
|
| +
|
| + void forEach(f(Element element)) => importScope.values.forEach(f);
|
| +}
|
| +
|
| +abstract class LibraryDependencyElementX extends ElementX {
|
| + final LibraryDependency node;
|
| + final Uri uri;
|
| + LibraryElement libraryDependency;
|
| +
|
| + LibraryDependencyElementX(CompilationUnitElement enclosingElement,
|
| + ElementKind kind,
|
| + this.node,
|
| + this.uri)
|
| + : super('', kind, enclosingElement);
|
| +
|
| + @override
|
| + List<MetadataAnnotation> get metadata => node.metadata;
|
| +
|
| + void set metadata(value) {
|
| + // The metadata is stored on [libraryDependency].
|
| + throw new SpannableAssertionFailure(
|
| + this, 'Cannot set metadata on a import/export.');
|
| + }
|
| +
|
| + @override
|
| + Token get position => node.getBeginToken();
|
| +
|
| + SourceSpan get sourcePosition {
|
| + return new SourceSpan.fromNode(compilationUnit.script.resourceUri, node);
|
| + }
|
| +
|
| + String toString() => '$kind($uri)';
|
| +}
|
| +
|
| +class ImportElementX extends LibraryDependencyElementX
|
| + implements ImportElement {
|
| + PrefixElementX prefix;
|
| +
|
| + ImportElementX(CompilationUnitElement enclosingElement, Import node, Uri uri)
|
| + : super(enclosingElement, ElementKind.IMPORT, node, uri);
|
| +
|
| + @override
|
| + Import get node => super.node;
|
| +
|
| + @override
|
| + LibraryElement get importedLibrary => libraryDependency;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor, arg) => visitor.visitImportElement(this, arg);
|
| +
|
| + @override
|
| + bool get isDeferred => node.isDeferred;
|
| +}
|
| +
|
| +class SyntheticImportElement extends ImportElementX {
|
| + SyntheticImportElement(CompilationUnitElement enclosingElement, Uri uri)
|
| + : super(enclosingElement, null, uri);
|
| +
|
| + @override
|
| + Token get position => library.position;
|
| +
|
| + @override
|
| + bool get isSynthesized => true;
|
| +
|
| + @override
|
| + bool get isDeferred => false;
|
| +
|
| + @override
|
| + List<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
|
| +
|
| + @override
|
| + SourceSpan get sourcePosition => library.sourcePosition;
|
| +}
|
| +
|
| +
|
| +class ExportElementX extends LibraryDependencyElementX
|
| + implements ExportElement {
|
| +
|
| + ExportElementX(CompilationUnitElement enclosingElement, Export node, Uri uri)
|
| + : super(enclosingElement, ElementKind.EXPORT, node, uri);
|
| +
|
| + Export get node => super.node;
|
| +
|
| + @override
|
| + LibraryElement get exportedLibrary => libraryDependency;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor, arg) => visitor.visitExportElement(this, arg);
|
| }
|
|
|
| class LibraryElementX
|
| @@ -903,6 +994,9 @@ class LibraryElementX
|
| */
|
| Link<Element> slotForExports;
|
|
|
| + List<ImportElement> _imports = <ImportElement>[];
|
| + List<ExportElement> _exports = <ExportElement>[];
|
| +
|
| final Map<LibraryDependency, LibraryElement> tagMapping =
|
| new Map<LibraryDependency, LibraryElement>();
|
|
|
| @@ -954,13 +1048,17 @@ class LibraryElementX
|
| return tagsCache;
|
| }
|
|
|
| - /// Record which element an import or export tag resolved to.
|
| - void recordResolvedTag(LibraryDependency tag, LibraryElement library) {
|
| - assert(tagMapping[tag] == null);
|
| - tagMapping[tag] = library;
|
| + void addImportDeclaration(ImportElement import) {
|
| + _imports.add(import);
|
| + }
|
| +
|
| + Iterable<ImportElement> get imports => _imports;
|
| +
|
| + void addExportDeclaration(ExportElement export) {
|
| + _exports.add(export);
|
| }
|
|
|
| - LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag];
|
| + Iterable<ExportElement> get exports => _exports;
|
|
|
| /**
|
| * Adds [element] to the import scope of this library.
|
| @@ -969,7 +1067,9 @@ class LibraryElementX
|
| * [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) {
|
| + void addImport(Element element,
|
| + ImportElement import,
|
| + DiagnosticListener listener) {
|
| importScope.addImport(this, element, import, listener);
|
| }
|
|
|
| @@ -996,12 +1096,6 @@ class LibraryElementX
|
| */
|
| 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.
|
| */
|
| @@ -1053,7 +1147,9 @@ class LibraryElementX
|
| }
|
|
|
| Element findExported(String elementName) {
|
| - for (Link link = exports; !link.isEmpty; link = link.tail) {
|
| + assert(invariant(this, exportsHandled,
|
| + message: 'Exports not handled on $this'));
|
| + for (Link link = slotForExports; !link.isEmpty; link = link.tail) {
|
| Element element = link.head;
|
| if (element.name == elementName) return element;
|
| }
|
| @@ -1061,16 +1157,17 @@ class LibraryElementX
|
| }
|
|
|
| void forEachExport(f(Element element)) {
|
| - exports.forEach((Element e) => f(e));
|
| + assert(invariant(this, exportsHandled,
|
| + message: 'Exports not handled on $this'));
|
| + slotForExports.forEach((Element e) => f(e));
|
| }
|
|
|
| - Link<Import> getImportsFor(Element element) => importers.getImports(element);
|
| -
|
| - @override
|
| - void forEachImport(f(Element element)) {
|
| - importScope.importScope.values.forEach(f);
|
| + Iterable<ImportElement> getImportsFor(Element element) {
|
| + return importers.getImports(element);
|
| }
|
|
|
| + void forEachImport(f(Element element)) => importScope.forEach(f);
|
| +
|
| void forEachLocalMember(f(Element element)) {
|
| if (isPatch) {
|
| // Patch libraries traverse both origin and injected members.
|
| @@ -1096,17 +1193,23 @@ class LibraryElementX
|
| });
|
| }
|
|
|
| - bool hasLibraryName() => libraryTag != null;
|
| + bool get 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() {
|
| + String get libraryName {
|
| if (libraryTag == null) return '';
|
| return libraryTag.name.toString();
|
| }
|
|
|
| + String get libraryOrScriptName {
|
| + 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);
|
|
|
| String toString() {
|
| @@ -1133,13 +1236,15 @@ class PrefixElementX extends ElementX implements PrefixElement {
|
|
|
| final ImportScope importScope = new ImportScope();
|
|
|
| - bool get isDeferred => _deferredImport != null;
|
| + bool get isDeferred => deferredImport != null;
|
|
|
| // Only needed for deferred imports.
|
| - Import _deferredImport;
|
| - Import get deferredImport => _deferredImport;
|
| + final ImportElement deferredImport;
|
|
|
| - PrefixElementX(String prefix, Element enclosing, this.firstPosition)
|
| + PrefixElementX(String prefix,
|
| + Element enclosing,
|
| + this.firstPosition,
|
| + this.deferredImport)
|
| : super(prefix, ElementKind.PREFIX, enclosing);
|
|
|
| bool get isTopLevel => false;
|
| @@ -1150,7 +1255,9 @@ class PrefixElementX extends ElementX implements PrefixElement {
|
|
|
| Token get position => firstPosition;
|
|
|
| - void addImport(Element element, Import import, DiagnosticListener listener) {
|
| + void addImport(Element element,
|
| + ImportElement import,
|
| + DiagnosticListener listener) {
|
| importScope.addImport(this, element, import, listener);
|
| }
|
|
|
| @@ -1158,10 +1265,6 @@ class PrefixElementX extends ElementX implements PrefixElement {
|
| return visitor.visitPrefixElement(this, arg);
|
| }
|
|
|
| - void markAsDeferred(Import deferredImport) {
|
| - _deferredImport = deferredImport;
|
| - }
|
| -
|
| String toString() => '$kind($name)';
|
| }
|
|
|
|
|