Chromium Code Reviews| 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..63e89f4cd70012522ddf052a4ae8170675dc59db 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); |
| } |
| }); |
| } |
| @@ -763,21 +762,20 @@ class CompilationUnitElementX extends ElementX |
| } |
| class Importers { |
|
karlklose
2015/09/15 06:35:55
Could you think of a more descriptive name for thi
Johnni Winther
2015/09/15 07:50:06
Done.
|
| - 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>(); |
| + List<ImportElement> getImports(Element element) { |
| + List<ImportElement> imports = importers[element]; |
| + return imports != null ? imports : const <ImportElement>[]; |
| } |
| - Import getImport(Element element) => getImports(element).head; |
| + ImportElement getImport(Element element) => getImports(element).first; |
| - void registerImport(Element element, Import import) { |
| + void registerImport(Element element, ImportElement import) { |
| if (import == null) return; |
| - importers[element] = |
| - importers.putIfAbsent(element, () => const Link<Import>()) |
| - .prepend(import); |
| + importers.putIfAbsent(element, () => <ImportElement>[]).add(import); |
| } |
| } |
| @@ -800,7 +798,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 +813,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 +834,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 +843,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 +864,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 +989,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 +1043,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 +1062,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 +1091,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 +1142,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 +1152,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 +1188,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 +1231,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 +1250,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 +1260,6 @@ class PrefixElementX extends ElementX implements PrefixElement { |
| return visitor.visitPrefixElement(this, arg); |
| } |
| - void markAsDeferred(Import deferredImport) { |
| - _deferredImport = deferredImport; |
| - } |
| - |
| String toString() => '$kind($name)'; |
| } |