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

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

Issue 25864002: Update handling of exports. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update status 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
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/warnings.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of dart2js; 5 part of dart2js;
6 6
7 /** 7 /**
8 * [CompilerTask] for loading libraries and setting up the import/export scopes. 8 * [CompilerTask] for loading libraries and setting up the import/export scopes.
9 * 9 *
10 * The library loader uses four different kinds of URIs in different parts of 10 * The library loader uses four different kinds of URIs in different parts of
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 } 562 }
563 } 563 }
564 } 564 }
565 565
566 /** 566 /**
567 * The combinator filter computed from an export tag and the library dependency 567 * The combinator filter computed from an export tag and the library dependency
568 * node for the library that declared the export tag. This represents an edge in 568 * node for the library that declared the export tag. This represents an edge in
569 * the library dependency graph. 569 * the library dependency graph.
570 */ 570 */
571 class ExportLink { 571 class ExportLink {
572 final Export export;
572 final CombinatorFilter combinatorFilter; 573 final CombinatorFilter combinatorFilter;
573 final LibraryDependencyNode exportNode; 574 final LibraryDependencyNode exportNode;
574 575
575 ExportLink(Export export, LibraryDependencyNode this.exportNode) 576 ExportLink(Export export, LibraryDependencyNode this.exportNode)
576 : this.combinatorFilter = new CombinatorFilter.fromTag(export); 577 : this.export = export,
578 this.combinatorFilter = new CombinatorFilter.fromTag(export);
577 579
578 /** 580 /**
579 * Exports [element] to the dependent library unless [element] is filtered by 581 * Exports [element] to the dependent library unless [element] is filtered by
580 * the export combinators. Returns [:true:] if the set pending exports of the 582 * the export combinators. Returns [:true:] if the set pending exports of the
581 * dependent library was modified. 583 * dependent library was modified.
582 */ 584 */
583 bool exportElement(Element element) { 585 bool exportElement(Element element) {
584 if (combinatorFilter.exclude(element)) return false; 586 if (combinatorFilter.exclude(element)) return false;
585 return exportNode.addElementToPendingExports(element); 587 return exportNode.addElementToPendingExports(element, export);
586 } 588 }
587 } 589 }
588 590
589 /** 591 /**
590 * A node in the library dependency graph. 592 * A node in the library dependency graph.
591 * 593 *
592 * This class is used to collect the library dependencies expressed through 594 * This class is used to collect the library dependencies expressed through
593 * import and export tags, and as the work-list entry in computations of library 595 * import and export tags, and as the work-list entry in computations of library
594 * exports performed in [LibraryDependencyHandler.computeExports]. 596 * exports performed in [LibraryDependencyHandler.computeExports].
595 */ 597 */
(...skipping 19 matching lines...) Expand all
615 */ 617 */
616 Link<ExportLink> dependencies = const Link<ExportLink>(); 618 Link<ExportLink> dependencies = const Link<ExportLink>();
617 619
618 /** 620 /**
619 * The export scope for [library] which is gradually computed by the work-list 621 * The export scope for [library] which is gradually computed by the work-list
620 * computation in [LibraryDependencyHandler.computeExports]. 622 * computation in [LibraryDependencyHandler.computeExports].
621 */ 623 */
622 Map<SourceString, Element> exportScope = 624 Map<SourceString, Element> exportScope =
623 new LinkedHashMap<SourceString, Element>(); 625 new LinkedHashMap<SourceString, Element>();
624 626
627 /// Map from exported elements to the export directives that exported them.
628 Map<Element, Link<Export>> exporters = new Map<Element, Link<Export>>();
629
625 /** 630 /**
626 * The set of exported elements that need to be propageted to dependent 631 * The set of exported elements that need to be propageted to dependent
627 * libraries as part of the work-list computation performed in 632 * libraries as part of the work-list computation performed in
628 * [LibraryDependencyHandler.computeExports]. 633 * [LibraryDependencyHandler.computeExports]. Each export element is mapped
634 * to a list of exports directives that export it.
629 */ 635 */
630 Set<Element> pendingExportSet = new Set<Element>(); 636 Map<Element, Link<Export>> pendingExportMap =
637 new Map<Element, Link<Export>>();
631 638
632 LibraryDependencyNode(LibraryElement this.library); 639 LibraryDependencyNode(LibraryElement this.library);
633 640
634 /** 641 /**
635 * Registers that the library of this node imports [importLibrary] through the 642 * Registers that the library of this node imports [importLibrary] through the
636 * [import] tag. 643 * [import] tag.
637 */ 644 */
638 void registerImportDependency(Import import, 645 void registerImportDependency(Import import,
639 LibraryElement importedLibrary) { 646 LibraryElement importedLibrary) {
640 imports = imports.prepend(new ImportLink(import, importedLibrary)); 647 imports = imports.prepend(new ImportLink(import, importedLibrary));
641 } 648 }
642 649
643 /** 650 /**
644 * Registers that the library of this node is exported by 651 * Registers that the library of this node is exported by
645 * [exportingLibraryNode] through the [export] tag. 652 * [exportingLibraryNode] through the [export] tag.
646 */ 653 */
647 void registerExportDependency(Export export, 654 void registerExportDependency(Export export,
648 LibraryDependencyNode exportingLibraryNode) { 655 LibraryDependencyNode exportingLibraryNode) {
649 dependencies = 656 dependencies =
650 dependencies.prepend(new ExportLink(export, exportingLibraryNode)); 657 dependencies.prepend(new ExportLink(export, exportingLibraryNode));
651 } 658 }
652 659
653 /** 660 /**
654 * Registers all non-private locally declared members of the library of this 661 * Registers all non-private locally declared members of the library of this
655 * node to be exported. This forms the basis for the work-list computation of 662 * node to be exported. This forms the basis for the work-list computation of
656 * the export scopes performed in [LibraryDependencyHandler.computeExports]. 663 * the export scopes performed in [LibraryDependencyHandler.computeExports].
657 */ 664 */
658 void registerInitialExports() { 665 void registerInitialExports() {
659 pendingExportSet.addAll(library.getNonPrivateElementsInScope()); 666 for (Element element in library.getNonPrivateElementsInScope()) {
667 pendingExportMap[element] = const Link<Export>();
668 }
660 } 669 }
661 670
662 void registerHandledExports(LibraryElement exportedLibraryElement, 671 void registerHandledExports(LibraryElement exportedLibraryElement,
672 Export export,
663 CombinatorFilter filter) { 673 CombinatorFilter filter) {
664 assert(invariant(library, exportedLibraryElement.exportsHandled)); 674 assert(invariant(library, exportedLibraryElement.exportsHandled));
665 for (Element exportedElement in exportedLibraryElement.exports) { 675 for (Element exportedElement in exportedLibraryElement.exports) {
666 if (!filter.exclude(exportedElement)) { 676 if (!filter.exclude(exportedElement)) {
667 pendingExportSet.add(exportedElement); 677 Link<Export> exports =
678 pendingExportMap.putIfAbsent(exportedElement,
679 () => const Link<Export>());
680 pendingExportMap[exportedElement] = exports.prepend(export);
668 } 681 }
669 } 682 }
670 } 683 }
671 684
672 /** 685 /**
673 * Registers the compute export scope with the node library. 686 * Registers the compute export scope with the node library.
674 */ 687 */
675 void registerExports() { 688 void registerExports() {
676 library.setExports(exportScope.values.toList()); 689 library.setExports(exportScope.values.toList());
677 } 690 }
678 691
679 /** 692 /**
680 * Registers the imports of the node library. 693 * Registers the imports of the node library.
681 */ 694 */
682 void registerImports(Compiler compiler) { 695 void registerImports(Compiler compiler) {
683 for (ImportLink link in imports) { 696 for (ImportLink link in imports) {
684 link.importLibrary(compiler, library); 697 link.importLibrary(compiler, library);
685 } 698 }
686 } 699 }
687 700
688 /** 701 /**
689 * Copies and clears pending export set for this node. 702 * Copies and clears pending export set for this node.
690 */ 703 */
691 List<Element> pullPendingExports() { 704 Map<Element, Link<Export>> pullPendingExports() {
692 List<Element> pendingExports = new List.from(pendingExportSet); 705 Map<Element, Link<Export>> pendingExports =
693 pendingExportSet.clear(); 706 new Map<Element, Link<Export>>.from(pendingExportMap);
707 pendingExportMap.clear();
694 return pendingExports; 708 return pendingExports;
695 } 709 }
696 710
697 /** 711 /**
698 * Adds [element] to the export scope for this node. If the [element] name 712 * Adds [element] to the export scope for this node. If the [element] name
699 * is a duplicate, an error element is inserted into the export scope. 713 * is a duplicate, an error element is inserted into the export scope.
700 */ 714 */
701 Element addElementToExportScope(Compiler compiler, Element element) { 715 Element addElementToExportScope(Compiler compiler, Element element,
716 Link<Export> exports) {
717
702 SourceString name = element.name; 718 SourceString name = element.name;
719
720 void reportDuplicateExport(Element duplicate,
721 Link<Export> duplicateExports,
722 {bool reportError: true}) {
723 compiler.withCurrentElement(library, () {
724 for (Export export in duplicateExports) {
725 if (reportError) {
726 compiler.reportError(export,
727 MessageKind.DUPLICATE_EXPORT, {'name': name});
728 reportError = false;
729 } else {
730 compiler.reportInfo(export,
731 MessageKind.DUPLICATE_EXPORT_CONT, {'name': name});
732 }
733 }
734 });
735 }
736
737 void reportDuplicateExportDecl(Element duplicate,
738 Link<Export> duplicateExports) {
739 compiler.reportInfo(duplicate, MessageKind.DUPLICATE_EXPORT_DECL,
740 {'name': name, 'uriString': duplicateExports.head.uri});
741 }
742
703 Element existingElement = exportScope[name]; 743 Element existingElement = exportScope[name];
704 if (existingElement != null) { 744 if (existingElement != null && existingElement != element) {
705 if (existingElement.isErroneous()) { 745 if (existingElement.isErroneous()) {
706 compiler.reportError(element, MessageKind.DUPLICATE_EXPORT, 746 reportDuplicateExport(element, exports);
707 {'name': name}); 747 reportDuplicateExportDecl(element, exports);
708 element = existingElement; 748 element = existingElement;
709 } else if (existingElement.getLibrary() != library) { 749 } else if (existingElement.getLibrary() != library) {
710 // Declared elements hide exported elements. 750 // Declared elements hide exported elements.
711 compiler.reportError(existingElement, MessageKind.DUPLICATE_EXPORT, 751 Link<Export> existingExports = exporters[existingElement];
712 {'name': name}); 752 reportDuplicateExport(existingElement, existingExports);
713 compiler.reportError(element, MessageKind.DUPLICATE_EXPORT, 753 reportDuplicateExport(element, exports, reportError: false);
714 {'name': name}); 754 reportDuplicateExportDecl(existingElement, existingExports);
755 reportDuplicateExportDecl(element, exports);
715 element = exportScope[name] = new ErroneousElementX( 756 element = exportScope[name] = new ErroneousElementX(
716 MessageKind.DUPLICATE_EXPORT, {'name': name}, name, library); 757 MessageKind.DUPLICATE_EXPORT, {'name': name}, name, library);
717 } 758 }
718 } else { 759 } else {
719 exportScope[name] = element; 760 exportScope[name] = element;
761 exporters[element] = exports;
720 } 762 }
721 return element; 763 return element;
722 } 764 }
723 765
724 /** 766 /**
725 * Propagates the exported [element] to all library nodes that depend upon 767 * Propagates the exported [element] to all library nodes that depend upon
726 * this node. If the propagation updated any pending exports, [:true:] is 768 * this node. If the propagation updated any pending exports, [:true:] is
727 * returned. 769 * returned.
728 */ 770 */
729 bool propagateElement(Element element) { 771 bool propagateElement(Element element) {
730 bool change = false; 772 bool change = false;
731 for (ExportLink link in dependencies) { 773 for (ExportLink link in dependencies) {
732 if (link.exportElement(element)) { 774 if (link.exportElement(element)) {
733 change = true; 775 change = true;
734 } 776 }
735 } 777 }
736 return change; 778 return change;
737 } 779 }
738 780
739 /** 781 /**
740 * Adds [element] to the pending exports of this node and returns [:true:] if 782 * Adds [element] to the pending exports of this node and returns [:true:] if
741 * the pending export set was modified. The combinators of [export] are used 783 * the pending export set was modified. The combinators of [export] are used
742 * to filter the element. 784 * to filter the element.
743 */ 785 */
744 bool addElementToPendingExports(Element element) { 786 bool addElementToPendingExports(Element element, Export export) {
787 bool changed = false;
745 if (!identical(exportScope[element.name], element)) { 788 if (!identical(exportScope[element.name], element)) {
746 if (!pendingExportSet.contains(element)) { 789 Link<Export> exports = pendingExportMap.putIfAbsent(element, () {
747 pendingExportSet.add(element); 790 changed = true;
748 return true; 791 return const Link<Export>();
749 } 792 });
793 pendingExportMap[element] = exports.prepend(export);
750 } 794 }
751 return false; 795 return changed;
752 } 796 }
753 } 797 }
754 798
755 /** 799 /**
756 * Helper class used for computing the possibly cyclic import/export scopes of 800 * Helper class used for computing the possibly cyclic import/export scopes of
757 * a set of libraries. 801 * a set of libraries.
758 * 802 *
759 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded 803 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded
760 * libraries and to compute their import/export scopes through a fixed-point 804 * libraries and to compute their import/export scopes through a fixed-point
761 * algorithm. 805 * algorithm.
(...skipping 14 matching lines...) Expand all
776 820
777 /** 821 /**
778 * Performs a fixed-point computation on the export scopes of all registered 822 * Performs a fixed-point computation on the export scopes of all registered
779 * libraries and creates the import/export of the libraries based on the 823 * libraries and creates the import/export of the libraries based on the
780 * fixed-point. 824 * fixed-point.
781 */ 825 */
782 void computeExports() { 826 void computeExports() {
783 bool changed = true; 827 bool changed = true;
784 while (changed) { 828 while (changed) {
785 changed = false; 829 changed = false;
786 Map<LibraryDependencyNode, List<Element>> tasks = 830 Map<LibraryDependencyNode, Map<Element, Link<Export>>> tasks =
787 new LinkedHashMap<LibraryDependencyNode, List<Element>>(); 831 new Map<LibraryDependencyNode, Map<Element, Link<Export>>>();
788 832
789 // Locally defined elements take precedence over exported 833 // Locally defined elements take precedence over exported
790 // elements. So we must propagate local elements first. We 834 // elements. So we must propagate local elements first. We
791 // ensure this by pulling the pending exports before 835 // ensure this by pulling the pending exports before
792 // propagating. This enforces that we handle exports 836 // propagating. This enforces that we handle exports
793 // breadth-first, with locally defined elements being level 0. 837 // breadth-first, with locally defined elements being level 0.
794 nodeMap.forEach((_, LibraryDependencyNode node) { 838 nodeMap.forEach((_, LibraryDependencyNode node) {
795 List<Element> pendingExports = node.pullPendingExports(); 839 Map<Element, Link<Export>> pendingExports = node.pullPendingExports();
796 tasks[node] = pendingExports; 840 tasks[node] = pendingExports;
797 }); 841 });
798 tasks.forEach((LibraryDependencyNode node, List<Element> pendingExports) { 842 tasks.forEach((LibraryDependencyNode node,
799 pendingExports.forEach((Element element) { 843 Map<Element, Link<Export>> pendingExports) {
800 element = node.addElementToExportScope(compiler, element); 844 pendingExports.forEach((Element element, Link<Export> exports) {
845 element = node.addElementToExportScope(compiler, element, exports);
801 if (node.propagateElement(element)) { 846 if (node.propagateElement(element)) {
802 changed = true; 847 changed = true;
803 } 848 }
804 }); 849 });
805 }); 850 });
806 } 851 }
807 852
808 // Setup export scopes. These have to be set before computing the import 853 // Setup export scopes. These have to be set before computing the import
809 // scopes to avoid accessing uncomputed export scopes during handling of 854 // scopes to avoid accessing uncomputed export scopes during handling of
810 // imports. 855 // imports.
(...skipping 15 matching lines...) Expand all
826 LibraryElement loadedLibrary) { 871 LibraryElement loadedLibrary) {
827 if (tag != null) { 872 if (tag != null) {
828 library.recordResolvedTag(tag, loadedLibrary); 873 library.recordResolvedTag(tag, loadedLibrary);
829 } 874 }
830 if (tag is Export) { 875 if (tag is Export) {
831 // [loadedLibrary] is exported by [library]. 876 // [loadedLibrary] is exported by [library].
832 LibraryDependencyNode exportingNode = nodeMap[library]; 877 LibraryDependencyNode exportingNode = nodeMap[library];
833 if (loadedLibrary.exportsHandled) { 878 if (loadedLibrary.exportsHandled) {
834 // Export scope already computed on [loadedLibrary]. 879 // Export scope already computed on [loadedLibrary].
835 var combinatorFilter = new CombinatorFilter.fromTag(tag); 880 var combinatorFilter = new CombinatorFilter.fromTag(tag);
836 exportingNode.registerHandledExports(loadedLibrary, combinatorFilter); 881 exportingNode.registerHandledExports(
882 loadedLibrary, tag, combinatorFilter);
837 return; 883 return;
838 } 884 }
839 LibraryDependencyNode exportedNode = nodeMap[loadedLibrary]; 885 LibraryDependencyNode exportedNode = nodeMap[loadedLibrary];
840 assert(invariant(loadedLibrary, exportedNode != null, 886 assert(invariant(loadedLibrary, exportedNode != null,
841 message: "$loadedLibrary has not been registered")); 887 message: "$loadedLibrary has not been registered"));
842 assert(invariant(library, exportingNode != null, 888 assert(invariant(library, exportingNode != null,
843 message: "$library has not been registered")); 889 message: "$library has not been registered"));
844 exportedNode.registerExportDependency(tag, exportingNode); 890 exportedNode.registerExportDependency(tag, exportingNode);
845 } else if (tag == null || tag is Import) { 891 } else if (tag == null || tag is Import) {
846 // [loadedLibrary] is imported by [library]. 892 // [loadedLibrary] is imported by [library].
(...skipping 12 matching lines...) Expand all
859 } 905 }
860 906
861 /** 907 /**
862 * Registers all top-level entities of [library] as starting point for the 908 * Registers all top-level entities of [library] as starting point for the
863 * fixed-point computation of the import/export scopes. 909 * fixed-point computation of the import/export scopes.
864 */ 910 */
865 void registerLibraryExports(LibraryElement library) { 911 void registerLibraryExports(LibraryElement library) {
866 nodeMap[library].registerInitialExports(); 912 nodeMap[library].registerInitialExports();
867 } 913 }
868 } 914 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/warnings.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698