| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 return element.name.isEmpty ? null : element.name; | 102 return element.name.isEmpty ? null : element.name; |
| 103 } | 103 } |
| 104 | 104 |
| 105 ast.Library getLibraryReference(LibraryElement element) { | 105 ast.Library getLibraryReference(LibraryElement element) { |
| 106 var uri = applicationRoot.relativeUri(element.source.uri); | 106 var uri = applicationRoot.relativeUri(element.source.uri); |
| 107 return repository.getLibraryReference(uri) | 107 return repository.getLibraryReference(uri) |
| 108 ..name ??= getLibraryName(element) | 108 ..name ??= getLibraryName(element) |
| 109 ..fileUri = "file://${element.source.fullName}"; | 109 ..fileUri = "file://${element.source.fullName}"; |
| 110 } | 110 } |
| 111 | 111 |
| 112 void _buildTopLevelMember(ast.Member member, Element element) { | 112 void _buildTopLevelMember( |
| 113 var astNode = element.computeNode(); | 113 ast.Member member, Element element, Declaration astNode) { |
| 114 assert(member.parent != null); | 114 assert(member.parent != null); |
| 115 new MemberBodyBuilder(this, member, element).build(astNode); | 115 new MemberBodyBuilder(this, member, element).build(astNode); |
| 116 } | 116 } |
| 117 | 117 |
| 118 /// True if [element] is in the process of being loaded by | 118 /// True if [element] is in the process of being loaded by |
| 119 /// [_buildLibraryBody]. | 119 /// [_buildLibraryBody]. |
| 120 /// | 120 /// |
| 121 /// If this is the case, we should avoid adding new members to the classes | 121 /// If this is the case, we should avoid adding new members to the classes |
| 122 /// in the library, since the AST builder will rebuild the member lists. | 122 /// in the library, since the AST builder will rebuild the member lists. |
| 123 bool isLibraryBeingLoaded(LibraryElement element) { | 123 bool isLibraryBeingLoaded(LibraryElement element) { |
| 124 return _libraryBeingLoaded == element; | 124 return _libraryBeingLoaded == element; |
| 125 } | 125 } |
| 126 | 126 |
| 127 void _buildLibraryBody(LibraryElement element, ast.Library library) { | 127 void _buildLibraryBody(LibraryElement element, ast.Library library, |
| 128 List<CompilationUnit> units) { |
| 128 assert(_libraryBeingLoaded == null); | 129 assert(_libraryBeingLoaded == null); |
| 129 _libraryBeingLoaded = element; | 130 _libraryBeingLoaded = element; |
| 130 var classes = <ast.Class>[]; | 131 var classes = <ast.Class>[]; |
| 131 var procedures = <ast.Procedure>[]; | 132 var procedures = <ast.Procedure>[]; |
| 132 var fields = <ast.Field>[]; | 133 var fields = <ast.Field>[]; |
| 133 void loadClass(ClassElement classElement) { | 134 |
| 134 var node = getClassReference(classElement); | 135 void loadClass(NamedCompilationUnitMember declaration) { |
| 135 promoteToBodyLevel(node); | 136 // [declaration] can be a ClassDeclaration, EnumDeclaration, or a |
| 137 // ClassTypeAlias. |
| 138 ClassElement element = declaration.element; |
| 139 var node = getClassReference(element); |
| 140 promoteToBodyLevel(node, element, declaration); |
| 136 classes.add(node); | 141 classes.add(node); |
| 137 } | 142 } |
| 138 | 143 |
| 139 void loadProcedure(Element memberElement) { | 144 void loadProcedure(FunctionDeclaration declaration) { |
| 140 var node = getMemberReference(memberElement); | 145 var element = declaration.element; |
| 141 _buildTopLevelMember(node, memberElement); | 146 var node = getMemberReference(element); |
| 147 _buildTopLevelMember(node, element, declaration); |
| 142 procedures.add(node); | 148 procedures.add(node); |
| 143 } | 149 } |
| 144 | 150 |
| 145 void loadField(Element memberElement) { | 151 void loadField(TopLevelVariableDeclaration declaration) { |
| 146 var node = getMemberReference(memberElement); | 152 for (var field in declaration.variables.variables) { |
| 147 _buildTopLevelMember(node, memberElement); | 153 var element = field.element; |
| 148 fields.add(node); | 154 // Ignore fields inserted through error recovery. |
| 155 if (element.name == '') continue; |
| 156 var node = getMemberReference(element); |
| 157 _buildTopLevelMember(node, element, field); |
| 158 fields.add(node); |
| 159 } |
| 149 } | 160 } |
| 150 | 161 |
| 151 for (var unit in element.units) { | 162 for (var unit in units) { |
| 152 unit.types.forEach(loadClass); | 163 for (CompilationUnitMember declaration in unit.declarations) { |
| 153 unit.enums.forEach(loadClass); | 164 if (declaration is ClassDeclaration || |
| 154 for (var accessor in unit.accessors) { | 165 declaration is EnumDeclaration || |
| 155 if (!accessor.isSynthetic) { | 166 declaration is ClassTypeAlias) { |
| 156 loadProcedure(accessor); | 167 loadClass(declaration); |
| 157 } | 168 } else if (declaration is FunctionDeclaration) { |
| 158 } | 169 loadProcedure(declaration); |
| 159 for (var function in unit.functions) { | 170 } else if (declaration is TopLevelVariableDeclaration) { |
| 160 loadProcedure(function); | 171 loadField(declaration); |
| 161 } | 172 } else if (declaration is FunctionTypeAlias) { |
| 162 for (var field in unit.topLevelVariables) { | 173 // Nothing to do. Typedefs are handled lazily while constructing type |
| 163 // Ignore fields inserted through error recovery. | 174 // references. |
| 164 if (!field.isSynthetic && field.name != '') { | 175 } else { |
| 165 loadField(field); | 176 throw "unexpected node: ${declaration.runtimeType} $declaration"; |
| 166 } | 177 } |
| 167 } | 178 } |
| 168 } | 179 } |
| 169 libraryElements.add(element); | 180 libraryElements.add(element); |
| 170 _iterateWorklist(); | 181 _iterateWorklist(); |
| 171 // Ensure everything is stored in the original declaration order. | 182 // Ensure everything is stored in the original declaration order. |
| 172 library.classes | 183 library.classes |
| 173 ..clear() | 184 ..clear() |
| 174 ..addAll(classes) | 185 ..addAll(classes) |
| 175 ..addAll(_mixinApplications[library]?.values ?? const []); | 186 ..addAll(_mixinApplications[library]?.values ?? const []); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 if (!method.isStatic && !method.isSynthetic) { | 356 if (!method.isStatic && !method.isSynthetic) { |
| 346 getMemberReference(method); | 357 getMemberReference(method); |
| 347 } | 358 } |
| 348 } | 359 } |
| 349 } | 360 } |
| 350 for (var supertype in classNode.supers) { | 361 for (var supertype in classNode.supers) { |
| 351 promoteToHierarchyLevel(supertype.classNode); | 362 promoteToHierarchyLevel(supertype.classNode); |
| 352 } | 363 } |
| 353 } | 364 } |
| 354 | 365 |
| 355 void promoteToBodyLevel(ast.Class classNode) { | 366 void promoteToBodyLevel(ast.Class classNode, ClassElement element, |
| 367 NamedCompilationUnitMember astNode) { |
| 356 if (classNode.level == ast.ClassLevel.Body) return; | 368 if (classNode.level == ast.ClassLevel.Body) return; |
| 357 promoteToHierarchyLevel(classNode); | 369 promoteToHierarchyLevel(classNode); |
| 358 classNode.level = ast.ClassLevel.Body; | 370 classNode.level = ast.ClassLevel.Body; |
| 359 var element = getClassElement(classNode); | |
| 360 if (element == null) return; | |
| 361 var astNode = element.computeNode(); | |
| 362 // Clear out the member references that were put in the class. | 371 // Clear out the member references that were put in the class. |
| 363 // The AST builder will load them all put back in the right order. | 372 // The AST builder will load them all put back in the right order. |
| 364 classNode..fields.clear()..procedures.clear()..constructors.clear(); | 373 classNode..fields.clear()..procedures.clear()..constructors.clear(); |
| 365 new ClassBodyBuilder(this, classNode, element).build(astNode); | 374 new ClassBodyBuilder(this, classNode, element).build(astNode); |
| 366 } | 375 } |
| 367 | 376 |
| 368 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) { | 377 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) { |
| 369 return _classTypeParameters[element]; | 378 return _classTypeParameters[element]; |
| 370 } | 379 } |
| 371 | 380 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 'col ${location.columnNumber})'; | 587 'col ${location.columnNumber})'; |
| 579 } | 588 } |
| 580 | 589 |
| 581 void ensureLibraryIsLoaded(ast.Library node) { | 590 void ensureLibraryIsLoaded(ast.Library node) { |
| 582 if (!node.isExternal) return; | 591 if (!node.isExternal) return; |
| 583 node.isExternal = false; | 592 node.isExternal = false; |
| 584 var source = context.sourceFactory | 593 var source = context.sourceFactory |
| 585 .forUri2(applicationRoot.absoluteUri(node.importUri)); | 594 .forUri2(applicationRoot.absoluteUri(node.importUri)); |
| 586 assert(source != null); | 595 assert(source != null); |
| 587 var element = context.computeLibraryElement(source); | 596 var element = context.computeLibraryElement(source); |
| 588 context.resolveCompilationUnit(source, element); | 597 var units = <CompilationUnit>[]; |
| 589 _buildLibraryBody(element, node); | 598 bool reportErrors = node.importUri.scheme != 'dart'; |
| 590 if (node.importUri.scheme != 'dart') { | 599 var tree = context.resolveCompilationUnit(source, element); |
| 591 for (var unit in element.units) { | 600 units.add(tree); |
| 592 LineInfo lines; | 601 if (reportErrors) _processErrors(source); |
| 593 for (var error in context.computeErrors(unit.source)) { | 602 for (var part in element.parts) { |
| 594 if (error.errorCode is CompileTimeErrorCode || | 603 var source = part.source; |
| 595 error.errorCode is ParserErrorCode || | 604 units.add(context.resolveCompilationUnit(source, element)); |
| 596 error.errorCode is ScannerErrorCode || | 605 if (reportErrors) _processErrors(source); |
| 597 error.errorCode is StrongModeCode) { | 606 } |
| 598 lines ??= context.computeLineInfo(source); | 607 _buildLibraryBody(element, node, units); |
| 599 errors.add(formatErrorMessage(error, source.shortName, lines)); | 608 } |
| 600 } | 609 |
| 601 } | 610 void _processErrors(Source source) { |
| 611 LineInfo lines; |
| 612 for (var error in context.computeErrors(source)) { |
| 613 if (error.errorCode is CompileTimeErrorCode || |
| 614 error.errorCode is ParserErrorCode || |
| 615 error.errorCode is ScannerErrorCode || |
| 616 error.errorCode is StrongModeCode) { |
| 617 lines ??= context.computeLineInfo(source); |
| 618 errors.add(formatErrorMessage(error, source.shortName, lines)); |
| 602 } | 619 } |
| 603 } | 620 } |
| 604 } | 621 } |
| 605 | 622 |
| 606 void loadEverything({Target target}) { | 623 void loadEverything({Target target}) { |
| 607 ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary())); | 624 ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary())); |
| 608 if (target != null) { | 625 if (target != null) { |
| 609 for (var uri in target.extraRequiredLibraries) { | 626 for (var uri in target.extraRequiredLibraries) { |
| 610 var library = _findLibraryElement(uri); | 627 var library = _findLibraryElement(uri); |
| 611 if (library == null) { | 628 if (library == null) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 .getLibraryReference(applicationRoot.relativeUri(mainLibrary)); | 665 .getLibraryReference(applicationRoot.relativeUri(mainLibrary)); |
| 649 ensureLibraryIsLoaded(library); | 666 ensureLibraryIsLoaded(library); |
| 650 loadEverything(target: target); | 667 loadEverything(target: target); |
| 651 var program = new ast.Program(repository.libraries); | 668 var program = new ast.Program(repository.libraries); |
| 652 program.mainMethod = library.procedures.firstWhere( | 669 program.mainMethod = library.procedures.firstWhere( |
| 653 (member) => member.name?.name == 'main', | 670 (member) => member.name?.name == 'main', |
| 654 orElse: () => null); | 671 orElse: () => null); |
| 655 for (LibraryElement libraryElement in libraryElements) { | 672 for (LibraryElement libraryElement in libraryElements) { |
| 656 for (CompilationUnitElement compilationUnitElement | 673 for (CompilationUnitElement compilationUnitElement |
| 657 in libraryElement.units) { | 674 in libraryElement.units) { |
| 658 // TODO(jensj): Get this another way? | 675 var source = compilationUnitElement.source; |
| 659 LineInfo lineInfo = compilationUnitElement.computeNode().lineInfo; | 676 LineInfo lineInfo = context.computeLineInfo(source); |
| 660 program.uriToLineStarts[ | 677 program.uriToLineStarts["file://${source.fullName}"] = |
| 661 "file://${compilationUnitElement.source.source.fullName}"] = | |
| 662 new List<int>.generate(lineInfo.lineCount, lineInfo.getOffsetOfLine, | 678 new List<int>.generate(lineInfo.lineCount, lineInfo.getOffsetOfLine, |
| 663 growable: false); | 679 growable: false); |
| 664 } | 680 } |
| 665 } | 681 } |
| 666 return program; | 682 return program; |
| 667 } | 683 } |
| 668 | 684 |
| 669 ast.Library loadLibrary(Uri uri) { | 685 ast.Library loadLibrary(Uri uri) { |
| 670 ast.Library library = | 686 ast.Library library = |
| 671 repository.getLibraryReference(applicationRoot.relativeUri(uri)); | 687 repository.getLibraryReference(applicationRoot.relativeUri(uri)); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() | 831 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() |
| 816 ..sourceFactory = new SourceFactory(resolvers) | 832 ..sourceFactory = new SourceFactory(resolvers) |
| 817 ..analysisOptions = createAnalysisOptions(options.strongMode); | 833 ..analysisOptions = createAnalysisOptions(options.strongMode); |
| 818 | 834 |
| 819 options.declaredVariables.forEach((String name, String value) { | 835 options.declaredVariables.forEach((String name, String value) { |
| 820 context.declaredVariables.define(name, value); | 836 context.declaredVariables.define(name, value); |
| 821 }); | 837 }); |
| 822 | 838 |
| 823 return context; | 839 return context; |
| 824 } | 840 } |
| OLD | NEW |