| 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:kernel/application_root.dart'; |
| 19 import 'package:package_config/discovery.dart'; | 20 import 'package:package_config/discovery.dart'; |
| 20 import 'package:package_config/packages.dart'; | 21 import 'package:package_config/packages.dart'; |
| 21 | 22 |
| 22 import '../ast.dart' as ast; | 23 import '../ast.dart' as ast; |
| 23 import '../repository.dart'; | 24 import '../repository.dart'; |
| 24 import '../target/targets.dart' show Target; | 25 import '../target/targets.dart' show Target; |
| 25 import '../type_algebra.dart'; | 26 import '../type_algebra.dart'; |
| 26 import 'analyzer.dart'; | 27 import 'analyzer.dart'; |
| 27 import 'ast_from_analyzer.dart'; | 28 import 'ast_from_analyzer.dart'; |
| 28 | 29 |
| 29 /// Options passed to the Dart frontend. | 30 /// Options passed to the Dart frontend. |
| 30 class DartOptions { | 31 class DartOptions { |
| 31 /// True if user code should be loaded in strong mode. | 32 /// True if user code should be loaded in strong mode. |
| 32 bool strongMode; | 33 bool strongMode; |
| 33 | 34 |
| 34 /// True if the Dart SDK should be loaded in strong mode. | 35 /// True if the Dart SDK should be loaded in strong mode. |
| 35 bool strongModeSdk; | 36 bool strongModeSdk; |
| 36 String sdk; | 37 String sdk; |
| 37 String packagePath; | 38 String packagePath; |
| 39 ApplicationRoot applicationRoot; |
| 38 Map<Uri, Uri> customUriMappings; | 40 Map<Uri, Uri> customUriMappings; |
| 39 Map<String, String> declaredVariables; | 41 Map<String, String> declaredVariables; |
| 40 | 42 |
| 41 DartOptions( | 43 DartOptions( |
| 42 {bool strongMode: false, | 44 {bool strongMode: false, |
| 43 bool strongModeSdk, | 45 bool strongModeSdk, |
| 44 this.sdk, | 46 this.sdk, |
| 45 this.packagePath, | 47 this.packagePath, |
| 48 ApplicationRoot applicationRoot, |
| 46 Map<Uri, Uri> customUriMappings, | 49 Map<Uri, Uri> customUriMappings, |
| 47 Map<String, String> declaredVariables}) | 50 Map<String, String> declaredVariables}) |
| 48 : this.customUriMappings = customUriMappings ?? <Uri, Uri>{}, | 51 : this.customUriMappings = customUriMappings ?? <Uri, Uri>{}, |
| 49 this.declaredVariables = declaredVariables ?? <String, String>{}, | 52 this.declaredVariables = declaredVariables ?? <String, String>{}, |
| 50 this.strongMode = strongMode, | 53 this.strongMode = strongMode, |
| 51 this.strongModeSdk = strongModeSdk ?? strongMode; | 54 this.strongModeSdk = strongModeSdk ?? strongMode, |
| 55 this.applicationRoot = applicationRoot ?? new ApplicationRoot.none(); |
| 52 } | 56 } |
| 53 | 57 |
| 54 abstract class ReferenceLevelLoader { | 58 abstract class ReferenceLevelLoader { |
| 55 ast.Library getLibraryReference(LibraryElement element); | 59 ast.Library getLibraryReference(LibraryElement element); |
| 56 ast.Class getClassReference(ClassElement element); | 60 ast.Class getClassReference(ClassElement element); |
| 57 ast.Member getMemberReference(Element element); | 61 ast.Member getMemberReference(Element element); |
| 58 ast.Class getRootClassReference(); | 62 ast.Class getRootClassReference(); |
| 59 ast.Constructor getRootClassConstructorReference(); | 63 ast.Constructor getRootClassConstructorReference(); |
| 60 ast.Class getCoreClassReference(String className); | 64 ast.Class getCoreClassReference(String className); |
| 61 ast.Constructor getCoreClassConstructorReference(String className, | 65 ast.Constructor getCoreClassConstructorReference(String className, |
| 62 {String constructorName, String library}); | 66 {String constructorName, String library}); |
| 63 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element); | 67 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element); |
| 64 ast.Class getSharedMixinApplicationClass( | 68 ast.Class getSharedMixinApplicationClass( |
| 65 ast.Library library, ast.Class supertype, ast.Class mixin); | 69 ast.Library library, ast.Class supertype, ast.Class mixin); |
| 66 bool get strongMode; | 70 bool get strongMode; |
| 67 } | 71 } |
| 68 | 72 |
| 69 class DartLoader implements ReferenceLevelLoader { | 73 class DartLoader implements ReferenceLevelLoader { |
| 70 final Repository repository; | 74 final Repository repository; |
| 75 final ApplicationRoot applicationRoot; |
| 71 final Bimap<ClassElement, ast.Class> _classes = | 76 final Bimap<ClassElement, ast.Class> _classes = |
| 72 new Bimap<ClassElement, ast.Class>(); | 77 new Bimap<ClassElement, ast.Class>(); |
| 73 final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>(); | 78 final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>(); |
| 74 final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters = | 79 final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters = |
| 75 <TypeParameterElement, ast.TypeParameter>{}; | 80 <TypeParameterElement, ast.TypeParameter>{}; |
| 76 final Map<ast.Library, Map<String, ast.Class>> _mixinApplications = | 81 final Map<ast.Library, Map<String, ast.Class>> _mixinApplications = |
| 77 <ast.Library, Map<String, ast.Class>>{}; | 82 <ast.Library, Map<String, ast.Class>>{}; |
| 78 final AnalysisContext context; | 83 final AnalysisContext context; |
| 79 LibraryElement _dartCoreLibrary; | 84 LibraryElement _dartCoreLibrary; |
| 80 final List errors = []; | 85 final List errors = []; |
| 81 final List libraryElements = []; | 86 final List libraryElements = []; |
| 82 | 87 |
| 83 /// Classes that have been referenced, and must be promoted to type level | 88 /// Classes that have been referenced, and must be promoted to type level |
| 84 /// so as not to expose partially initialized classes. | 89 /// so as not to expose partially initialized classes. |
| 85 final List<ast.Class> temporaryClassWorklist = []; | 90 final List<ast.Class> temporaryClassWorklist = []; |
| 86 | 91 |
| 87 LibraryElement _libraryBeingLoaded = null; | 92 LibraryElement _libraryBeingLoaded = null; |
| 88 | 93 |
| 89 bool get strongMode => context.analysisOptions.strongMode; | 94 bool get strongMode => context.analysisOptions.strongMode; |
| 90 | 95 |
| 91 DartLoader(this.repository, DartOptions options, Packages packages, | 96 DartLoader(this.repository, DartOptions options, Packages packages, |
| 92 {DartSdk dartSdk}) | 97 {DartSdk dartSdk}) |
| 93 : this.context = createContext(options, packages, dartSdk: dartSdk); | 98 : this.context = createContext(options, packages, dartSdk: dartSdk), |
| 94 | 99 this.applicationRoot = options.applicationRoot; |
| 95 LibraryElement getLibraryElement(ast.Library node) { | |
| 96 return context | |
| 97 .getLibraryElement(context.sourceFactory.forUri2(node.importUri)); | |
| 98 } | |
| 99 | 100 |
| 100 String getLibraryName(LibraryElement element) { | 101 String getLibraryName(LibraryElement element) { |
| 101 return element.name.isEmpty ? null : element.name; | 102 return element.name.isEmpty ? null : element.name; |
| 102 } | 103 } |
| 103 | 104 |
| 104 ast.Library getLibraryReference(LibraryElement element) { | 105 ast.Library getLibraryReference(LibraryElement element) { |
| 105 return repository.getLibraryReference(element.source.uri) | 106 var uri = applicationRoot.relativeUri(element.source.uri); |
| 107 return repository.getLibraryReference(uri) |
| 106 ..name ??= getLibraryName(element) | 108 ..name ??= getLibraryName(element) |
| 107 ..fileUri = "file://${element.source.fullName}"; | 109 ..fileUri = "file://${element.source.fullName}"; |
| 108 } | 110 } |
| 109 | 111 |
| 110 void _buildTopLevelMember(ast.Member member, Element element) { | 112 void _buildTopLevelMember(ast.Member member, Element element) { |
| 111 var astNode = element.computeNode(); | 113 var astNode = element.computeNode(); |
| 112 assert(member.parent != null); | 114 assert(member.parent != null); |
| 113 new MemberBodyBuilder(this, member, element).build(astNode); | 115 new MemberBodyBuilder(this, member, element).build(astNode); |
| 114 } | 116 } |
| 115 | 117 |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 AnalysisError error, String filename, LineInfo lines) { | 574 AnalysisError error, String filename, LineInfo lines) { |
| 573 var location = lines.getLocation(error.offset); | 575 var location = lines.getLocation(error.offset); |
| 574 return '[error] ${error.message} ($filename, ' | 576 return '[error] ${error.message} ($filename, ' |
| 575 'line ${location.lineNumber}, ' | 577 'line ${location.lineNumber}, ' |
| 576 'col ${location.columnNumber})'; | 578 'col ${location.columnNumber})'; |
| 577 } | 579 } |
| 578 | 580 |
| 579 void ensureLibraryIsLoaded(ast.Library node) { | 581 void ensureLibraryIsLoaded(ast.Library node) { |
| 580 if (!node.isExternal) return; | 582 if (!node.isExternal) return; |
| 581 node.isExternal = false; | 583 node.isExternal = false; |
| 582 var source = context.sourceFactory.forUri2(node.importUri); | 584 var source = context.sourceFactory |
| 585 .forUri2(applicationRoot.absoluteUri(node.importUri)); |
| 583 assert(source != null); | 586 assert(source != null); |
| 584 var element = context.computeLibraryElement(source); | 587 var element = context.computeLibraryElement(source); |
| 585 context.resolveCompilationUnit(source, element); | 588 context.resolveCompilationUnit(source, element); |
| 586 _buildLibraryBody(element, node); | 589 _buildLibraryBody(element, node); |
| 587 if (node.importUri.scheme != 'dart') { | 590 if (node.importUri.scheme != 'dart') { |
| 588 for (var unit in element.units) { | 591 for (var unit in element.units) { |
| 589 LineInfo lines; | 592 LineInfo lines; |
| 590 for (var error in context.computeErrors(unit.source)) { | 593 for (var error in context.computeErrors(unit.source)) { |
| 591 if (error.errorCode is CompileTimeErrorCode || | 594 if (error.errorCode is CompileTimeErrorCode || |
| 592 error.errorCode is ParserErrorCode || | 595 error.errorCode is ParserErrorCode || |
| (...skipping 23 matching lines...) Expand all Loading... |
| 616 ensureLibraryIsLoaded(repository.libraries[i]); | 619 ensureLibraryIsLoaded(repository.libraries[i]); |
| 617 } | 620 } |
| 618 } | 621 } |
| 619 | 622 |
| 620 /// Builds a list of sources that have been loaded. | 623 /// Builds a list of sources that have been loaded. |
| 621 /// | 624 /// |
| 622 /// This operation may be expensive and should only be used for diagnostics. | 625 /// This operation may be expensive and should only be used for diagnostics. |
| 623 List<String> getLoadedFileNames() { | 626 List<String> getLoadedFileNames() { |
| 624 var list = <String>[]; | 627 var list = <String>[]; |
| 625 for (var library in repository.libraries) { | 628 for (var library in repository.libraries) { |
| 626 LibraryElement element = context.computeLibraryElement( | 629 LibraryElement element = context.computeLibraryElement(context |
| 627 context.sourceFactory.forUri2(library.importUri)); | 630 .sourceFactory |
| 631 .forUri2(applicationRoot.absoluteUri(library.importUri))); |
| 628 for (var unit in element.units) { | 632 for (var unit in element.units) { |
| 629 list.add(unit.source.fullName); | 633 list.add(unit.source.fullName); |
| 630 } | 634 } |
| 631 } | 635 } |
| 632 return list; | 636 return list; |
| 633 } | 637 } |
| 634 | 638 |
| 635 void _iterateWorklist() { | 639 void _iterateWorklist() { |
| 636 while (temporaryClassWorklist.isNotEmpty) { | 640 while (temporaryClassWorklist.isNotEmpty) { |
| 637 var element = temporaryClassWorklist.removeLast(); | 641 var element = temporaryClassWorklist.removeLast(); |
| 638 promoteToTypeLevel(element); | 642 promoteToTypeLevel(element); |
| 639 } | 643 } |
| 640 } | 644 } |
| 641 | 645 |
| 642 ast.Program loadProgram(String mainLibrary, {Target target}) { | 646 ast.Program loadProgram(Uri mainLibrary, {Target target}) { |
| 643 ast.Library library = repository.getLibrary(mainLibrary); | 647 ast.Library library = repository |
| 648 .getLibraryReference(applicationRoot.relativeUri(mainLibrary)); |
| 644 ensureLibraryIsLoaded(library); | 649 ensureLibraryIsLoaded(library); |
| 645 loadEverything(target: target); | 650 loadEverything(target: target); |
| 646 var program = new ast.Program(repository.libraries); | 651 var program = new ast.Program(repository.libraries); |
| 647 program.mainMethod = library.procedures.firstWhere( | 652 program.mainMethod = library.procedures.firstWhere( |
| 648 (member) => member.name?.name == 'main', | 653 (member) => member.name?.name == 'main', |
| 649 orElse: () => null); | 654 orElse: () => null); |
| 650 for (LibraryElement libraryElement in libraryElements) { | 655 for (LibraryElement libraryElement in libraryElements) { |
| 651 for (CompilationUnitElement compilationUnitElement | 656 for (CompilationUnitElement compilationUnitElement |
| 652 in libraryElement.units) { | 657 in libraryElement.units) { |
| 653 // TODO(jensj): Get this another way? | 658 // TODO(jensj): Get this another way? |
| 654 LineInfo lineInfo = compilationUnitElement.computeNode().lineInfo; | 659 LineInfo lineInfo = compilationUnitElement.computeNode().lineInfo; |
| 655 program.uriToLineStarts[ | 660 program.uriToLineStarts[ |
| 656 "file://${compilationUnitElement.source.source.fullName}"] = | 661 "file://${compilationUnitElement.source.source.fullName}"] = |
| 657 new List<int>.generate(lineInfo.lineCount, lineInfo.getOffsetOfLine, | 662 new List<int>.generate(lineInfo.lineCount, lineInfo.getOffsetOfLine, |
| 658 growable: false); | 663 growable: false); |
| 659 } | 664 } |
| 660 } | 665 } |
| 661 return program; | 666 return program; |
| 662 } | 667 } |
| 663 | 668 |
| 664 ast.Library loadLibrary(String mainLibrary) { | 669 ast.Library loadLibrary(Uri uri) { |
| 665 ast.Library library = repository.getLibrary(mainLibrary); | 670 ast.Library library = |
| 671 repository.getLibraryReference(applicationRoot.relativeUri(uri)); |
| 666 ensureLibraryIsLoaded(library); | 672 ensureLibraryIsLoaded(library); |
| 667 return library; | 673 return library; |
| 668 } | 674 } |
| 669 } | 675 } |
| 670 | 676 |
| 671 class Bimap<K, V> { | 677 class Bimap<K, V> { |
| 672 final Map<K, V> nodeMap = <K, V>{}; | 678 final Map<K, V> nodeMap = <K, V>{}; |
| 673 final Map<V, K> inverse = <V, K>{}; | 679 final Map<V, K> inverse = <V, K>{}; |
| 674 | 680 |
| 675 bool containsKey(K key) => nodeMap.containsKey(key); | 681 bool containsKey(K key) => nodeMap.containsKey(key); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() | 815 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() |
| 810 ..sourceFactory = new SourceFactory(resolvers) | 816 ..sourceFactory = new SourceFactory(resolvers) |
| 811 ..analysisOptions = createAnalysisOptions(options.strongMode); | 817 ..analysisOptions = createAnalysisOptions(options.strongMode); |
| 812 | 818 |
| 813 options.declaredVariables.forEach((String name, String value) { | 819 options.declaredVariables.forEach((String name, String value) { |
| 814 context.declaredVariables.define(name, value); | 820 context.declaredVariables.define(name, value); |
| 815 }); | 821 }); |
| 816 | 822 |
| 817 return context; | 823 return context; |
| 818 } | 824 } |
| OLD | NEW |