| 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'; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 <ast.Library, Map<String, ast.Class>>{}; | 99 <ast.Library, Map<String, ast.Class>>{}; |
| 100 final AnalysisContext context; | 100 final AnalysisContext context; |
| 101 LibraryElement _dartCoreLibrary; | 101 LibraryElement _dartCoreLibrary; |
| 102 final List errors = []; | 102 final List errors = []; |
| 103 final List libraryElements = []; | 103 final List libraryElements = []; |
| 104 | 104 |
| 105 /// Classes that have been referenced, and must be promoted to type level | 105 /// Classes that have been referenced, and must be promoted to type level |
| 106 /// so as not to expose partially initialized classes. | 106 /// so as not to expose partially initialized classes. |
| 107 final List<ast.Class> temporaryClassWorklist = []; | 107 final List<ast.Class> temporaryClassWorklist = []; |
| 108 | 108 |
| 109 final Map<LibraryElement, List<ClassElement>> mixinLibraryWorklist = {}; |
| 110 |
| 109 final bool ignoreRedirectingFactories; | 111 final bool ignoreRedirectingFactories; |
| 110 | 112 |
| 111 LibraryElement _libraryBeingLoaded = null; | 113 LibraryElement _libraryBeingLoaded = null; |
| 112 | 114 |
| 113 bool get strongMode => context.analysisOptions.strongMode; | 115 bool get strongMode => context.analysisOptions.strongMode; |
| 114 | 116 |
| 115 DartLoader(this.repository, DartOptions options, Packages packages, | 117 DartLoader(this.repository, DartOptions options, Packages packages, |
| 116 {DartSdk dartSdk, AnalysisContext context, | 118 {DartSdk dartSdk, |
| 117 this.ignoreRedirectingFactories: true}) | 119 AnalysisContext context, |
| 120 this.ignoreRedirectingFactories: true}) |
| 118 : this.context = | 121 : this.context = |
| 119 context ?? createContext(options, packages, dartSdk: dartSdk), | 122 context ?? createContext(options, packages, dartSdk: dartSdk), |
| 120 this.applicationRoot = options.applicationRoot; | 123 this.applicationRoot = options.applicationRoot; |
| 121 | 124 |
| 122 String getLibraryName(LibraryElement element) { | 125 String getLibraryName(LibraryElement element) { |
| 123 return element.name.isEmpty ? null : element.name; | 126 return element.name.isEmpty ? null : element.name; |
| 124 } | 127 } |
| 125 | 128 |
| 126 ast.Library getLibraryReference(LibraryElement element) { | 129 ast.Library getLibraryReference(LibraryElement element) { |
| 127 var uri = applicationRoot.relativeUri(element.source.uri); | 130 var uri = applicationRoot.relativeUri(element.source.uri); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 loadField(declaration); | 195 loadField(declaration); |
| 193 } else if (declaration is FunctionTypeAlias) { | 196 } else if (declaration is FunctionTypeAlias) { |
| 194 // Nothing to do. Typedefs are handled lazily while constructing type | 197 // Nothing to do. Typedefs are handled lazily while constructing type |
| 195 // references. | 198 // references. |
| 196 } else { | 199 } else { |
| 197 throw "unexpected node: ${declaration.runtimeType} $declaration"; | 200 throw "unexpected node: ${declaration.runtimeType} $declaration"; |
| 198 } | 201 } |
| 199 } | 202 } |
| 200 } | 203 } |
| 201 libraryElements.add(element); | 204 libraryElements.add(element); |
| 202 _iterateWorklist(); | 205 _iterateTemporaryClassWorklist(); |
| 203 // Ensure everything is stored in the original declaration order. | 206 // Ensure everything is stored in the original declaration order. |
| 204 library.classes | 207 library.classes |
| 205 ..clear() | 208 ..clear() |
| 206 ..addAll(classes) | 209 ..addAll(classes) |
| 207 ..addAll(_mixinApplications[library]?.values ?? const []); | 210 ..addAll(_mixinApplications[library]?.values ?? const []); |
| 208 library.fields | 211 library.fields |
| 209 ..clear() | 212 ..clear() |
| 210 ..addAll(fields); | 213 ..addAll(fields); |
| 211 library.procedures | 214 library.procedures |
| 212 ..clear() | 215 ..clear() |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 if (!method.isStatic && !method.isSynthetic) { | 384 if (!method.isStatic && !method.isSynthetic) { |
| 382 getMemberReference(method); | 385 getMemberReference(method); |
| 383 } | 386 } |
| 384 } | 387 } |
| 385 } | 388 } |
| 386 for (var supertype in classNode.supers) { | 389 for (var supertype in classNode.supers) { |
| 387 promoteToHierarchyLevel(supertype.classNode); | 390 promoteToHierarchyLevel(supertype.classNode); |
| 388 } | 391 } |
| 389 } | 392 } |
| 390 | 393 |
| 394 void promoteToMixinLevel(ast.Class classNode, ClassElement element, |
| 395 NamedCompilationUnitMember astNode) { |
| 396 if (classNode.level.index >= ast.ClassLevel.Mixin.index) return; |
| 397 promoteToHierarchyLevel(classNode); |
| 398 classNode.level = ast.ClassLevel.Mixin; |
| 399 // Clear out the member references that were put in the class. |
| 400 // The AST builder will load them all put back in the right order. |
| 401 classNode..fields.clear()..procedures.clear()..constructors.clear(); |
| 402 new ClassBodyBuilder(this, classNode, element).build(astNode); |
| 403 |
| 404 // Ensure mixed-in classes are available. |
| 405 for (var mixin in element.mixins) { |
| 406 _ensureMixinBecomesLoaded(mixin.element); |
| 407 } |
| 408 } |
| 409 |
| 410 /// Ensures that [element] eventually becomes loaded at least at mixin level. |
| 411 void _ensureMixinBecomesLoaded(ClassElement element) { |
| 412 if (isLibraryBeingLoaded(element.library)) { |
| 413 return; |
| 414 } |
| 415 var class_ = getClassReference(element); |
| 416 if (class_.level.index >= ast.ClassLevel.Mixin.index) { |
| 417 return; |
| 418 } |
| 419 var list = mixinLibraryWorklist[element.library] ??= <ClassElement>[]; |
| 420 list.add(element); |
| 421 } |
| 422 |
| 391 void promoteToBodyLevel(ast.Class classNode, ClassElement element, | 423 void promoteToBodyLevel(ast.Class classNode, ClassElement element, |
| 392 NamedCompilationUnitMember astNode) { | 424 NamedCompilationUnitMember astNode) { |
| 393 if (classNode.level == ast.ClassLevel.Body) return; | 425 if (classNode.level == ast.ClassLevel.Body) return; |
| 394 promoteToHierarchyLevel(classNode); | 426 promoteToMixinLevel(classNode, element, astNode); |
| 395 classNode.level = ast.ClassLevel.Body; | 427 classNode.level = ast.ClassLevel.Body; |
| 396 // Clear out the member references that were put in the class. | 428 // This frontend delivers the same contents for classes at body and mixin |
| 397 // The AST builder will load them all put back in the right order. | 429 // levels, even though as specified, the mixin level does not require all |
| 398 classNode..fields.clear()..procedures.clear()..constructors.clear(); | 430 // the static members to be present. So no additional work is needed. |
| 399 new ClassBodyBuilder(this, classNode, element).build(astNode); | |
| 400 } | 431 } |
| 401 | 432 |
| 402 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) { | 433 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) { |
| 403 return _classTypeParameters[element]; | 434 return _classTypeParameters[element]; |
| 404 } | 435 } |
| 405 | 436 |
| 406 Element getMemberElement(ast.Member node) { | 437 Element getMemberElement(ast.Member node) { |
| 407 return _members.inverse[node]; | 438 return _members.inverse[node]; |
| 408 } | 439 } |
| 409 | 440 |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 | 641 |
| 611 String formatErrorMessage( | 642 String formatErrorMessage( |
| 612 AnalysisError error, String filename, LineInfo lines) { | 643 AnalysisError error, String filename, LineInfo lines) { |
| 613 var location = lines.getLocation(error.offset); | 644 var location = lines.getLocation(error.offset); |
| 614 return '[error] ${error.message} ($filename, ' | 645 return '[error] ${error.message} ($filename, ' |
| 615 'line ${location.lineNumber}, ' | 646 'line ${location.lineNumber}, ' |
| 616 'col ${location.columnNumber})'; | 647 'col ${location.columnNumber})'; |
| 617 } | 648 } |
| 618 | 649 |
| 619 void ensureLibraryIsLoaded(ast.Library node) { | 650 void ensureLibraryIsLoaded(ast.Library node) { |
| 651 _ensureLibraryIsLoaded(node); |
| 652 _iterateMixinLibraryWorklist(); |
| 653 } |
| 654 |
| 655 void _ensureLibraryIsLoaded(ast.Library node) { |
| 620 if (!node.isExternal) return; | 656 if (!node.isExternal) return; |
| 621 node.isExternal = false; | 657 node.isExternal = false; |
| 622 var source = context.sourceFactory | 658 var source = context.sourceFactory |
| 623 .forUri2(applicationRoot.absoluteUri(node.importUri)); | 659 .forUri2(applicationRoot.absoluteUri(node.importUri)); |
| 624 assert(source != null); | 660 assert(source != null); |
| 625 var element = context.computeLibraryElement(source); | 661 var element = context.computeLibraryElement(source); |
| 626 var units = <CompilationUnit>[]; | 662 var units = <CompilationUnit>[]; |
| 627 bool reportErrors = node.importUri.scheme != 'dart'; | 663 bool reportErrors = node.importUri.scheme != 'dart'; |
| 628 var tree = context.resolveCompilationUnit(source, element); | 664 var tree = context.resolveCompilationUnit(source, element); |
| 629 units.add(tree); | 665 units.add(tree); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 642 if (error.errorCode is CompileTimeErrorCode || | 678 if (error.errorCode is CompileTimeErrorCode || |
| 643 error.errorCode is ParserErrorCode || | 679 error.errorCode is ParserErrorCode || |
| 644 error.errorCode is ScannerErrorCode || | 680 error.errorCode is ScannerErrorCode || |
| 645 error.errorCode is StrongModeCode) { | 681 error.errorCode is StrongModeCode) { |
| 646 lines ??= context.computeLineInfo(source); | 682 lines ??= context.computeLineInfo(source); |
| 647 errors.add(formatErrorMessage(error, source.shortName, lines)); | 683 errors.add(formatErrorMessage(error, source.shortName, lines)); |
| 648 } | 684 } |
| 649 } | 685 } |
| 650 } | 686 } |
| 651 | 687 |
| 688 void loadSdkInterface(ast.Program program, Target target) { |
| 689 var requiredSdkMembers = target.requiredSdkClasses; |
| 690 for (var libraryUri in requiredSdkMembers.keys) { |
| 691 var source = context.sourceFactory.forUri2(Uri.parse(libraryUri)); |
| 692 var libraryElement = context.computeLibraryElement(source); |
| 693 for (var member in requiredSdkMembers[libraryUri]) { |
| 694 var type = libraryElement.getType(member); |
| 695 if (type == null) { |
| 696 throw 'Could not find $member in $libraryUri'; |
| 697 } |
| 698 promoteToTypeLevel(getClassReference(type)); |
| 699 } |
| 700 } |
| 701 _iterateTemporaryClassWorklist(); |
| 702 _iterateMixinLibraryWorklist(); |
| 703 } |
| 704 |
| 652 void loadEverything({Target target, bool compileSdk}) { | 705 void loadEverything({Target target, bool compileSdk}) { |
| 653 compileSdk ??= true; | 706 compileSdk ??= true; |
| 654 if (compileSdk) { | 707 if (compileSdk) { |
| 655 ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary())); | 708 ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary())); |
| 656 if (target != null) { | 709 if (target != null) { |
| 657 for (var uri in target.extraRequiredLibraries) { | 710 for (var uri in target.extraRequiredLibraries) { |
| 658 var library = _findLibraryElement(uri); | 711 var library = _findLibraryElement(uri); |
| 659 if (library == null) { | 712 if (library == null) { |
| 660 errors.add('Could not find required library $uri'); | 713 errors.add('Could not find required library $uri'); |
| 661 continue; | 714 continue; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 681 LibraryElement element = context.computeLibraryElement(context | 734 LibraryElement element = context.computeLibraryElement(context |
| 682 .sourceFactory | 735 .sourceFactory |
| 683 .forUri2(applicationRoot.absoluteUri(library.importUri))); | 736 .forUri2(applicationRoot.absoluteUri(library.importUri))); |
| 684 for (var unit in element.units) { | 737 for (var unit in element.units) { |
| 685 list.add(unit.source.fullName); | 738 list.add(unit.source.fullName); |
| 686 } | 739 } |
| 687 } | 740 } |
| 688 return list; | 741 return list; |
| 689 } | 742 } |
| 690 | 743 |
| 691 void _iterateWorklist() { | 744 void _iterateTemporaryClassWorklist() { |
| 692 while (temporaryClassWorklist.isNotEmpty) { | 745 while (temporaryClassWorklist.isNotEmpty) { |
| 693 var element = temporaryClassWorklist.removeLast(); | 746 var element = temporaryClassWorklist.removeLast(); |
| 694 promoteToTypeLevel(element); | 747 promoteToTypeLevel(element); |
| 695 } | 748 } |
| 696 } | 749 } |
| 697 | 750 |
| 751 void _iterateMixinLibraryWorklist() { |
| 752 // The worklist groups classes in the same library together so that we |
| 753 // request resolved ASTs for each library only once. |
| 754 while (mixinLibraryWorklist.isNotEmpty) { |
| 755 LibraryElement library = mixinLibraryWorklist.keys.first; |
| 756 _libraryBeingLoaded = library; |
| 757 List<ClassElement> classes = mixinLibraryWorklist.remove(library); |
| 758 for (var class_ in classes) { |
| 759 var classNode = getClassReference(class_); |
| 760 promoteToMixinLevel(classNode, class_, class_.computeNode()); |
| 761 } |
| 762 _libraryBeingLoaded = null; |
| 763 } |
| 764 _iterateTemporaryClassWorklist(); |
| 765 } |
| 766 |
| 698 ast.Procedure _getMainMethod(Uri uri) { | 767 ast.Procedure _getMainMethod(Uri uri) { |
| 699 Source source = context.sourceFactory.forUri2(uri); | 768 Source source = context.sourceFactory.forUri2(uri); |
| 700 LibraryElement library = context.computeLibraryElement(source); | 769 LibraryElement library = context.computeLibraryElement(source); |
| 701 var mainElement = library.entryPoint; | 770 var mainElement = library.entryPoint; |
| 702 if (mainElement == null) return null; | 771 if (mainElement == null) return null; |
| 703 var mainMember = getMemberReference(mainElement); | 772 var mainMember = getMemberReference(mainElement); |
| 704 if (mainMember is ast.Procedure && !mainMember.isAccessor) { | 773 if (mainMember is ast.Procedure && !mainMember.isAccessor) { |
| 705 return mainMember; | 774 return mainMember; |
| 706 } | 775 } |
| 707 // Top-level 'main' getters are not supported at the moment. | 776 // Top-level 'main' getters are not supported at the moment. |
| 708 return null; | 777 return null; |
| 709 } | 778 } |
| 710 | 779 |
| 711 ast.Procedure _makeMissingMainMethod(ast.Library library) { | 780 ast.Procedure _makeMissingMainMethod(ast.Library library) { |
| 712 var main = new ast.Procedure( | 781 var main = new ast.Procedure( |
| 713 new ast.Name('main'), | 782 new ast.Name('main'), |
| 714 ast.ProcedureKind.Method, | 783 ast.ProcedureKind.Method, |
| 715 new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw( | 784 new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw( |
| 716 new ast.StringLiteral('Program has no main method')))), | 785 new ast.StringLiteral('Program has no main method')))), |
| 717 isStatic: true) | 786 isStatic: true)..fileUri = library.fileUri; |
| 718 ..fileUri = library.fileUri; | |
| 719 library.addMember(main); | 787 library.addMember(main); |
| 720 return main; | 788 return main; |
| 721 } | 789 } |
| 722 | 790 |
| 723 ast.Program loadProgram(Uri mainLibrary, {Target target, bool compileSdk}) { | 791 ast.Program loadProgram(Uri mainLibrary, {Target target, bool compileSdk}) { |
| 724 Uri uri = applicationRoot.relativeUri(mainLibrary); | 792 Uri uri = applicationRoot.relativeUri(mainLibrary); |
| 725 ast.Library library = repository.getLibraryReference(uri); | 793 ast.Library library = repository.getLibraryReference(uri); |
| 726 ensureLibraryIsLoaded(library); | 794 ensureLibraryIsLoaded(library); |
| 727 var mainMethod = _getMainMethod(mainLibrary); | 795 var mainMethod = _getMainMethod(mainLibrary); |
| 728 loadEverything(target: target, compileSdk: compileSdk); | 796 loadEverything(target: target, compileSdk: compileSdk); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() | 972 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() |
| 905 ..sourceFactory = new SourceFactory(resolvers) | 973 ..sourceFactory = new SourceFactory(resolvers) |
| 906 ..analysisOptions = createAnalysisOptions(options.strongMode); | 974 ..analysisOptions = createAnalysisOptions(options.strongMode); |
| 907 | 975 |
| 908 options.declaredVariables.forEach((String name, String value) { | 976 options.declaredVariables.forEach((String name, String value) { |
| 909 context.declaredVariables.define(name, value); | 977 context.declaredVariables.define(name, value); |
| 910 }); | 978 }); |
| 911 | 979 |
| 912 return context; | 980 return context; |
| 913 } | 981 } |
| OLD | NEW |