| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library elements.modelx; | 5 library elements.modelx; |
| 6 | 6 |
| 7 import '../compiler.dart' show | 7 import '../compiler.dart' show |
| 8 Compiler; | 8 Compiler; |
| 9 import '../constants/constant_constructors.dart'; | 9 import '../constants/constant_constructors.dart'; |
| 10 import '../constants/constructors.dart'; | 10 import '../constants/constructors.dart'; |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 newElement); | 553 newElement); |
| 554 | 554 |
| 555 void diagnose(Element context, DiagnosticListener listener) { | 555 void diagnose(Element context, DiagnosticListener listener) { |
| 556 Setlet ambiguousElements = flatten(); | 556 Setlet ambiguousElements = flatten(); |
| 557 MessageKind code = (ambiguousElements.length == 1) | 557 MessageKind code = (ambiguousElements.length == 1) |
| 558 ? MessageKind.AMBIGUOUS_REEXPORT : MessageKind.AMBIGUOUS_LOCATION; | 558 ? MessageKind.AMBIGUOUS_REEXPORT : MessageKind.AMBIGUOUS_LOCATION; |
| 559 LibraryElementX importer = context.library; | 559 LibraryElementX importer = context.library; |
| 560 for (Element element in ambiguousElements) { | 560 for (Element element in ambiguousElements) { |
| 561 var arguments = {'name': element.name}; | 561 var arguments = {'name': element.name}; |
| 562 listener.reportInfo(element, code, arguments); | 562 listener.reportInfo(element, code, arguments); |
| 563 Link<Import> importers = importer.importers.getImports(element); | |
| 564 listener.withCurrentElement(importer, () { | 563 listener.withCurrentElement(importer, () { |
| 565 for (; !importers.isEmpty; importers = importers.tail) { | 564 for (ImportElement import in importer.importers.getImports(element)) { |
| 566 listener.reportInfo( | 565 listener.reportInfo( |
| 567 importers.head, MessageKind.IMPORTED_HERE, arguments); | 566 import, MessageKind.IMPORTED_HERE, arguments); |
| 568 } | 567 } |
| 569 }); | 568 }); |
| 570 } | 569 } |
| 571 } | 570 } |
| 572 } | 571 } |
| 573 | 572 |
| 574 /// Element synthesized to recover from a duplicated member of an element. | 573 /// Element synthesized to recover from a duplicated member of an element. |
| 575 class DuplicatedElementX extends AmbiguousElementX { | 574 class DuplicatedElementX extends AmbiguousElementX { |
| 576 DuplicatedElementX( | 575 DuplicatedElementX( |
| 577 MessageKind messageKind, | 576 MessageKind messageKind, |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 | 754 |
| 756 bool get hasMembers => !localMembers.isEmpty; | 755 bool get hasMembers => !localMembers.isEmpty; |
| 757 | 756 |
| 758 Element get analyzableElement => library; | 757 Element get analyzableElement => library; |
| 759 | 758 |
| 760 accept(ElementVisitor visitor, arg) { | 759 accept(ElementVisitor visitor, arg) { |
| 761 return visitor.visitCompilationUnitElement(this, arg); | 760 return visitor.visitCompilationUnitElement(this, arg); |
| 762 } | 761 } |
| 763 } | 762 } |
| 764 | 763 |
| 764 /// Map from [Element] to the [ImportElement]s throught which it was imported. |
| 765 /// |
| 766 /// This is used for error reporting and deferred loading. |
| 765 class Importers { | 767 class Importers { |
| 766 Map<Element, Link<Import>> importers = new Map<Element, Link<Import>>(); | 768 Map<Element, List<ImportElement>> importers = |
| 769 new Map<Element, List<ImportElement>>(); |
| 767 | 770 |
| 768 Link<Import> getImports(Element element) { | 771 /// Returns the the list of [ImportElement]s through which [element] was |
| 769 Link<Import> imports = importers[element]; | 772 /// imported. |
| 770 return imports != null ? imports : const Link<Import>(); | 773 List<ImportElement> getImports(Element element) { |
| 774 List<ImportElement> imports = importers[element]; |
| 775 return imports != null ? imports : const <ImportElement>[]; |
| 771 } | 776 } |
| 772 | 777 |
| 773 Import getImport(Element element) => getImports(element).head; | 778 /// Returns the first [ImportElement] through which [element] was imported. |
| 779 ImportElement getImport(Element element) => getImports(element).first; |
| 774 | 780 |
| 775 void registerImport(Element element, Import import) { | 781 /// Register [element] as imported through [import]; |
| 776 if (import == null) return; | 782 void registerImport(Element element, ImportElement import) { |
| 777 | 783 importers.putIfAbsent(element, () => <ImportElement>[]).add(import); |
| 778 importers[element] = | |
| 779 importers.putIfAbsent(element, () => const Link<Import>()) | |
| 780 .prepend(import); | |
| 781 } | 784 } |
| 782 } | 785 } |
| 783 | 786 |
| 784 class ImportScope { | 787 class ImportScope { |
| 785 /** | 788 /** |
| 786 * Map for elements imported through import declarations. | 789 * Map for elements imported through import declarations. |
| 787 * | 790 * |
| 788 * Addition to the map is performed by [addImport]. Lookup is done trough | 791 * Addition to the map is performed by [addImport]. Lookup is done trough |
| 789 * [find]. | 792 * [find]. |
| 790 */ | 793 */ |
| 791 final Map<String, Element> importScope = | 794 final Map<String, Element> importScope = |
| 792 new Map<String, Element>(); | 795 new Map<String, Element>(); |
| 793 | 796 |
| 794 /** | 797 /** |
| 795 * Adds [element] to the import scope of this library. | 798 * Adds [element] to the import scope of this library. |
| 796 * | 799 * |
| 797 * If an element by the same name is already in the imported scope, an | 800 * If an element by the same name is already in the imported scope, an |
| 798 * [ErroneousElement] will be put in the imported scope, allowing for | 801 * [ErroneousElement] will be put in the imported scope, allowing for |
| 799 * detection of ambiguous uses of imported names. | 802 * detection of ambiguous uses of imported names. |
| 800 */ | 803 */ |
| 801 void addImport(Element enclosingElement, | 804 void addImport(Element enclosingElement, |
| 802 Element element, | 805 Element element, |
| 803 Import import, | 806 ImportElement import, |
| 804 DiagnosticListener listener) { | 807 DiagnosticListener listener) { |
| 805 LibraryElementX library = enclosingElement.library; | 808 LibraryElementX library = enclosingElement.library; |
| 806 Importers importers = library.importers; | 809 Importers importers = library.importers; |
| 807 | 810 |
| 808 String name = element.name; | 811 String name = element.name; |
| 809 | 812 |
| 810 // The loadLibrary function always shadows existing bindings to that name. | 813 // The loadLibrary function always shadows existing bindings to that name. |
| 811 if (element.isDeferredLoaderGetter) { | 814 if (element.isDeferredLoaderGetter) { |
| 812 importScope.remove(name); | 815 importScope.remove(name); |
| 813 // TODO(sigurdm): Print a hint. | 816 // TODO(sigurdm): Print a hint. |
| 814 } | 817 } |
| 815 Element existing = importScope.putIfAbsent(name, () => element); | 818 Element existing = importScope.putIfAbsent(name, () => element); |
| 816 importers.registerImport(element, import); | 819 importers.registerImport(element, import); |
| 817 | 820 |
| 818 void registerWarnOnUseElement(Import import, | 821 void registerWarnOnUseElement(ImportElement import, |
| 819 MessageKind messageKind, | 822 MessageKind messageKind, |
| 820 Element hidingElement, | 823 Element hidingElement, |
| 821 Element hiddenElement) { | 824 Element hiddenElement) { |
| 822 Uri hiddenUri = hiddenElement.library.canonicalUri; | 825 Uri hiddenUri = hiddenElement.library.canonicalUri; |
| 823 Uri hidingUri = hidingElement.library.canonicalUri; | 826 Uri hidingUri = hidingElement.library.canonicalUri; |
| 824 Element element = new WarnOnUseElementX( | 827 Element element = new WarnOnUseElementX( |
| 825 new WrappedMessage( | 828 new WrappedMessage( |
| 826 null, // Report on reference to [hidingElement]. | 829 null, // Report on reference to [hidingElement]. |
| 827 messageKind, | 830 messageKind, |
| 828 {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}), | 831 {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}), |
| 829 new WrappedMessage( | 832 new WrappedMessage( |
| 830 listener.spanFromSpannable(import), | 833 listener.spanFromSpannable(import), |
| 831 MessageKind.IMPORTED_HERE, | 834 MessageKind.IMPORTED_HERE, |
| 832 {'name': name}), | 835 {'name': name}), |
| 833 enclosingElement, hidingElement); | 836 enclosingElement, hidingElement); |
| 834 importScope[name] = element; | 837 importScope[name] = element; |
| 835 importers.registerImport(element, import); | 838 importers.registerImport(element, import); |
| 836 } | 839 } |
| 837 | 840 |
| 838 if (existing != element) { | 841 if (existing != element) { |
| 839 Import existingImport = importers.getImport(existing); | 842 ImportElement existingImport = importers.getImport(existing); |
| 840 if (existing.library.isPlatformLibrary && | 843 if (existing.library.isPlatformLibrary && |
| 841 !element.library.isPlatformLibrary) { | 844 !element.library.isPlatformLibrary) { |
| 842 // [existing] is implicitly hidden. | 845 // [existing] is implicitly hidden. |
| 843 registerWarnOnUseElement( | 846 registerWarnOnUseElement( |
| 844 import, MessageKind.HIDDEN_IMPORT, element, existing); | 847 import, MessageKind.HIDDEN_IMPORT, element, existing); |
| 845 } else if (!existing.library.isPlatformLibrary && | 848 } else if (!existing.library.isPlatformLibrary && |
| 846 element.library.isPlatformLibrary) { | 849 element.library.isPlatformLibrary) { |
| 847 // [element] is implicitly hidden. | 850 // [element] is implicitly hidden. |
| 848 if (import == null) { | 851 if (import.isSynthesized) { |
| 849 // [element] is imported implicitly (probably through dart:core). | 852 // [element] is imported implicitly (probably through dart:core). |
| 850 registerWarnOnUseElement( | 853 registerWarnOnUseElement( |
| 851 existingImport, MessageKind.HIDDEN_IMPLICIT_IMPORT, | 854 existingImport, MessageKind.HIDDEN_IMPLICIT_IMPORT, |
| 852 existing, element); | 855 existing, element); |
| 853 } else { | 856 } else { |
| 854 registerWarnOnUseElement( | 857 registerWarnOnUseElement( |
| 855 import, MessageKind.HIDDEN_IMPORT, existing, element); | 858 import, MessageKind.HIDDEN_IMPORT, existing, element); |
| 856 } | 859 } |
| 857 } else { | 860 } else { |
| 858 Element ambiguousElement = new AmbiguousImportX( | 861 Element ambiguousElement = new AmbiguousImportX( |
| 859 MessageKind.DUPLICATE_IMPORT, {'name': name}, | 862 MessageKind.DUPLICATE_IMPORT, {'name': name}, |
| 860 enclosingElement, existing, element); | 863 enclosingElement, existing, element); |
| 861 importScope[name] = ambiguousElement; | 864 importScope[name] = ambiguousElement; |
| 862 importers.registerImport(ambiguousElement, import); | 865 importers.registerImport(ambiguousElement, import); |
| 863 importers.registerImport(ambiguousElement, existingImport); | 866 importers.registerImport(ambiguousElement, existingImport); |
| 864 } | 867 } |
| 865 } | 868 } |
| 866 } | 869 } |
| 867 | 870 |
| 868 Element operator [](String name) => importScope[name]; | 871 Element operator [](String name) => importScope[name]; |
| 872 |
| 873 void forEach(f(Element element)) => importScope.values.forEach(f); |
| 874 } |
| 875 |
| 876 abstract class LibraryDependencyElementX extends ElementX { |
| 877 final LibraryDependency node; |
| 878 final Uri uri; |
| 879 LibraryElement libraryDependency; |
| 880 |
| 881 LibraryDependencyElementX(CompilationUnitElement enclosingElement, |
| 882 ElementKind kind, |
| 883 this.node, |
| 884 this.uri) |
| 885 : super('', kind, enclosingElement); |
| 886 |
| 887 @override |
| 888 List<MetadataAnnotation> get metadata => node.metadata; |
| 889 |
| 890 void set metadata(value) { |
| 891 // The metadata is stored on [libraryDependency]. |
| 892 throw new SpannableAssertionFailure( |
| 893 this, 'Cannot set metadata on a import/export.'); |
| 894 } |
| 895 |
| 896 @override |
| 897 Token get position => node.getBeginToken(); |
| 898 |
| 899 SourceSpan get sourcePosition { |
| 900 return new SourceSpan.fromNode(compilationUnit.script.resourceUri, node); |
| 901 } |
| 902 |
| 903 String toString() => '$kind($uri)'; |
| 904 } |
| 905 |
| 906 class ImportElementX extends LibraryDependencyElementX |
| 907 implements ImportElement { |
| 908 PrefixElementX prefix; |
| 909 |
| 910 ImportElementX(CompilationUnitElement enclosingElement, Import node, Uri uri) |
| 911 : super(enclosingElement, ElementKind.IMPORT, node, uri); |
| 912 |
| 913 @override |
| 914 Import get node => super.node; |
| 915 |
| 916 @override |
| 917 LibraryElement get importedLibrary => libraryDependency; |
| 918 |
| 919 @override |
| 920 accept(ElementVisitor visitor, arg) => visitor.visitImportElement(this, arg); |
| 921 |
| 922 @override |
| 923 bool get isDeferred => node.isDeferred; |
| 924 } |
| 925 |
| 926 class SyntheticImportElement extends ImportElementX { |
| 927 SyntheticImportElement(CompilationUnitElement enclosingElement, Uri uri) |
| 928 : super(enclosingElement, null, uri); |
| 929 |
| 930 @override |
| 931 Token get position => library.position; |
| 932 |
| 933 @override |
| 934 bool get isSynthesized => true; |
| 935 |
| 936 @override |
| 937 bool get isDeferred => false; |
| 938 |
| 939 @override |
| 940 List<MetadataAnnotation> get metadata => const <MetadataAnnotation>[]; |
| 941 |
| 942 @override |
| 943 SourceSpan get sourcePosition => library.sourcePosition; |
| 944 } |
| 945 |
| 946 |
| 947 class ExportElementX extends LibraryDependencyElementX |
| 948 implements ExportElement { |
| 949 |
| 950 ExportElementX(CompilationUnitElement enclosingElement, Export node, Uri uri) |
| 951 : super(enclosingElement, ElementKind.EXPORT, node, uri); |
| 952 |
| 953 Export get node => super.node; |
| 954 |
| 955 @override |
| 956 LibraryElement get exportedLibrary => libraryDependency; |
| 957 |
| 958 @override |
| 959 accept(ElementVisitor visitor, arg) => visitor.visitExportElement(this, arg); |
| 869 } | 960 } |
| 870 | 961 |
| 871 class LibraryElementX | 962 class LibraryElementX |
| 872 extends ElementX | 963 extends ElementX |
| 873 with LibraryElementCommon, | 964 with LibraryElementCommon, |
| 874 AnalyzableElementX, | 965 AnalyzableElementX, |
| 875 PatchMixin<LibraryElementX> | 966 PatchMixin<LibraryElementX> |
| 876 implements LibraryElement { | 967 implements LibraryElement { |
| 877 final Uri canonicalUri; | 968 final Uri canonicalUri; |
| 878 | 969 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 896 /** | 987 /** |
| 897 * Link for elements exported either through export declarations or through | 988 * Link for elements exported either through export declarations or through |
| 898 * declaration. This field should not be accessed directly but instead through | 989 * declaration. This field should not be accessed directly but instead through |
| 899 * the [exports] getter. | 990 * the [exports] getter. |
| 900 * | 991 * |
| 901 * [LibraryDependencyHandler] sets this field through [setExports] when the | 992 * [LibraryDependencyHandler] sets this field through [setExports] when the |
| 902 * library is loaded. | 993 * library is loaded. |
| 903 */ | 994 */ |
| 904 Link<Element> slotForExports; | 995 Link<Element> slotForExports; |
| 905 | 996 |
| 997 List<ImportElement> _imports = <ImportElement>[]; |
| 998 List<ExportElement> _exports = <ExportElement>[]; |
| 999 |
| 906 final Map<LibraryDependency, LibraryElement> tagMapping = | 1000 final Map<LibraryDependency, LibraryElement> tagMapping = |
| 907 new Map<LibraryDependency, LibraryElement>(); | 1001 new Map<LibraryDependency, LibraryElement>(); |
| 908 | 1002 |
| 909 LibraryElementX(Script script, | 1003 LibraryElementX(Script script, |
| 910 [Uri canonicalUri, LibraryElementX origin]) | 1004 [Uri canonicalUri, LibraryElementX origin]) |
| 911 : this.canonicalUri = | 1005 : this.canonicalUri = |
| 912 ((canonicalUri == null) ? script.readableUri : canonicalUri), | 1006 ((canonicalUri == null) ? script.readableUri : canonicalUri), |
| 913 this.isSynthesized = script.isSynthesized, | 1007 this.isSynthesized = script.isSynthesized, |
| 914 super(script.name, ElementKind.LIBRARY, null) { | 1008 super(script.name, ElementKind.LIBRARY, null) { |
| 915 entryCompilationUnit = new CompilationUnitElementX(script, this); | 1009 entryCompilationUnit = new CompilationUnitElementX(script, this); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 } | 1041 } |
| 948 | 1042 |
| 949 Iterable<LibraryTag> get tags { | 1043 Iterable<LibraryTag> get tags { |
| 950 if (tagsCache == null) { | 1044 if (tagsCache == null) { |
| 951 tagsCache = tagsBuilder.toList(); | 1045 tagsCache = tagsBuilder.toList(); |
| 952 tagsBuilder = null; | 1046 tagsBuilder = null; |
| 953 } | 1047 } |
| 954 return tagsCache; | 1048 return tagsCache; |
| 955 } | 1049 } |
| 956 | 1050 |
| 957 /// Record which element an import or export tag resolved to. | 1051 void addImportDeclaration(ImportElement import) { |
| 958 void recordResolvedTag(LibraryDependency tag, LibraryElement library) { | 1052 _imports.add(import); |
| 959 assert(tagMapping[tag] == null); | |
| 960 tagMapping[tag] = library; | |
| 961 } | 1053 } |
| 962 | 1054 |
| 963 LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag]; | 1055 Iterable<ImportElement> get imports => _imports; |
| 1056 |
| 1057 void addExportDeclaration(ExportElement export) { |
| 1058 _exports.add(export); |
| 1059 } |
| 1060 |
| 1061 Iterable<ExportElement> get exports => _exports; |
| 964 | 1062 |
| 965 /** | 1063 /** |
| 966 * Adds [element] to the import scope of this library. | 1064 * Adds [element] to the import scope of this library. |
| 967 * | 1065 * |
| 968 * If an element by the same name is already in the imported scope, an | 1066 * If an element by the same name is already in the imported scope, an |
| 969 * [ErroneousElement] will be put in the imported scope, allowing for | 1067 * [ErroneousElement] will be put in the imported scope, allowing for |
| 970 * detection of ambiguous uses of imported names. | 1068 * detection of ambiguous uses of imported names. |
| 971 */ | 1069 */ |
| 972 void addImport(Element element, Import import, DiagnosticListener listener) { | 1070 void addImport(Element element, |
| 1071 ImportElement import, |
| 1072 DiagnosticListener listener) { |
| 973 importScope.addImport(this, element, import, listener); | 1073 importScope.addImport(this, element, import, listener); |
| 974 } | 1074 } |
| 975 | 1075 |
| 976 void addMember(Element element, DiagnosticListener listener) { | 1076 void addMember(Element element, DiagnosticListener listener) { |
| 977 localMembers = localMembers.prepend(element); | 1077 localMembers = localMembers.prepend(element); |
| 978 addToScope(element, listener); | 1078 addToScope(element, listener); |
| 979 } | 1079 } |
| 980 | 1080 |
| 981 void addToScope(Element element, DiagnosticListener listener) { | 1081 void addToScope(Element element, DiagnosticListener listener) { |
| 982 localScope.add(element, listener); | 1082 localScope.add(element, listener); |
| 983 } | 1083 } |
| 984 | 1084 |
| 985 Element localLookup(String elementName) { | 1085 Element localLookup(String elementName) { |
| 986 Element result = localScope.lookup(elementName); | 1086 Element result = localScope.lookup(elementName); |
| 987 if (result == null && isPatch) { | 1087 if (result == null && isPatch) { |
| 988 result = origin.localLookup(elementName); | 1088 result = origin.localLookup(elementName); |
| 989 } | 1089 } |
| 990 return result; | 1090 return result; |
| 991 } | 1091 } |
| 992 | 1092 |
| 993 /** | 1093 /** |
| 994 * Returns [:true:] if the export scope has already been computed for this | 1094 * Returns [:true:] if the export scope has already been computed for this |
| 995 * library. | 1095 * library. |
| 996 */ | 1096 */ |
| 997 bool get exportsHandled => slotForExports != null; | 1097 bool get exportsHandled => slotForExports != null; |
| 998 | 1098 |
| 999 Link<Element> get exports { | |
| 1000 assert(invariant(this, exportsHandled, | |
| 1001 message: 'Exports not handled on $this')); | |
| 1002 return slotForExports; | |
| 1003 } | |
| 1004 | |
| 1005 /** | 1099 /** |
| 1006 * Sets the export scope of this library. This method can only be called once. | 1100 * Sets the export scope of this library. This method can only be called once. |
| 1007 */ | 1101 */ |
| 1008 void setExports(Iterable<Element> exportedElements) { | 1102 void setExports(Iterable<Element> exportedElements) { |
| 1009 assert(invariant(this, !exportsHandled, | 1103 assert(invariant(this, !exportsHandled, |
| 1010 message: 'Exports already set to $slotForExports on $this')); | 1104 message: 'Exports already set to $slotForExports on $this')); |
| 1011 assert(invariant(this, exportedElements != null)); | 1105 assert(invariant(this, exportedElements != null)); |
| 1012 var builder = new LinkBuilder<Element>(); | 1106 var builder = new LinkBuilder<Element>(); |
| 1013 for (Element export in exportedElements) { | 1107 for (Element export in exportedElements) { |
| 1014 builder.addLast(export); | 1108 builder.addLast(export); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 // TODO((johnniwinther): How to handle injected elements in the patch | 1140 // TODO((johnniwinther): How to handle injected elements in the patch |
| 1047 // library? | 1141 // library? |
| 1048 Element result = localScope.lookup(elementName); | 1142 Element result = localScope.lookup(elementName); |
| 1049 if (result == null && isPatch) { | 1143 if (result == null && isPatch) { |
| 1050 return origin.findLocal(elementName); | 1144 return origin.findLocal(elementName); |
| 1051 } | 1145 } |
| 1052 return result; | 1146 return result; |
| 1053 } | 1147 } |
| 1054 | 1148 |
| 1055 Element findExported(String elementName) { | 1149 Element findExported(String elementName) { |
| 1056 for (Link link = exports; !link.isEmpty; link = link.tail) { | 1150 assert(invariant(this, exportsHandled, |
| 1151 message: 'Exports not handled on $this')); |
| 1152 for (Link link = slotForExports; !link.isEmpty; link = link.tail) { |
| 1057 Element element = link.head; | 1153 Element element = link.head; |
| 1058 if (element.name == elementName) return element; | 1154 if (element.name == elementName) return element; |
| 1059 } | 1155 } |
| 1060 return null; | 1156 return null; |
| 1061 } | 1157 } |
| 1062 | 1158 |
| 1063 void forEachExport(f(Element element)) { | 1159 void forEachExport(f(Element element)) { |
| 1064 exports.forEach((Element e) => f(e)); | 1160 assert(invariant(this, exportsHandled, |
| 1161 message: 'Exports not handled on $this')); |
| 1162 slotForExports.forEach((Element e) => f(e)); |
| 1065 } | 1163 } |
| 1066 | 1164 |
| 1067 Link<Import> getImportsFor(Element element) => importers.getImports(element); | 1165 Iterable<ImportElement> getImportsFor(Element element) { |
| 1166 return importers.getImports(element); |
| 1167 } |
| 1068 | 1168 |
| 1069 @override | 1169 void forEachImport(f(Element element)) => importScope.forEach(f); |
| 1070 void forEachImport(f(Element element)) { | |
| 1071 importScope.importScope.values.forEach(f); | |
| 1072 } | |
| 1073 | 1170 |
| 1074 void forEachLocalMember(f(Element element)) { | 1171 void forEachLocalMember(f(Element element)) { |
| 1075 if (isPatch) { | 1172 if (isPatch) { |
| 1076 // Patch libraries traverse both origin and injected members. | 1173 // Patch libraries traverse both origin and injected members. |
| 1077 origin.localMembers.forEach(f); | 1174 origin.localMembers.forEach(f); |
| 1078 | 1175 |
| 1079 void filterPatch(Element element) { | 1176 void filterPatch(Element element) { |
| 1080 if (!element.isPatch) { | 1177 if (!element.isPatch) { |
| 1081 // Do not traverse the patch members. | 1178 // Do not traverse the patch members. |
| 1082 f(element); | 1179 f(element); |
| 1083 } | 1180 } |
| 1084 } | 1181 } |
| 1085 localMembers.forEach(filterPatch); | 1182 localMembers.forEach(filterPatch); |
| 1086 } else { | 1183 } else { |
| 1087 localMembers.forEach(f); | 1184 localMembers.forEach(f); |
| 1088 } | 1185 } |
| 1089 } | 1186 } |
| 1090 | 1187 |
| 1091 Iterable<Element> getNonPrivateElementsInScope() { | 1188 Iterable<Element> getNonPrivateElementsInScope() { |
| 1092 return localScope.values.where((Element element) { | 1189 return localScope.values.where((Element element) { |
| 1093 // At this point [localScope] only contains members so we don't need | 1190 // At this point [localScope] only contains members so we don't need |
| 1094 // to check for foreign or prefix elements. | 1191 // to check for foreign or prefix elements. |
| 1095 return !Name.isPrivateName(element.name); | 1192 return !Name.isPrivateName(element.name); |
| 1096 }); | 1193 }); |
| 1097 } | 1194 } |
| 1098 | 1195 |
| 1099 bool hasLibraryName() => libraryTag != null; | 1196 bool get hasLibraryName => libraryTag != null; |
| 1100 | 1197 |
| 1101 /** | 1198 String get libraryName { |
| 1102 * Returns the library name, which is either the name given in the library tag | |
| 1103 * or the empty string if there is no library tag. | |
| 1104 */ | |
| 1105 String getLibraryName() { | |
| 1106 if (libraryTag == null) return ''; | 1199 if (libraryTag == null) return ''; |
| 1107 return libraryTag.name.toString(); | 1200 return libraryTag.name.toString(); |
| 1108 } | 1201 } |
| 1109 | 1202 |
| 1203 String get libraryOrScriptName { |
| 1204 if (libraryTag != null) { |
| 1205 return libraryTag.name.toString(); |
| 1206 } else { |
| 1207 // Use the file name as script name. |
| 1208 String path = canonicalUri.path; |
| 1209 return path.substring(path.lastIndexOf('/') + 1); |
| 1210 } |
| 1211 } |
| 1212 |
| 1110 Scope buildScope() => new LibraryScope(this); | 1213 Scope buildScope() => new LibraryScope(this); |
| 1111 | 1214 |
| 1112 String toString() { | 1215 String toString() { |
| 1113 if (origin != null) { | 1216 if (origin != null) { |
| 1114 return 'patch library(${canonicalUri})'; | 1217 return 'patch library(${canonicalUri})'; |
| 1115 } else if (patch != null) { | 1218 } else if (patch != null) { |
| 1116 return 'origin library(${canonicalUri})'; | 1219 return 'origin library(${canonicalUri})'; |
| 1117 } else { | 1220 } else { |
| 1118 return 'library(${canonicalUri})'; | 1221 return 'library(${canonicalUri})'; |
| 1119 } | 1222 } |
| 1120 } | 1223 } |
| 1121 | 1224 |
| 1122 accept(ElementVisitor visitor, arg) { | 1225 accept(ElementVisitor visitor, arg) { |
| 1123 return visitor.visitLibraryElement(this, arg); | 1226 return visitor.visitLibraryElement(this, arg); |
| 1124 } | 1227 } |
| 1125 | 1228 |
| 1126 // TODO(johnniwinther): Remove these when issue 18630 is fixed. | 1229 // TODO(johnniwinther): Remove these when issue 18630 is fixed. |
| 1127 LibraryElementX get patch => super.patch; | 1230 LibraryElementX get patch => super.patch; |
| 1128 LibraryElementX get origin => super.origin; | 1231 LibraryElementX get origin => super.origin; |
| 1129 } | 1232 } |
| 1130 | 1233 |
| 1131 class PrefixElementX extends ElementX implements PrefixElement { | 1234 class PrefixElementX extends ElementX implements PrefixElement { |
| 1132 Token firstPosition; | 1235 Token firstPosition; |
| 1133 | 1236 |
| 1134 final ImportScope importScope = new ImportScope(); | 1237 final ImportScope importScope = new ImportScope(); |
| 1135 | 1238 |
| 1136 bool get isDeferred => _deferredImport != null; | 1239 bool get isDeferred => deferredImport != null; |
| 1137 | 1240 |
| 1138 // Only needed for deferred imports. | 1241 // Only needed for deferred imports. |
| 1139 Import _deferredImport; | 1242 final ImportElement deferredImport; |
| 1140 Import get deferredImport => _deferredImport; | |
| 1141 | 1243 |
| 1142 PrefixElementX(String prefix, Element enclosing, this.firstPosition) | 1244 PrefixElementX(String prefix, |
| 1245 Element enclosing, |
| 1246 this.firstPosition, |
| 1247 this.deferredImport) |
| 1143 : super(prefix, ElementKind.PREFIX, enclosing); | 1248 : super(prefix, ElementKind.PREFIX, enclosing); |
| 1144 | 1249 |
| 1145 bool get isTopLevel => false; | 1250 bool get isTopLevel => false; |
| 1146 | 1251 |
| 1147 Element lookupLocalMember(String memberName) => importScope[memberName]; | 1252 Element lookupLocalMember(String memberName) => importScope[memberName]; |
| 1148 | 1253 |
| 1149 DartType computeType(Compiler compiler) => const DynamicType(); | 1254 DartType computeType(Compiler compiler) => const DynamicType(); |
| 1150 | 1255 |
| 1151 Token get position => firstPosition; | 1256 Token get position => firstPosition; |
| 1152 | 1257 |
| 1153 void addImport(Element element, Import import, DiagnosticListener listener) { | 1258 void addImport(Element element, |
| 1259 ImportElement import, |
| 1260 DiagnosticListener listener) { |
| 1154 importScope.addImport(this, element, import, listener); | 1261 importScope.addImport(this, element, import, listener); |
| 1155 } | 1262 } |
| 1156 | 1263 |
| 1157 accept(ElementVisitor visitor, arg) { | 1264 accept(ElementVisitor visitor, arg) { |
| 1158 return visitor.visitPrefixElement(this, arg); | 1265 return visitor.visitPrefixElement(this, arg); |
| 1159 } | 1266 } |
| 1160 | 1267 |
| 1161 void markAsDeferred(Import deferredImport) { | |
| 1162 _deferredImport = deferredImport; | |
| 1163 } | |
| 1164 | |
| 1165 String toString() => '$kind($name)'; | 1268 String toString() => '$kind($name)'; |
| 1166 } | 1269 } |
| 1167 | 1270 |
| 1168 class TypedefElementX extends ElementX | 1271 class TypedefElementX extends ElementX |
| 1169 with AstElementMixin, | 1272 with AstElementMixin, |
| 1170 AnalyzableElementX, | 1273 AnalyzableElementX, |
| 1171 TypeDeclarationElementX<TypedefType> | 1274 TypeDeclarationElementX<TypedefType> |
| 1172 implements TypedefElement { | 1275 implements TypedefElement { |
| 1173 Typedef cachedNode; | 1276 Typedef cachedNode; |
| 1174 | 1277 |
| (...skipping 1792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2967 AstElement get definingElement; | 3070 AstElement get definingElement; |
| 2968 | 3071 |
| 2969 bool get hasResolvedAst => definingElement.hasTreeElements; | 3072 bool get hasResolvedAst => definingElement.hasTreeElements; |
| 2970 | 3073 |
| 2971 ResolvedAst get resolvedAst { | 3074 ResolvedAst get resolvedAst { |
| 2972 return new ResolvedAst(declaration, | 3075 return new ResolvedAst(declaration, |
| 2973 definingElement.node, definingElement.treeElements); | 3076 definingElement.node, definingElement.treeElements); |
| 2974 } | 3077 } |
| 2975 | 3078 |
| 2976 } | 3079 } |
| OLD | NEW |