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 |