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 'dart:collection' show LinkedHashMap; | 7 import 'dart:collection' show LinkedHashMap; |
8 | 8 |
9 import 'elements.dart'; | 9 import 'elements.dart'; |
10 import '../../compiler.dart' as api; | 10 import '../../compiler.dart' as api; |
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
627 } | 627 } |
628 | 628 |
629 bool get hasMembers => !localMembers.isEmpty; | 629 bool get hasMembers => !localMembers.isEmpty; |
630 | 630 |
631 int compareTo(CompilationUnitElement other) { | 631 int compareTo(CompilationUnitElement other) { |
632 if (this == other) return 0; | 632 if (this == other) return 0; |
633 return '${script.uri}'.compareTo('${other.script.uri}'); | 633 return '${script.uri}'.compareTo('${other.script.uri}'); |
634 } | 634 } |
635 } | 635 } |
636 | 636 |
637 class ImportScope { | |
638 /** | |
639 * Map for elements imported through import declarations. | |
640 * | |
641 * Addition to the map is performed by [addImport]. Lookup is done trough | |
642 * [find]. | |
643 */ | |
644 final Map<SourceString, Element> importScope = | |
645 new Map<SourceString, Element>(); | |
646 | |
647 /** | |
648 * Adds [element] to the import scope of this library. | |
649 * | |
650 * If an element by the same name is already in the imported scope, an | |
651 * [ErroneousElement] will be put in the imported scope, allowing for | |
652 * detection of ambiguous uses of imported names. | |
653 */ | |
654 void addImport(Element enclosingElement, | |
655 Element element, Import import, DiagnosticListener listener) { | |
kasperl
2013/10/11 11:51:49
Use separate lines for the arguments?
Johnni Winther
2013/10/11 12:30:30
Done.
| |
656 LibraryElementX library = enclosingElement.getLibrary(); | |
657 Map<Element, Link<Import>> importers = library.importers; | |
658 importers[element] = | |
659 importers.putIfAbsent(element, () => const Link<Import>()) | |
660 .prepend(import); | |
kasperl
2013/10/11 11:51:49
Don't we usually indent this more?
Johnni Winther
2013/10/11 12:30:30
Yes. Done.
| |
661 SourceString name = element.name; | |
662 Element existing = importScope.putIfAbsent(name, () => element); | |
663 | |
664 Element createWarnOnUseElement(Spannable spannable, | |
665 MessageKind messageKind, | |
666 Element hidingElement, | |
667 Element hiddenElement) { | |
668 Uri hiddenUri = hiddenElement.getLibrary().canonicalUri; | |
669 Uri hidingUri = hidingElement.getLibrary().canonicalUri; | |
670 return new WarnOnUseElementX( | |
671 new WrappedMessage( | |
672 null, // Report on reference to [hidingElement]. | |
673 messageKind, | |
674 {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}), | |
675 new WrappedMessage( | |
676 listener.spanFromSpannable(spannable), | |
677 MessageKind.IMPORTED_HERE, | |
678 {'name': name}), | |
679 enclosingElement, hidingElement); | |
680 } | |
681 | |
682 if (existing != element) { | |
683 if (existing.getLibrary().isPlatformLibrary && | |
684 !element.getLibrary().isPlatformLibrary) { | |
685 // [existing] is implicitly hidden. | |
686 importScope[name] = createWarnOnUseElement( | |
687 import, MessageKind.HIDDEN_IMPORT, element, existing); | |
688 } else if (!existing.getLibrary().isPlatformLibrary && | |
689 element.getLibrary().isPlatformLibrary) { | |
690 // [element] is implicitly hidden. | |
691 if (import == null) { | |
692 // [element] is imported implicitly (probably through dart:core). | |
693 importScope[name] = createWarnOnUseElement( | |
694 importers[existing].head, MessageKind.HIDDEN_IMPLICIT_IMPORT, | |
695 existing, element); | |
696 } else { | |
697 importScope[name] = createWarnOnUseElement( | |
698 import, MessageKind.HIDDEN_IMPORT, existing, element); | |
699 } | |
700 } else { | |
701 importScope[name] = new AmbiguousElementX( | |
702 MessageKind.DUPLICATE_IMPORT, {'name': name}, | |
703 enclosingElement, existing, element); | |
704 } | |
705 } | |
706 } | |
707 | |
708 Element operator [](SourceString name) => importScope[name]; | |
709 } | |
710 | |
637 class LibraryElementX extends ElementX implements LibraryElement { | 711 class LibraryElementX extends ElementX implements LibraryElement { |
638 final Uri canonicalUri; | 712 final Uri canonicalUri; |
639 CompilationUnitElement entryCompilationUnit; | 713 CompilationUnitElement entryCompilationUnit; |
640 Link<CompilationUnitElement> compilationUnits = | 714 Link<CompilationUnitElement> compilationUnits = |
641 const Link<CompilationUnitElement>(); | 715 const Link<CompilationUnitElement>(); |
642 Link<LibraryTag> tags = const Link<LibraryTag>(); | 716 Link<LibraryTag> tags = const Link<LibraryTag>(); |
643 LibraryName libraryTag; | 717 LibraryName libraryTag; |
644 bool canUseNative = false; | 718 bool canUseNative = false; |
645 Link<Element> localMembers = const Link<Element>(); | 719 Link<Element> localMembers = const Link<Element>(); |
646 final ScopeX localScope = new ScopeX(); | 720 final ScopeX localScope = new ScopeX(); |
721 final ImportScope importScope = new ImportScope(); | |
647 | 722 |
648 /** | 723 /** |
649 * If this library is patched, [patch] points to the patch library. | 724 * If this library is patched, [patch] points to the patch library. |
650 * | 725 * |
651 * See [:patch_parser.dart:] for a description of the terminology. | 726 * See [:patch_parser.dart:] for a description of the terminology. |
652 */ | 727 */ |
653 LibraryElementX patch = null; | 728 LibraryElementX patch = null; |
654 | 729 |
655 /** | 730 /** |
656 * If this is a patch library, [origin] points to the origin library. | 731 * If this is a patch library, [origin] points to the origin library. |
657 * | 732 * |
658 * See [:patch_parser.dart:] for a description of the terminology. | 733 * See [:patch_parser.dart:] for a description of the terminology. |
659 */ | 734 */ |
660 final LibraryElementX origin; | 735 final LibraryElementX origin; |
661 | 736 |
662 /** | |
663 * Map for elements imported through import declarations. | |
664 * | |
665 * Addition to the map is performed by [addImport]. Lookup is done trough | |
666 * [find]. | |
667 */ | |
668 final Map<SourceString, Element> importScope; | |
669 | |
670 /// A mapping from an imported element to the "import" tag. | 737 /// A mapping from an imported element to the "import" tag. |
671 final Map<Element, Link<Import>> importers; | 738 final Map<Element, Link<Import>> importers; |
672 | 739 |
673 /** | 740 /** |
674 * Link for elements exported either through export declarations or through | 741 * Link for elements exported either through export declarations or through |
675 * declaration. This field should not be accessed directly but instead through | 742 * declaration. This field should not be accessed directly but instead through |
676 * the [exports] getter. | 743 * the [exports] getter. |
677 * | 744 * |
678 * [LibraryDependencyHandler] sets this field through [setExports] when the | 745 * [LibraryDependencyHandler] sets this field through [setExports] when the |
679 * library is loaded. | 746 * library is loaded. |
680 */ | 747 */ |
681 Link<Element> slotForExports; | 748 Link<Element> slotForExports; |
682 | 749 |
683 final Map<LibraryDependency, LibraryElement> tagMapping = | 750 final Map<LibraryDependency, LibraryElement> tagMapping = |
684 new LinkedHashMap<LibraryDependency, LibraryElement>(); | 751 new LinkedHashMap<LibraryDependency, LibraryElement>(); |
685 | 752 |
686 LibraryElementX(Script script, [Uri canonicalUri, LibraryElement this.origin]) | 753 LibraryElementX(Script script, [Uri canonicalUri, LibraryElement this.origin]) |
687 : this.canonicalUri = ((canonicalUri == null) ? script.uri : canonicalUri), | 754 : this.canonicalUri = ((canonicalUri == null) ? script.uri : canonicalUri), |
688 importScope = new Map<SourceString, Element>(), | |
689 importers = new Map<Element, Link<Import>>(), | 755 importers = new Map<Element, Link<Import>>(), |
690 super(new SourceString(script.name), ElementKind.LIBRARY, null) { | 756 super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
691 entryCompilationUnit = new CompilationUnitElementX(script, this); | 757 entryCompilationUnit = new CompilationUnitElementX(script, this); |
692 if (isPatch) { | 758 if (isPatch) { |
693 origin.patch = this; | 759 origin.patch = this; |
694 } | 760 } |
695 } | 761 } |
696 | 762 |
697 bool get isPatched => patch != null; | 763 bool get isPatched => patch != null; |
698 bool get isPatch => origin != null; | 764 bool get isPatch => origin != null; |
(...skipping 27 matching lines...) Expand all Loading... | |
726 | 792 |
727 LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag]; | 793 LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag]; |
728 | 794 |
729 /** | 795 /** |
730 * Adds [element] to the import scope of this library. | 796 * Adds [element] to the import scope of this library. |
731 * | 797 * |
732 * If an element by the same name is already in the imported scope, an | 798 * If an element by the same name is already in the imported scope, an |
733 * [ErroneousElement] will be put in the imported scope, allowing for detectio n of ambiguous uses of imported names. | 799 * [ErroneousElement] will be put in the imported scope, allowing for detectio n of ambiguous uses of imported names. |
734 */ | 800 */ |
735 void addImport(Element element, Import import, DiagnosticListener listener) { | 801 void addImport(Element element, Import import, DiagnosticListener listener) { |
736 importers[element] = | 802 importScope.addImport(this, element, import, listener); |
737 importers.putIfAbsent(element, () => const Link<Import>()) | |
738 .prepend(import); | |
739 SourceString name = element.name; | |
740 Element existing = importScope.putIfAbsent(name, () => element); | |
741 | |
742 Element createWarnOnUseElement(Spannable spannable, | |
743 MessageKind messageKind, | |
744 Element hidingElement, | |
745 Element hiddenElement) { | |
746 Uri hiddenUri = hiddenElement.getLibrary().canonicalUri; | |
747 Uri hidingUri = hidingElement.getLibrary().canonicalUri; | |
748 return new WarnOnUseElementX( | |
749 new WrappedMessage( | |
750 null, // Report on reference to [hidingElement]. | |
751 messageKind, | |
752 {'name': name, 'hiddenUri': hiddenUri, 'hidingUri': hidingUri}), | |
753 new WrappedMessage( | |
754 listener.spanFromSpannable(spannable), | |
755 MessageKind.IMPORTED_HERE, | |
756 {'name': name}), | |
757 this, hidingElement); | |
758 } | |
759 | |
760 if (existing != element) { | |
761 if (existing.getLibrary().isPlatformLibrary && | |
762 !element.getLibrary().isPlatformLibrary) { | |
763 // [existing] is implicitly hidden. | |
764 importScope[name] = createWarnOnUseElement( | |
765 import, MessageKind.HIDDEN_IMPORT, element, existing); | |
766 } else if (!existing.getLibrary().isPlatformLibrary && | |
767 element.getLibrary().isPlatformLibrary) { | |
768 // [element] is implicitly hidden. | |
769 if (import == null) { | |
770 // [element] is imported implicitly (probably through dart:core). | |
771 importScope[name] = createWarnOnUseElement( | |
772 importers[existing].head, MessageKind.HIDDEN_IMPLICIT_IMPORT, | |
773 existing, element); | |
774 } else { | |
775 importScope[name] = createWarnOnUseElement( | |
776 import, MessageKind.HIDDEN_IMPORT, existing, element); | |
777 } | |
778 } else { | |
779 // TODO(johnniwinther): Provide access to the import tags from which | |
780 // the elements came. | |
781 importScope[name] = new AmbiguousElementX( | |
782 MessageKind.DUPLICATE_IMPORT, {'name': name}, | |
783 this, existing, element); | |
784 } | |
785 } | |
786 } | 803 } |
787 | 804 |
788 void addMember(Element element, DiagnosticListener listener) { | 805 void addMember(Element element, DiagnosticListener listener) { |
789 localMembers = localMembers.prepend(element); | 806 localMembers = localMembers.prepend(element); |
790 addToScope(element, listener); | 807 addToScope(element, listener); |
791 } | 808 } |
792 | 809 |
793 void addToScope(Element element, DiagnosticListener listener) { | 810 void addToScope(Element element, DiagnosticListener listener) { |
794 localScope.add(element, listener); | 811 localScope.add(element, listener); |
795 } | 812 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
925 } | 942 } |
926 } | 943 } |
927 | 944 |
928 int compareTo(LibraryElement other) { | 945 int compareTo(LibraryElement other) { |
929 if (this == other) return 0; | 946 if (this == other) return 0; |
930 return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName()); | 947 return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName()); |
931 } | 948 } |
932 } | 949 } |
933 | 950 |
934 class PrefixElementX extends ElementX implements PrefixElement { | 951 class PrefixElementX extends ElementX implements PrefixElement { |
935 Map<SourceString, Element> imported; | |
936 Token firstPosition; | 952 Token firstPosition; |
937 | 953 |
954 final ImportScope importScope = new ImportScope(); | |
955 | |
938 PrefixElementX(SourceString prefix, Element enclosing, this.firstPosition) | 956 PrefixElementX(SourceString prefix, Element enclosing, this.firstPosition) |
939 : imported = new Map<SourceString, Element>(), | 957 : super(prefix, ElementKind.PREFIX, enclosing); |
940 super(prefix, ElementKind.PREFIX, enclosing); | |
941 | 958 |
942 Element lookupLocalMember(SourceString memberName) => imported[memberName]; | 959 Element lookupLocalMember(SourceString memberName) => importScope[memberName]; |
943 | 960 |
944 DartType computeType(Compiler compiler) => compiler.types.dynamicType; | 961 DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
945 | 962 |
946 Token position() => firstPosition; | 963 Token position() => firstPosition; |
964 | |
965 void addImport(Element element, Import import, DiagnosticListener listener) { | |
966 importScope.addImport(this, element, import, listener); | |
967 } | |
947 } | 968 } |
948 | 969 |
949 class TypedefElementX extends ElementX implements TypedefElement { | 970 class TypedefElementX extends ElementX implements TypedefElement { |
950 Typedef cachedNode; | 971 Typedef cachedNode; |
951 | 972 |
952 /** | 973 /** |
953 * The type of this typedef in which the type arguments are the type | 974 * The type of this typedef in which the type arguments are the type |
954 * variables. | 975 * variables. |
955 * | 976 * |
956 * This resembles the [ClassElement.thisType] though a typedef has no notion | 977 * This resembles the [ClassElement.thisType] though a typedef has no notion |
(...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2306 | 2327 |
2307 MetadataAnnotation ensureResolved(Compiler compiler) { | 2328 MetadataAnnotation ensureResolved(Compiler compiler) { |
2308 if (resolutionState == STATE_NOT_STARTED) { | 2329 if (resolutionState == STATE_NOT_STARTED) { |
2309 compiler.resolver.resolveMetadataAnnotation(this); | 2330 compiler.resolver.resolveMetadataAnnotation(this); |
2310 } | 2331 } |
2311 return this; | 2332 return this; |
2312 } | 2333 } |
2313 | 2334 |
2314 String toString() => 'MetadataAnnotation($value, $resolutionState)'; | 2335 String toString() => 'MetadataAnnotation($value, $resolutionState)'; |
2315 } | 2336 } |
OLD | NEW |