OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.analyzer.loader; | 4 library kernel.analyzer.loader; |
5 | 5 |
6 import 'dart:async'; | 6 import 'dart:async'; |
7 import 'dart:io' as io; | 7 import 'dart:io' as io; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
11 import 'package:analyzer/file_system/physical_file_system.dart'; | 11 import 'package:analyzer/file_system/physical_file_system.dart'; |
12 import 'package:analyzer/source/package_map_resolver.dart'; | 12 import 'package:analyzer/source/package_map_resolver.dart'; |
13 import 'package:analyzer/src/dart/scanner/scanner.dart'; | 13 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
14 import 'package:analyzer/src/dart/sdk/sdk.dart'; | 14 import 'package:analyzer/src/dart/sdk/sdk.dart'; |
15 import 'package:analyzer/src/generated/engine.dart'; | 15 import 'package:analyzer/src/generated/engine.dart'; |
16 import 'package:analyzer/src/generated/parser.dart'; | 16 import 'package:analyzer/src/generated/parser.dart'; |
17 import 'package:analyzer/src/generated/sdk.dart'; | 17 import 'package:analyzer/src/generated/sdk.dart'; |
18 import 'package:analyzer/src/generated/source_io.dart'; | 18 import 'package:analyzer/src/generated/source_io.dart'; |
19 import 'package:analyzer/src/summary/summary_sdk.dart'; | 19 import 'package:analyzer/src/summary/summary_sdk.dart'; |
20 import 'package:kernel/application_root.dart'; | 20 import 'package:kernel/application_root.dart'; |
21 import 'package:package_config/discovery.dart'; | 21 import 'package:package_config/discovery.dart'; |
22 import 'package:package_config/packages.dart'; | 22 import 'package:package_config/packages.dart'; |
23 | 23 |
24 import '../ast.dart' as ast; | 24 import '../ast.dart' as ast; |
25 import '../repository.dart'; | |
26 import '../target/targets.dart' show Target; | 25 import '../target/targets.dart' show Target; |
27 import '../type_algebra.dart'; | 26 import '../type_algebra.dart'; |
28 import 'analyzer.dart'; | 27 import 'analyzer.dart'; |
29 import 'ast_from_analyzer.dart'; | 28 import 'ast_from_analyzer.dart'; |
30 | 29 |
31 /// Options passed to the Dart frontend. | 30 /// Options passed to the Dart frontend. |
32 class DartOptions { | 31 class DartOptions { |
33 /// True if user code should be loaded in strong mode. | 32 /// True if user code should be loaded in strong mode. |
34 bool strongMode; | 33 bool strongMode; |
35 | 34 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 ast.Class getCoreClassReference(String className); | 77 ast.Class getCoreClassReference(String className); |
79 ast.Constructor getCoreClassConstructorReference(String className, | 78 ast.Constructor getCoreClassConstructorReference(String className, |
80 {String constructorName, String library}); | 79 {String constructorName, String library}); |
81 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element); | 80 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element); |
82 ast.Class getSharedMixinApplicationClass( | 81 ast.Class getSharedMixinApplicationClass( |
83 ast.Library library, ast.Class supertype, ast.Class mixin); | 82 ast.Library library, ast.Class supertype, ast.Class mixin); |
84 bool get strongMode; | 83 bool get strongMode; |
85 } | 84 } |
86 | 85 |
87 class DartLoader implements ReferenceLevelLoader { | 86 class DartLoader implements ReferenceLevelLoader { |
88 final Repository repository; | 87 final ast.Program program; |
89 final ApplicationRoot applicationRoot; | 88 final ApplicationRoot applicationRoot; |
90 final Bimap<ClassElement, ast.Class> _classes = | 89 final Bimap<ClassElement, ast.Class> _classes = |
91 new Bimap<ClassElement, ast.Class>(); | 90 new Bimap<ClassElement, ast.Class>(); |
92 final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>(); | 91 final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>(); |
93 final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters = | 92 final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters = |
94 <TypeParameterElement, ast.TypeParameter>{}; | 93 <TypeParameterElement, ast.TypeParameter>{}; |
95 final Map<ast.Library, Map<String, ast.Class>> _mixinApplications = | 94 final Map<ast.Library, Map<String, ast.Class>> _mixinApplications = |
96 <ast.Library, Map<String, ast.Class>>{}; | 95 <ast.Library, Map<String, ast.Class>>{}; |
97 final AnalysisContext context; | 96 final AnalysisContext context; |
98 LibraryElement _dartCoreLibrary; | 97 LibraryElement _dartCoreLibrary; |
99 final List errors = []; | 98 final List errors = []; |
100 final List libraryElements = []; | 99 final List libraryElements = []; |
101 | 100 |
102 /// Classes that have been referenced, and must be promoted to type level | 101 /// Classes that have been referenced, and must be promoted to type level |
103 /// so as not to expose partially initialized classes. | 102 /// so as not to expose partially initialized classes. |
104 final List<ast.Class> temporaryClassWorklist = []; | 103 final List<ast.Class> temporaryClassWorklist = []; |
105 | 104 |
106 LibraryElement _libraryBeingLoaded = null; | 105 LibraryElement _libraryBeingLoaded = null; |
107 | 106 |
108 bool get strongMode => context.analysisOptions.strongMode; | 107 bool get strongMode => context.analysisOptions.strongMode; |
109 | 108 |
110 DartLoader(this.repository, DartOptions options, Packages packages, | 109 DartLoader(this.program, DartOptions options, Packages packages, |
111 {DartSdk dartSdk, AnalysisContext context}) | 110 {DartSdk dartSdk, AnalysisContext context}) |
112 : this.context = | 111 : this.context = context ?? createContext(options, packages, dartSdk: dart
Sdk), |
113 context ?? createContext(options, packages, dartSdk: dartSdk), | |
114 this.applicationRoot = options.applicationRoot; | 112 this.applicationRoot = options.applicationRoot; |
115 | 113 |
116 String getLibraryName(LibraryElement element) { | 114 String getLibraryName(LibraryElement element) { |
117 return element.name.isEmpty ? null : element.name; | 115 return element.name.isEmpty ? null : element.name; |
118 } | 116 } |
119 | 117 |
120 ast.Library getLibraryReference(LibraryElement element) { | 118 ast.Library getLibraryReference(LibraryElement element) { |
121 var uri = applicationRoot.relativeUri(element.source.uri); | 119 var uri = applicationRoot.relativeUri(element.source.uri); |
122 return repository.getLibraryReference(uri) | 120 return program.getLibraryReference(uri) |
123 ..name ??= getLibraryName(element) | 121 ..name ??= getLibraryName(element) |
124 ..fileUri = '${element.source.uri}'; | 122 ..fileUri = '${element.source.uri}'; |
125 } | 123 } |
126 | 124 |
127 void _buildTopLevelMember( | 125 void _buildTopLevelMember( |
128 ast.Member member, Element element, Declaration astNode) { | 126 ast.Member member, Element element, Declaration astNode) { |
129 assert(member.parent != null); | 127 assert(member.parent != null); |
130 new MemberBodyBuilder(this, member, element).build(astNode); | 128 new MemberBodyBuilder(this, member, element).build(astNode); |
131 } | 129 } |
132 | 130 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 var freshParameters = | 330 var freshParameters = |
333 getFreshTypeParameters(classNode.typeParameters); | 331 getFreshTypeParameters(classNode.typeParameters); |
334 var mixinClass = new ast.Class( | 332 var mixinClass = new ast.Class( |
335 name: '${classNode.name}^${mixinType.classNode.name}', | 333 name: '${classNode.name}^${mixinType.classNode.name}', |
336 isAbstract: true, | 334 isAbstract: true, |
337 typeParameters: freshParameters.freshTypeParameters, | 335 typeParameters: freshParameters.freshTypeParameters, |
338 supertype: freshParameters.substituteSuper(supertype), | 336 supertype: freshParameters.substituteSuper(supertype), |
339 mixedInType: freshParameters.substituteSuper(mixinType), | 337 mixedInType: freshParameters.substituteSuper(mixinType), |
340 fileUri: classNode.fileUri)..fileOffset = element.nameOffset; | 338 fileUri: classNode.fileUri)..fileOffset = element.nameOffset; |
341 mixinClass.level = ast.ClassLevel.Type; | 339 mixinClass.level = ast.ClassLevel.Type; |
| 340 addMixinClassToLibrary(mixinClass, classNode.enclosingLibrary); |
342 supertype = new ast.Supertype(mixinClass, | 341 supertype = new ast.Supertype(mixinClass, |
343 classNode.typeParameters.map(makeTypeParameterType).toList()); | 342 classNode.typeParameters.map(makeTypeParameterType).toList()); |
344 addMixinClassToLibrary(mixinClass, classNode.enclosingLibrary); | |
345 // This class cannot be used from anywhere else, so don't try to | 343 // This class cannot be used from anywhere else, so don't try to |
346 // generate shared mixin applications using it. | 344 // generate shared mixin applications using it. |
347 useSharedMixin = false; | 345 useSharedMixin = false; |
348 } | 346 } |
349 } | 347 } |
350 classNode.supertype = supertype; | 348 classNode.supertype = supertype; |
351 for (var implementedType in element.interfaces) { | 349 for (var implementedType in element.interfaces) { |
352 classNode.implementedTypes.add(scope.buildSupertype(implementedType)); | 350 classNode.implementedTypes.add(scope.buildSupertype(implementedType)); |
353 } | 351 } |
354 } | 352 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 } | 400 } |
403 | 401 |
404 ast.Member getMemberReference(Element element) { | 402 ast.Member getMemberReference(Element element) { |
405 assert(element != null); | 403 assert(element != null); |
406 assert(element is! Member); // Use the "base element". | 404 assert(element is! Member); // Use the "base element". |
407 return _members[element] ??= _buildMemberReference(element); | 405 return _members[element] ??= _buildMemberReference(element); |
408 } | 406 } |
409 | 407 |
410 ast.Member _buildMemberReference(Element element) { | 408 ast.Member _buildMemberReference(Element element) { |
411 assert(element != null); | 409 assert(element != null); |
412 var node = _buildOrphanedMemberReference(element); | 410 var member = _buildOrphanedMemberReference(element); |
413 // Set the parent pointer and store it in the enclosing class or library. | 411 // Set the parent pointer and store it in the enclosing class or library. |
414 // If the enclosing library is being built from the AST, do not add the | 412 // If the enclosing library is being built from the AST, do not add the |
415 // member, since the AST builder will put it in there. | 413 // member, since the AST builder will put it in there. |
416 var parent = element.enclosingElement; | 414 var parent = element.enclosingElement; |
417 if (parent is ClassElement) { | 415 if (parent is ClassElement) { |
418 var class_ = getClassReference(parent); | 416 var class_ = getClassReference(parent); |
419 node.parent = class_; | 417 member.parent = class_; |
420 if (!isLibraryBeingLoaded(element.library)) { | 418 if (!isLibraryBeingLoaded(element.library)) { |
421 class_.addMember(node); | 419 class_.addMember(member); |
422 } | 420 } |
| 421 class_.canonicalName.getChildFromMember(member).bindTo(member); |
423 } else { | 422 } else { |
424 var library = getLibraryReference(element.library); | 423 var library = getLibraryReference(element.library); |
425 node.parent = library; | 424 member.parent = library; |
426 if (!isLibraryBeingLoaded(element.library)) { | 425 if (!isLibraryBeingLoaded(element.library)) { |
427 library.addMember(node); | 426 library.addMember(member); |
428 } | 427 } |
| 428 library.canonicalName.getChildFromMember(member).bindTo(member); |
429 } | 429 } |
430 return node; | 430 return member; |
431 } | 431 } |
432 | 432 |
433 ast.Member _buildOrphanedMemberReference(Element element) { | 433 ast.Member _buildOrphanedMemberReference(Element element) { |
434 assert(element != null); | 434 assert(element != null); |
435 ClassElement classElement = element.enclosingElement is ClassElement | 435 ClassElement classElement = element.enclosingElement is ClassElement |
436 ? element.enclosingElement | 436 ? element.enclosingElement |
437 : null; | 437 : null; |
438 TypeScope scope = classElement != null | 438 TypeScope scope = classElement != null |
439 ? new ClassScope(this, getLibraryReference(element.library)) | 439 ? new ClassScope(this, getLibraryReference(element.library)) |
440 : new TypeScope(this); | 440 : new TypeScope(this); |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 for (var uri in target.extraRequiredLibraries) { | 651 for (var uri in target.extraRequiredLibraries) { |
652 var library = _findLibraryElement(uri); | 652 var library = _findLibraryElement(uri); |
653 if (library == null) { | 653 if (library == null) { |
654 errors.add('Could not find required library $uri'); | 654 errors.add('Could not find required library $uri'); |
655 continue; | 655 continue; |
656 } | 656 } |
657 ensureLibraryIsLoaded(getLibraryReference(library)); | 657 ensureLibraryIsLoaded(getLibraryReference(library)); |
658 } | 658 } |
659 } | 659 } |
660 } | 660 } |
661 for (int i = 0; i < repository.libraries.length; ++i) { | 661 for (int i = 0; i < program.libraries.length; ++i) { |
662 var library = repository.libraries[i]; | 662 var library = program.libraries[i]; |
663 if (compileSdk || library.importUri.scheme != 'dart') { | 663 if (compileSdk || library.importUri.scheme != 'dart') { |
664 ensureLibraryIsLoaded(library); | 664 ensureLibraryIsLoaded(library); |
665 } | 665 } |
666 } | 666 } |
667 } | 667 } |
668 | 668 |
669 /// Builds a list of sources that have been loaded. | 669 /// Builds a list of sources that have been loaded. |
670 /// | 670 /// |
671 /// This operation may be expensive and should only be used for diagnostics. | 671 /// This operation may be expensive and should only be used for diagnostics. |
672 List<String> getLoadedFileNames() { | 672 List<String> getLoadedFileNames() { |
673 var list = <String>[]; | 673 var list = <String>[]; |
674 for (var library in repository.libraries) { | 674 for (var library in program.libraries) { |
675 LibraryElement element = context.computeLibraryElement(context | 675 LibraryElement element = context.computeLibraryElement(context |
676 .sourceFactory | 676 .sourceFactory |
677 .forUri2(applicationRoot.absoluteUri(library.importUri))); | 677 .forUri2(applicationRoot.absoluteUri(library.importUri))); |
678 for (var unit in element.units) { | 678 for (var unit in element.units) { |
679 list.add(unit.source.fullName); | 679 list.add(unit.source.fullName); |
680 } | 680 } |
681 } | 681 } |
682 return list; | 682 return list; |
683 } | 683 } |
684 | 684 |
(...skipping 24 matching lines...) Expand all Loading... |
709 new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw( | 709 new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw( |
710 new ast.StringLiteral('Program has no main method')))), | 710 new ast.StringLiteral('Program has no main method')))), |
711 isStatic: true) | 711 isStatic: true) |
712 ..fileUri = library.fileUri; | 712 ..fileUri = library.fileUri; |
713 library.addMember(main); | 713 library.addMember(main); |
714 return main; | 714 return main; |
715 } | 715 } |
716 | 716 |
717 ast.Program loadProgram(Uri mainLibrary, {Target target, bool compileSdk}) { | 717 ast.Program loadProgram(Uri mainLibrary, {Target target, bool compileSdk}) { |
718 Uri uri = applicationRoot.relativeUri(mainLibrary); | 718 Uri uri = applicationRoot.relativeUri(mainLibrary); |
719 ast.Library library = repository.getLibraryReference(uri); | 719 ast.Library library = program.getLibraryReference(uri); |
720 ensureLibraryIsLoaded(library); | 720 ensureLibraryIsLoaded(library); |
721 var mainMethod = _getMainMethod(mainLibrary); | 721 var mainMethod = _getMainMethod(mainLibrary); |
722 loadEverything(target: target, compileSdk: compileSdk); | 722 loadEverything(target: target, compileSdk: compileSdk); |
723 var program = new ast.Program(repository.libraries); | |
724 if (mainMethod == null) { | 723 if (mainMethod == null) { |
725 mainMethod = _makeMissingMainMethod(library); | 724 mainMethod = _makeMissingMainMethod(library); |
726 } | 725 } |
727 program.mainMethod = mainMethod; | 726 program.mainMethod = mainMethod; |
728 for (LibraryElement libraryElement in libraryElements) { | 727 for (LibraryElement libraryElement in libraryElements) { |
729 for (CompilationUnitElement compilationUnitElement | 728 for (CompilationUnitElement compilationUnitElement |
730 in libraryElement.units) { | 729 in libraryElement.units) { |
731 var source = compilationUnitElement.source; | 730 var source = compilationUnitElement.source; |
732 LineInfo lineInfo = context.computeLineInfo(source); | 731 LineInfo lineInfo = context.computeLineInfo(source); |
733 String sourceCode; | 732 String sourceCode; |
734 try { | 733 try { |
735 sourceCode = context.getContents(source).data; | 734 sourceCode = context.getContents(source).data; |
736 } catch (e) { | 735 } catch (e) { |
737 // The source's contents could not be accessed. | 736 // The source's contents could not be accessed. |
738 sourceCode = ''; | 737 sourceCode = ''; |
739 } | 738 } |
740 program.uriToSource['${source.uri}'] = | 739 program.uriToSource['${source.uri}'] = |
741 new ast.Source(lineInfo.lineStarts, sourceCode); | 740 new ast.Source(lineInfo.lineStarts, sourceCode); |
742 } | 741 } |
743 } | 742 } |
744 return program; | 743 return program; |
745 } | 744 } |
746 | 745 |
747 ast.Library loadLibrary(Uri uri) { | 746 ast.Library loadLibrary(Uri uri) { |
748 ast.Library library = | 747 ast.Library library = |
749 repository.getLibraryReference(applicationRoot.relativeUri(uri)); | 748 program.getLibraryReference(applicationRoot.relativeUri(uri)); |
750 ensureLibraryIsLoaded(library); | 749 ensureLibraryIsLoaded(library); |
751 return library; | 750 return library; |
752 } | 751 } |
753 } | 752 } |
754 | 753 |
755 class Bimap<K, V> { | 754 class Bimap<K, V> { |
756 final Map<K, V> nodeMap = <K, V>{}; | 755 final Map<K, V> nodeMap = <K, V>{}; |
757 final Map<V, K> inverse = <V, K>{}; | 756 final Map<V, K> inverse = <V, K>{}; |
758 | 757 |
759 bool containsKey(K key) => nodeMap.containsKey(key); | 758 bool containsKey(K key) => nodeMap.containsKey(key); |
(...skipping 10 matching lines...) Expand all Loading... |
770 /// Creates [DartLoader]s for a given configuration, while reusing the | 769 /// Creates [DartLoader]s for a given configuration, while reusing the |
771 /// [DartSdk] and [Packages] object if possible. | 770 /// [DartSdk] and [Packages] object if possible. |
772 class DartLoaderBatch { | 771 class DartLoaderBatch { |
773 Packages packages; | 772 Packages packages; |
774 DartSdk dartSdk; | 773 DartSdk dartSdk; |
775 | 774 |
776 String lastSdk; | 775 String lastSdk; |
777 String lastPackagePath; | 776 String lastPackagePath; |
778 bool lastStrongMode; | 777 bool lastStrongMode; |
779 | 778 |
780 Future<DartLoader> getLoader(Repository repository, DartOptions options, | 779 Future<DartLoader> getLoader(ast.Program program, DartOptions options, |
781 {String packageDiscoveryPath}) async { | 780 {String packageDiscoveryPath}) async { |
782 if (dartSdk == null || | 781 if (dartSdk == null || |
783 lastSdk != options.sdk || | 782 lastSdk != options.sdk || |
784 lastStrongMode != options.strongMode) { | 783 lastStrongMode != options.strongMode) { |
785 lastSdk = options.sdk; | 784 lastSdk = options.sdk; |
786 lastStrongMode = options.strongMode; | 785 lastStrongMode = options.strongMode; |
787 dartSdk = createDartSdk(options.sdk, strongMode: options.strongModeSdk); | 786 dartSdk = createDartSdk(options.sdk, strongMode: options.strongModeSdk); |
788 } | 787 } |
789 if (packages == null || | 788 if (packages == null || |
790 lastPackagePath != options.packagePath || | 789 lastPackagePath != options.packagePath || |
791 packageDiscoveryPath != null) { | 790 packageDiscoveryPath != null) { |
792 lastPackagePath = options.packagePath; | 791 lastPackagePath = options.packagePath; |
793 packages = await createPackages(options.packagePath, | 792 packages = await createPackages(options.packagePath, |
794 discoveryPath: packageDiscoveryPath); | 793 discoveryPath: packageDiscoveryPath); |
795 } | 794 } |
796 return new DartLoader(repository, options, packages, dartSdk: dartSdk); | 795 return new DartLoader(program, options, packages, dartSdk: dartSdk); |
797 } | 796 } |
798 } | 797 } |
799 | 798 |
800 Future<Packages> createPackages(String packagePath, | 799 Future<Packages> createPackages(String packagePath, |
801 {String discoveryPath}) async { | 800 {String discoveryPath}) async { |
802 if (packagePath != null) { | 801 if (packagePath != null) { |
803 var absolutePath = new io.File(packagePath).absolute.path; | 802 var absolutePath = new io.File(packagePath).absolute.path; |
804 if (await new io.Directory(packagePath).exists()) { | 803 if (await new io.Directory(packagePath).exists()) { |
805 return getPackagesDirectory(new Uri.file(absolutePath)); | 804 return getPackagesDirectory(new Uri.file(absolutePath)); |
806 } else if (await new io.File(packagePath).exists()) { | 805 } else if (await new io.File(packagePath).exists()) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() | 897 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() |
899 ..sourceFactory = new SourceFactory(resolvers) | 898 ..sourceFactory = new SourceFactory(resolvers) |
900 ..analysisOptions = createAnalysisOptions(options.strongMode); | 899 ..analysisOptions = createAnalysisOptions(options.strongMode); |
901 | 900 |
902 options.declaredVariables.forEach((String name, String value) { | 901 options.declaredVariables.forEach((String name, String value) { |
903 context.declaredVariables.define(name, value); | 902 context.declaredVariables.define(name, value); |
904 }); | 903 }); |
905 | 904 |
906 return context; | 905 return context; |
907 } | 906 } |
OLD | NEW |