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