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

Side by Side Diff: pkg/compiler/lib/src/deferred_load.dart

Issue 1335983004: Add ImportElement and ExportElement (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 3 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
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/outputter.dart ('k') | pkg/compiler/lib/src/dump_info.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 deferred_load; 5 library deferred_load;
6 6
7 import 'common/backend_api.dart' show 7 import 'common/backend_api.dart' show
8 Backend; 8 Backend;
9 import 'common/tasks.dart' show 9 import 'common/tasks.dart' show
10 CompilerTask; 10 CompilerTask;
11 import 'compiler.dart' show 11 import 'compiler.dart' show
12 Compiler; 12 Compiler;
13 import 'constants/values.dart' show 13 import 'constants/values.dart' show
14 ConstantValue, 14 ConstantValue,
15 ConstructedConstantValue, 15 ConstructedConstantValue,
16 DeferredConstantValue, 16 DeferredConstantValue,
17 StringConstantValue; 17 StringConstantValue;
18 import 'dart_types.dart'; 18 import 'dart_types.dart';
19 import 'diagnostics/messages.dart' show 19 import 'diagnostics/messages.dart' show
20 MessageKind; 20 MessageKind;
21 import 'diagnostics/spannable.dart' show 21 import 'diagnostics/spannable.dart' show
22 Spannable; 22 Spannable;
23 import 'elements/elements.dart' show 23 import 'elements/elements.dart' show
24 AccessorElement, 24 AccessorElement,
25 AstElement, 25 AstElement,
26 ClassElement, 26 ClassElement,
27 Element, 27 Element,
28 ElementKind, 28 ElementKind,
29 Elements, 29 Elements,
30 ExportElement,
30 FunctionElement, 31 FunctionElement,
32 ImportElement,
31 LibraryElement, 33 LibraryElement,
32 MetadataAnnotation, 34 MetadataAnnotation,
33 PrefixElement, 35 PrefixElement,
34 ScopeContainerElement, 36 ScopeContainerElement,
35 TypedefElement, 37 TypedefElement,
36 VoidElement; 38 VoidElement;
37 import 'js_backend/js_backend.dart' show 39 import 'js_backend/js_backend.dart' show
38 JavaScriptBackend; 40 JavaScriptBackend;
39 import 'resolution/resolution.dart' show 41 import 'resolution/resolution.dart' show
40 AnalyzableElementX; 42 AnalyzableElementX;
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 void registerConstantDeferredUse(DeferredConstantValue constant, 222 void registerConstantDeferredUse(DeferredConstantValue constant,
221 PrefixElement prefix) { 223 PrefixElement prefix) {
222 OutputUnit outputUnit = new OutputUnit(); 224 OutputUnit outputUnit = new OutputUnit();
223 outputUnit.imports.add(new _DeclaredDeferredImport(prefix.deferredImport)); 225 outputUnit.imports.add(new _DeclaredDeferredImport(prefix.deferredImport));
224 _constantToOutputUnit[constant] = outputUnit; 226 _constantToOutputUnit[constant] = outputUnit;
225 } 227 }
226 228
227 /// Answers whether [element] is explicitly deferred when referred to from 229 /// Answers whether [element] is explicitly deferred when referred to from
228 /// [library]. 230 /// [library].
229 bool _isExplicitlyDeferred(Element element, LibraryElement library) { 231 bool _isExplicitlyDeferred(Element element, LibraryElement library) {
230 Link<Import> imports = _getImports(element, library); 232 Iterable<ImportElement> imports = _getImports(element, library);
231 // If the element is not imported explicitly, it is implicitly imported 233 // If the element is not imported explicitly, it is implicitly imported
232 // not deferred. 234 // not deferred.
233 if (imports.isEmpty) return false; 235 if (imports.isEmpty) return false;
234 // An element could potentially be loaded by several imports. If all of them 236 // An element could potentially be loaded by several imports. If all of them
235 // is explicitly deferred, we say the element is explicitly deferred. 237 // is explicitly deferred, we say the element is explicitly deferred.
236 // TODO(sigurdm): We might want to give a warning if the imports do not 238 // TODO(sigurdm): We might want to give a warning if the imports do not
237 // agree. 239 // agree.
238 return imports.every((Import import) => import.isDeferred); 240 return imports.every((ImportElement import) => import.isDeferred);
239 } 241 }
240 242
241 /// Returns a [Link] of every [Import] that imports [element] into [library]. 243 /// Returns a [Link] of every [Import] that imports [element] into [library].
242 Link<Import> _getImports(Element element, LibraryElement library) { 244 Iterable<ImportElement> _getImports(Element element, LibraryElement library) {
243 if (element.isClassMember) { 245 if (element.isClassMember) {
244 element = element.enclosingClass; 246 element = element.enclosingClass;
245 } 247 }
246 if (element.isAccessor) { 248 if (element.isAccessor) {
247 element = (element as AccessorElement).abstractField; 249 element = (element as AccessorElement).abstractField;
248 } 250 }
249 return library.getImportsFor(element); 251 return library.getImportsFor(element);
250 } 252 }
251 253
252 /// Finds all elements and constants that [element] depends directly on. 254 /// Finds all elements and constants that [element] depends directly on.
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 Set<LibraryElement> _nonDeferredReachableLibraries(LibraryElement root) { 392 Set<LibraryElement> _nonDeferredReachableLibraries(LibraryElement root) {
391 Set<LibraryElement> result = new Set<LibraryElement>(); 393 Set<LibraryElement> result = new Set<LibraryElement>();
392 394
393 void traverseLibrary(LibraryElement library) { 395 void traverseLibrary(LibraryElement library) {
394 if (result.contains(library)) return; 396 if (result.contains(library)) return;
395 result.add(library); 397 result.add(library);
396 398
397 iterateTags(LibraryElement library) { 399 iterateTags(LibraryElement library) {
398 // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is 400 // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is
399 // changed to be a List instead of a Link. 401 // changed to be a List instead of a Link.
400 for (LibraryTag tag in library.tags) { 402 for (ImportElement import in library.imports) {
401 if (tag is! LibraryDependency) continue; 403 if (!import.isDeferred) {
402 LibraryDependency libraryDependency = tag; 404 LibraryElement importedLibrary = import.importedLibrary;
403 if (!(libraryDependency is Import && libraryDependency.isDeferred)) {
404 LibraryElement importedLibrary = library.getLibraryFromTag(tag);
405 traverseLibrary(importedLibrary); 405 traverseLibrary(importedLibrary);
406 } 406 }
407 } 407 }
408 for (ExportElement export in library.exports) {
409 LibraryElement exportedLibrary = export.exportedLibrary;
410 traverseLibrary(exportedLibrary);
411 }
408 } 412 }
409 413
410 iterateTags(library); 414 iterateTags(library);
411 if (library.isPatched) { 415 if (library.isPatched) {
412 iterateTags(library.implementation); 416 iterateTags(library.implementation);
413 } 417 }
414 } 418 }
415 traverseLibrary(root); 419 traverseLibrary(root);
416 result.add(compiler.coreLibrary); 420 result.add(compiler.coreLibrary);
417 return result; 421 return result;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 465
462 // This call can modify [dependentElements] and [dependentConstants]. 466 // This call can modify [dependentElements] and [dependentConstants].
463 _collectAllElementsAndConstantsResolvedFrom( 467 _collectAllElementsAndConstantsResolvedFrom(
464 element, dependentElements, dependentConstants, isMirrorUsage); 468 element, dependentElements, dependentConstants, isMirrorUsage);
465 469
466 library = element.library; 470 library = element.library;
467 } 471 }
468 472
469 for (Element dependency in dependentElements) { 473 for (Element dependency in dependentElements) {
470 if (_isExplicitlyDeferred(dependency, library)) { 474 if (_isExplicitlyDeferred(dependency, library)) {
471 for (Import deferredImport in _getImports(dependency, library)) { 475 for (ImportElement deferredImport in _getImports(dependency, library)) {
472 _mapDependencies( 476 _mapDependencies(element: dependency,
473 element: dependency,
474 import: new _DeclaredDeferredImport(deferredImport)); 477 import: new _DeclaredDeferredImport(deferredImport));
475 } 478 }
476 } else { 479 } else {
477 _mapDependencies(element: dependency, import: import); 480 _mapDependencies(element: dependency, import: import);
478 } 481 }
479 } 482 }
480 483
481 for (ConstantValue dependency in dependentConstants) { 484 for (ConstantValue dependency in dependentConstants) {
482 if (dependency is DeferredConstantValue) { 485 if (dependency is DeferredConstantValue) {
483 _mapConstantDependencies(dependency, 486 _mapConstantDependencies(dependency,
(...skipping 10 matching lines...) Expand all
494 void _addMirrorElements() { 497 void _addMirrorElements() {
495 void mapDependenciesIfResolved(Element element, 498 void mapDependenciesIfResolved(Element element,
496 _DeferredImport deferredImport) { 499 _DeferredImport deferredImport) {
497 // If an element is the target of a MirrorsUsed annotation but never used 500 // If an element is the target of a MirrorsUsed annotation but never used
498 // It will not be resolved, and we should not call isNeededForReflection. 501 // It will not be resolved, and we should not call isNeededForReflection.
499 // TODO(sigurdm): Unresolved elements should just answer false when 502 // TODO(sigurdm): Unresolved elements should just answer false when
500 // asked isNeededForReflection. Instead an internal error is triggered. 503 // asked isNeededForReflection. Instead an internal error is triggered.
501 // So we have to filter them out here. 504 // So we have to filter them out here.
502 if (element is AnalyzableElementX && !element.hasTreeElements) return; 505 if (element is AnalyzableElementX && !element.hasTreeElements) return;
503 if (compiler.backend.isAccessibleByReflection(element)) { 506 if (compiler.backend.isAccessibleByReflection(element)) {
504 _mapDependencies(element: element, import: deferredImport, 507 _mapDependencies(
505 isMirrorUsage: true); 508 element: element, import: deferredImport, isMirrorUsage: true);
506 } 509 }
507 } 510 }
508 511
509 // For each deferred import we analyze all elements reachable from the 512 // For each deferred import we analyze all elements reachable from the
510 // imported library through non-deferred imports. 513 // imported library through non-deferred imports.
511 handleLibrary(LibraryElement library, _DeferredImport deferredImport) { 514 void handleLibrary(LibraryElement library, _DeferredImport deferredImport) {
512 library.implementation.forEachLocalMember((Element element) { 515 library.implementation.forEachLocalMember((Element element) {
513 mapDependenciesIfResolved(element, deferredImport); 516 mapDependenciesIfResolved(element, deferredImport);
514 }); 517 });
515 518
516 for (MetadataAnnotation metadata in library.metadata) { 519 void processMetadata(Element element) {
517 ConstantValue constant = 520 for (MetadataAnnotation metadata in element.metadata) {
518 backend.constants.getConstantValueForMetadata(metadata);
519 if (constant != null) {
520 _mapConstantDependencies(constant, deferredImport);
521 }
522 }
523 for (LibraryTag tag in library.tags) {
524 for (MetadataAnnotation metadata in tag.metadata) {
525 ConstantValue constant = 521 ConstantValue constant =
526 backend.constants.getConstantValueForMetadata(metadata); 522 backend.constants.getConstantValueForMetadata(metadata);
527 if (constant != null) { 523 if (constant != null) {
528 _mapConstantDependencies(constant, deferredImport); 524 _mapConstantDependencies(constant, deferredImport);
529 } 525 }
530 } 526 }
531 } 527 }
528
529 processMetadata(library);
530 library.imports.forEach(processMetadata);
531 library.exports.forEach(processMetadata);
532 } 532 }
533 533
534 for (_DeferredImport deferredImport in _allDeferredImports.keys) { 534 for (_DeferredImport deferredImport in _allDeferredImports.keys) {
535 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; 535 LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
536 for (LibraryElement library in 536 for (LibraryElement library in
537 _nonDeferredReachableLibraries(deferredLibrary)) { 537 _nonDeferredReachableLibraries(deferredLibrary)) {
538 handleLibrary(library, deferredImport); 538 handleLibrary(library, deferredImport);
539 } 539 }
540 } 540 }
541 } 541 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 // import "lib.dart" as a; 705 // import "lib.dart" as a;
706 // import "lib2.dart" deferred as a; 706 // import "lib2.dart" deferred as a;
707 // 4. 707 // 4.
708 // import "lib.dart" as a; 708 // import "lib.dart" as a;
709 // import "lib2.dart" as a; 709 // import "lib2.dart" as a;
710 // We must be able to signal error for case 1, 2, 3, but accept case 4. 710 // We must be able to signal error for case 1, 2, 3, but accept case 4.
711 711
712 // The prefixes that have been used by any imports in this library. 712 // The prefixes that have been used by any imports in this library.
713 Setlet<String> usedPrefixes = new Setlet<String>(); 713 Setlet<String> usedPrefixes = new Setlet<String>();
714 // The last deferred import we saw with a given prefix (if any). 714 // The last deferred import we saw with a given prefix (if any).
715 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); 715 Map<String, ImportElement> prefixDeferredImport =
716 new Map<String, ImportElement>();
716 for (LibraryElement library in compiler.libraryLoader.libraries) { 717 for (LibraryElement library in compiler.libraryLoader.libraries) {
717 compiler.withCurrentElement(library, () { 718 compiler.withCurrentElement(library, () {
718 prefixDeferredImport.clear(); 719 prefixDeferredImport.clear();
719 usedPrefixes.clear(); 720 usedPrefixes.clear();
720 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List 721 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List
721 // instead of a Link. 722 // instead of a Link.
722 for (LibraryTag tag in library.tags) { 723 for (ImportElement import in library.imports) {
723 if (tag is! Import) continue;
724 Import import = tag;
725
726 /// Give an error if the old annotation-based syntax has been used. 724 /// Give an error if the old annotation-based syntax has been used.
727 List<MetadataAnnotation> metadataList = import.metadata; 725 List<MetadataAnnotation> metadataList = import.metadata;
728 if (metadataList != null) { 726 if (metadataList != null) {
729 for (MetadataAnnotation metadata in metadataList) { 727 for (MetadataAnnotation metadata in metadataList) {
730 metadata.ensureResolved(compiler); 728 metadata.ensureResolved(compiler);
731 ConstantValue value = 729 ConstantValue value =
732 compiler.constants.getConstantValue(metadata.constant); 730 compiler.constants.getConstantValue(metadata.constant);
733 Element element = value.getType(compiler.coreTypes).element; 731 Element element = value.getType(compiler.coreTypes).element;
734 if (element == deferredLibraryClass) { 732 if (element == deferredLibraryClass) {
735 compiler.reportError( 733 compiler.reportError(
736 import, MessageKind.DEFERRED_OLD_SYNTAX); 734 import, MessageKind.DEFERRED_OLD_SYNTAX);
737 } 735 }
738 } 736 }
739 } 737 }
740 738
741 String prefix = (import.prefix != null) 739 String prefix = (import.prefix != null)
742 ? import.prefix.toString() 740 ? import.prefix.name
743 : null; 741 : null;
744 // The last import we saw with the same prefix. 742 // The last import we saw with the same prefix.
745 Import previousDeferredImport = prefixDeferredImport[prefix]; 743 ImportElement previousDeferredImport = prefixDeferredImport[prefix];
746 if (import.isDeferred) { 744 if (import.isDeferred) {
747 _DeferredImport key = new _DeclaredDeferredImport(import); 745 _DeferredImport key = new _DeclaredDeferredImport(import);
748 LibraryElement importedLibrary = library.getLibraryFromTag(import); 746 LibraryElement importedLibrary = import.importedLibrary;
749 _allDeferredImports[key] = importedLibrary; 747 _allDeferredImports[key] = importedLibrary;
750 748
751 if (prefix == null) { 749 if (prefix == null) {
752 compiler.reportError(import, 750 compiler.reportError(import,
753 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); 751 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
754 } else { 752 } else {
755 prefixDeferredImport[prefix] = import; 753 prefixDeferredImport[prefix] = import;
756 _deferredImportDescriptions[key] = 754 _deferredImportDescriptions[key] =
757 new ImportDescription(import, library, compiler); 755 new ImportDescription(import, library, compiler);
758 } 756 }
759 isProgramSplit = true; 757 isProgramSplit = true;
760 lastDeferred = import; 758 lastDeferred = import;
761 } 759 }
762 if (prefix != null) { 760 if (prefix != null) {
763 if (previousDeferredImport != null || 761 if (previousDeferredImport != null ||
764 (import.isDeferred && usedPrefixes.contains(prefix))) { 762 (import.isDeferred && usedPrefixes.contains(prefix))) {
765 Import failingImport = (previousDeferredImport != null) 763 ImportElement failingImport = (previousDeferredImport != null)
766 ? previousDeferredImport 764 ? previousDeferredImport
767 : import; 765 : import;
768 compiler.reportError(failingImport.prefix, 766 compiler.reportError(failingImport.prefix,
769 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); 767 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX);
770 } 768 }
771 usedPrefixes.add(prefix); 769 usedPrefixes.add(prefix);
772 } 770 }
773 } 771 }
774 }); 772 });
775 } 773 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 } 867 }
870 } 868 }
871 869
872 class ImportDescription { 870 class ImportDescription {
873 /// Relative uri to the importing library. 871 /// Relative uri to the importing library.
874 final String importingUri; 872 final String importingUri;
875 /// The prefix this import is imported as. 873 /// The prefix this import is imported as.
876 final String prefix; 874 final String prefix;
877 final LibraryElement _importingLibrary; 875 final LibraryElement _importingLibrary;
878 876
879 ImportDescription(Import import, 877 ImportDescription(ImportElement import,
880 LibraryElement importingLibrary, 878 LibraryElement importingLibrary,
881 Compiler compiler) 879 Compiler compiler)
882 : importingUri = uri_extras.relativize( 880 : importingUri = uri_extras.relativize(
883 compiler.mainApp.canonicalUri, 881 compiler.mainApp.canonicalUri,
884 importingLibrary.canonicalUri, false), 882 importingLibrary.canonicalUri, false),
885 prefix = import.prefix.source, 883 prefix = import.prefix.name,
886 _importingLibrary = importingLibrary; 884 _importingLibrary = importingLibrary;
887 885
888 String get importingLibraryName { 886 String get importingLibraryName {
889 String libraryName = _importingLibrary.getLibraryName(); 887 return _importingLibrary.hasLibraryName
890 return libraryName == "" 888 ? _importingLibrary.libraryName : "<unnamed>";
891 ? "<unnamed>"
892 : libraryName;
893 } 889 }
894 } 890 }
895 891
896 /// A node in the deferred import graph. 892 /// A node in the deferred import graph.
897 /// 893 ///
898 /// This class serves as the root node; the 'import' of the main library. 894 /// This class serves as the root node; the 'import' of the main library.
899 class _DeferredImport { 895 class _DeferredImport {
900 const _DeferredImport(); 896 const _DeferredImport();
901 897
902 /// Computes a suggestive name for this import. 898 /// Computes a suggestive name for this import.
903 String computeImportDeferName(Compiler compiler) => 'main'; 899 String computeImportDeferName(Compiler compiler) => 'main';
904 } 900 }
905 901
906 /// A node in the deferred import graph defined by a deferred import directive. 902 /// A node in the deferred import graph defined by a deferred import directive.
907 class _DeclaredDeferredImport implements _DeferredImport { 903 class _DeclaredDeferredImport implements _DeferredImport {
908 final Import declaration; 904 final ImportElement declaration;
909 905
910 _DeclaredDeferredImport(this.declaration); 906 _DeclaredDeferredImport(this.declaration);
911 907
912 @override 908 @override
913 String computeImportDeferName(Compiler compiler) { 909 String computeImportDeferName(Compiler compiler) {
914 String result; 910 String result;
915 if (declaration.isDeferred) { 911 if (declaration.isDeferred) {
916 result = declaration.prefix.toString(); 912 result = declaration.prefix.name;
917 } else { 913 } else {
918 // Finds the first argument to the [DeferredLibrary] annotation 914 // Finds the first argument to the [DeferredLibrary] annotation
919 List<MetadataAnnotation> metadatas = declaration.metadata; 915 List<MetadataAnnotation> metadatas = declaration.metadata;
920 assert(metadatas != null); 916 assert(metadatas != null);
921 for (MetadataAnnotation metadata in metadatas) { 917 for (MetadataAnnotation metadata in metadatas) {
922 metadata.ensureResolved(compiler); 918 metadata.ensureResolved(compiler);
923 ConstantValue value = 919 ConstantValue value =
924 compiler.constants.getConstantValue(metadata.constant); 920 compiler.constants.getConstantValue(metadata.constant);
925 Element element = value.getType(compiler.coreTypes).element; 921 Element element = value.getType(compiler.coreTypes).element;
926 if (element == compiler.deferredLibraryClass) { 922 if (element == compiler.deferredLibraryClass) {
927 ConstructedConstantValue constant = value; 923 ConstructedConstantValue constant = value;
928 StringConstantValue s = constant.fields.values.single; 924 StringConstantValue s = constant.fields.values.single;
929 result = s.primitiveValue.slowToString(); 925 result = s.primitiveValue.slowToString();
930 break; 926 break;
931 } 927 }
932 } 928 }
933 } 929 }
934 assert(result != null); 930 assert(result != null);
935 return result; 931 return result;
936 } 932 }
937 933
938 bool operator ==(other) { 934 bool operator ==(other) {
939 if (other is! _DeclaredDeferredImport) return false; 935 if (other is! _DeclaredDeferredImport) return false;
940 return declaration == other.declaration; 936 return declaration == other.declaration;
941 } 937 }
942 938
943 int get hashCode => declaration.hashCode * 17; 939 int get hashCode => declaration.hashCode * 17;
944 } 940 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/outputter.dart ('k') | pkg/compiler/lib/src/dump_info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698