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

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: Add test. 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, 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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698