Chromium Code Reviews| 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 |