Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/elements/modelx.dart

Issue 27008003: Handle clash of prefix/non-prefix imports. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased + updated cf. comments. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698