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 | 4 |
5 import 'dart:async'; | |
5 import 'dart:collection' show HashSet, Queue; | 6 import 'dart:collection' show HashSet, Queue; |
6 import 'dart:convert' show BASE64, JSON, UTF8; | 7 import 'dart:convert' show JSON; |
7 import 'dart:io' show File; | 8 import 'dart:io' show File; |
8 | 9 |
9 import 'package:analyzer/analyzer.dart' | 10 import 'package:analyzer/analyzer.dart' |
10 show AnalysisError, CompilationUnit, ErrorSeverity; | 11 show AnalysisError, CompilationUnit, ErrorSeverity; |
12 import 'package:analyzer/context/declared_variables.dart'; | |
11 import 'package:analyzer/dart/element/element.dart' show LibraryElement; | 13 import 'package:analyzer/dart/element/element.dart' show LibraryElement; |
12 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider; | 14 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider; |
13 import 'package:analyzer/file_system/physical_file_system.dart' | 15 import 'package:analyzer/file_system/physical_file_system.dart' |
14 show PhysicalResourceProvider; | 16 show PhysicalResourceProvider; |
15 import 'package:analyzer/src/context/builder.dart' show ContextBuilder; | 17 import 'package:analyzer/src/context/builder.dart' show ContextBuilder; |
16 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; | 18 import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
19 import 'package:analyzer/src/dart/analysis/driver.dart'; | |
20 import 'package:analyzer/src/dart/analysis/file_state.dart'; | |
17 import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode; | 21 import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode; |
18 import 'package:analyzer/src/generated/engine.dart' | 22 import 'package:analyzer/src/generated/engine.dart' |
19 show AnalysisContext, AnalysisEngine; | 23 show AnalysisContext, AnalysisEngine; |
20 import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; | 24 import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; |
21 import 'package:analyzer/src/generated/source.dart' | 25 import 'package:analyzer/src/generated/source.dart' |
22 show ContentCache, DartUriResolver; | 26 show ContentCache, DartUriResolver, LineInfo; |
23 import 'package:analyzer/src/generated/source_io.dart' | 27 import 'package:analyzer/src/generated/source_io.dart' |
24 show Source, SourceKind, UriResolver; | 28 show Source, SourceKind, UriResolver; |
25 import 'package:analyzer/src/summary/package_bundle_reader.dart' | 29 import 'package:analyzer/src/summary/package_bundle_reader.dart' |
26 show InSummarySource, InputPackagesResultProvider, SummaryDataStore; | 30 show InSummarySource, SummaryDataStore; |
27 import 'package:args/args.dart' show ArgParser, ArgResults; | 31 import 'package:args/args.dart' show ArgParser, ArgResults; |
28 import 'package:args/src/usage_exception.dart' show UsageException; | 32 import 'package:args/src/usage_exception.dart' show UsageException; |
29 import 'package:func/func.dart' show Func1; | 33 import 'package:func/func.dart' show Func1; |
30 import 'package:path/path.dart' as path; | 34 import 'package:path/path.dart' as path; |
31 import 'package:source_maps/source_maps.dart'; | 35 import 'package:source_maps/source_maps.dart'; |
32 | 36 |
33 import '../analyzer/context.dart' show AnalyzerOptions, createSourceFactory; | 37 import '../analyzer/context.dart' show AnalyzerOptions, createSourceFactory; |
34 import '../js_ast/js_ast.dart' as JS; | 38 import '../js_ast/js_ast.dart' as JS; |
35 import 'code_generator.dart' show CodeGenerator; | 39 import 'code_generator.dart' show CodeGenerator; |
36 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; | 40 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; |
(...skipping 13 matching lines...) Expand all Loading... | |
50 /// It can be used once to produce a single module, or reused to save warm-up | 54 /// It can be used once to produce a single module, or reused to save warm-up |
51 /// time. (Currently there is no warm up, but there may be in the future.) | 55 /// time. (Currently there is no warm up, but there may be in the future.) |
52 /// | 56 /// |
53 /// The SDK source code is assumed to be immutable for the life of this class. | 57 /// The SDK source code is assumed to be immutable for the life of this class. |
54 /// | 58 /// |
55 /// For all other files, it is up to the [AnalysisContext] to decide whether or | 59 /// For all other files, it is up to the [AnalysisContext] to decide whether or |
56 /// not any caching is performed. By default an analysis context will assume | 60 /// not any caching is performed. By default an analysis context will assume |
57 /// sources are immutable for the life of the context, and cache information | 61 /// sources are immutable for the life of the context, and cache information |
58 /// about them. | 62 /// about them. |
59 class ModuleCompiler { | 63 class ModuleCompiler { |
60 final AnalysisContext context; | 64 final AnalysisDriver driver; |
61 final SummaryDataStore summaryData; | 65 final SummaryDataStore summaryData; |
62 final ExtensionTypeSet _extensionTypes; | 66 ExtensionTypeSet _extensionTypes; |
63 | 67 |
64 ModuleCompiler._(AnalysisContext context, this.summaryData) | 68 ModuleCompiler._(this.driver, this.summaryData); |
65 : context = context, | |
66 _extensionTypes = new ExtensionTypeSet(context); | |
67 | 69 |
68 factory ModuleCompiler(AnalyzerOptions options, | 70 factory ModuleCompiler(AnalyzerOptions options, |
69 {ResourceProvider resourceProvider, | 71 {ResourceProvider resourceProvider, |
70 String analysisRoot, | 72 String analysisRoot, |
71 List<UriResolver> fileResolvers, | 73 List<UriResolver> fileResolvers, |
72 SummaryDataStore summaryData}) { | 74 SummaryDataStore summaryData}) { |
73 // TODO(danrubel): refactor with analyzer CLI into analyzer common code | 75 // TODO(danrubel): refactor with analyzer CLI into analyzer common code |
74 AnalysisEngine.instance.processRequiredPlugins(); | 76 AnalysisEngine.instance.processRequiredPlugins(); |
75 | 77 |
76 resourceProvider ??= PhysicalResourceProvider.INSTANCE; | 78 resourceProvider ??= PhysicalResourceProvider.INSTANCE; |
(...skipping 15 matching lines...) Expand all Loading... | |
92 if (sdkSummaryBundle != null) { | 94 if (sdkSummaryBundle != null) { |
93 summaryData.addBundle(null, sdkSummaryBundle); | 95 summaryData.addBundle(null, sdkSummaryBundle); |
94 } | 96 } |
95 | 97 |
96 var srcFactory = createSourceFactory(options, | 98 var srcFactory = createSourceFactory(options, |
97 sdkResolver: sdkResolver, | 99 sdkResolver: sdkResolver, |
98 fileResolvers: fileResolvers, | 100 fileResolvers: fileResolvers, |
99 summaryData: summaryData, | 101 summaryData: summaryData, |
100 resourceProvider: resourceProvider); | 102 resourceProvider: resourceProvider); |
101 | 103 |
102 var context = | 104 var declaredVariables = new DeclaredVariables(); |
103 AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl; | 105 options.declaredVariables.forEach(declaredVariables.define); |
104 context.analysisOptions = analysisOptions; | 106 declaredVariables.define('dart.isVM', 'false'); |
105 context.sourceFactory = srcFactory; | 107 // TODO(vsm): Should this be hardcoded? |
106 if (sdkSummaryBundle != null) { | 108 declaredVariables.define('dart.library.html', 'true'); |
107 context.resultProvider = | 109 declaredVariables.define('dart.library.io', 'false'); |
108 new InputPackagesResultProvider(context, summaryData); | 110 |
111 if (!analysisOptions.strongMode) { | |
112 throw new ArgumentError('AnalysisOptions must be strong mode'); | |
109 } | 113 } |
110 options.declaredVariables.forEach(context.declaredVariables.define); | 114 if (!srcFactory.dartSdk.context.analysisOptions.strongMode) { |
111 context.declaredVariables.define('dart.isVM', 'false'); | 115 throw new ArgumentError('AnalysisOptions must have strong mode SDK'); |
112 | |
113 // TODO(vsm): Should this be hardcoded? | |
114 context.declaredVariables.define('dart.library.html', 'true'); | |
115 context.declaredVariables.define('dart.library.io', 'false'); | |
116 | |
117 if (!context.analysisOptions.strongMode) { | |
118 throw new ArgumentError('AnalysisContext must be strong mode'); | |
119 } | |
120 if (!context.sourceFactory.dartSdk.context.analysisOptions.strongMode) { | |
121 throw new ArgumentError('AnalysisContext must have strong mode SDK'); | |
122 } | 116 } |
123 | 117 |
124 return new ModuleCompiler._(context, summaryData); | 118 AnalysisDriver driver; |
119 { | |
Jennifer Messerly
2017/03/17 18:33:37
i'm not sure this block is necessary
scheglov
2017/04/25 17:07:35
We defined a couple of variables that are not usef
| |
120 var logger = new PerformanceLog(new StringBuffer()); | |
121 // var logger = new PerformanceLog(stdout); | |
Jennifer Messerly
2017/03/17 18:33:38
remove?
scheglov
2017/04/25 17:07:35
Done.
| |
122 var scheduler = new AnalysisDriverScheduler(logger); | |
123 driver = new AnalysisDriver( | |
124 scheduler, | |
125 logger, | |
126 resourceProvider, | |
127 new MemoryByteStore(), | |
128 new FileContentOverlay(), | |
129 'DDC', | |
130 srcFactory, | |
131 analysisOptions, | |
132 externalSummaries: summaryData); | |
133 scheduler.start(); | |
134 } | |
135 | |
136 return new ModuleCompiler._(driver, summaryData); | |
125 } | 137 } |
126 | 138 |
127 bool _isFatalError(AnalysisError e, CompilerOptions options) { | 139 bool _isFatalError(AnalysisError e, CompilerOptions options) { |
128 if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false; | 140 if (errorSeverity(driver.analysisOptions, e) != ErrorSeverity.ERROR) |
141 return false; | |
129 | 142 |
130 // These errors are not fatal in the REPL compile mode as we | 143 // These errors are not fatal in the REPL compile mode as we |
131 // allow access to private members across library boundaries | 144 // allow access to private members across library boundaries |
132 // and those accesses will show up as undefined members unless | 145 // and those accesses will show up as undefined members unless |
133 // additional analyzer changes are made to support them. | 146 // additional analyzer changes are made to support them. |
134 // TODO(jacobr): consider checking that the identifier name | 147 // TODO(jacobr): consider checking that the identifier name |
135 // referenced by the error is private. | 148 // referenced by the error is private. |
136 return !options.replCompile || | 149 return !options.replCompile || |
137 (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER && | 150 (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER && |
138 e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER && | 151 e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER && |
139 e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD); | 152 e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD); |
140 } | 153 } |
141 | 154 |
142 /// Compiles a single Dart build unit into a JavaScript module. | 155 /// Compiles a single Dart build unit into a JavaScript module. |
143 /// | 156 /// |
144 /// *Warning* - this may require resolving the entire world. | 157 /// *Warning* - this may require resolving the entire world. |
145 /// If that is not desired, the analysis context must be pre-configured using | 158 /// If that is not desired, the analysis context must be pre-configured using |
146 /// summaries before calling this method. | 159 /// summaries before calling this method. |
147 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { | 160 Future<JSModuleFile> compile(BuildUnit unit, CompilerOptions options) async { |
148 var trees = <CompilationUnit>[]; | 161 var trees = <CompilationUnit>[]; |
149 var errors = <AnalysisError>[]; | 162 var errors = <AnalysisError>[]; |
163 var lineInfoMap = <String, LineInfo>{}; | |
150 | 164 |
151 var librariesToCompile = new Queue<LibraryElement>(); | 165 var librariesToCompile = new Queue<LibraryElement>(); |
152 | 166 |
153 var compilingSdk = false; | 167 var compilingSdk = false; |
154 for (var sourcePath in unit.sources) { | 168 for (var sourceUriStr in unit.sources) { |
155 var sourceUri = Uri.parse(sourcePath); | 169 var sourceUri = Uri.parse(sourceUriStr); |
156 if (sourceUri.scheme == '') { | 170 if (sourceUri.scheme == '') { |
157 sourceUri = path.toUri(path.absolute(sourcePath)); | 171 sourceUri = path.toUri(path.absolute(sourceUriStr)); |
158 } else if (sourceUri.scheme == 'dart') { | 172 } else if (sourceUri.scheme == 'dart') { |
159 compilingSdk = true; | 173 compilingSdk = true; |
160 } | 174 } |
161 Source source = context.sourceFactory.forUri2(sourceUri); | 175 Source source = driver.sourceFactory.forUri2(sourceUri); |
176 String sourcePath = source.fullName; | |
162 | 177 |
163 var fileUsage = 'You need to pass at least one existing .dart file as an' | 178 var fileUsage = 'You need to pass at least one existing .dart file as an' |
164 ' argument.'; | 179 ' argument.'; |
165 if (source == null) { | 180 if (source == null) { |
166 throw new UsageException( | 181 throw new UsageException( |
167 'Could not create a source for "$sourcePath". The file name is in' | 182 'Could not create a source for "$sourceUriStr". The file name is in' |
168 ' the wrong format or was not found.', | 183 ' the wrong format or was not found.', |
169 fileUsage); | 184 fileUsage); |
170 } else if (!source.exists()) { | 185 } else if (!source.exists()) { |
171 throw new UsageException( | 186 throw new UsageException( |
172 'Given file "$sourcePath" does not exist.', fileUsage); | 187 'Given file "$sourceUriStr" does not exist.', fileUsage); |
173 } | 188 } |
174 | 189 |
175 // Ignore parts. They need to be handled in the context of their library. | 190 // Ignore parts. They need to be handled in the context of their library. |
176 if (context.computeKindOf(source) == SourceKind.PART) { | 191 SourceKind sourceKind = await driver.getSourceKind(sourcePath); |
192 if (sourceKind == SourceKind.PART) { | |
177 continue; | 193 continue; |
178 } | 194 } |
179 | 195 |
180 librariesToCompile.add(context.computeLibraryElement(source)); | 196 UnitElementResult unitResult = await driver.getUnitElement(sourcePath); |
197 LibraryElement library = unitResult.element.library; | |
198 librariesToCompile.add(library); | |
181 } | 199 } |
182 | 200 |
183 var libraries = new HashSet<LibraryElement>(); | 201 var libraries = new HashSet<LibraryElement>(); |
184 while (librariesToCompile.isNotEmpty) { | 202 while (librariesToCompile.isNotEmpty) { |
185 var library = librariesToCompile.removeFirst(); | 203 var library = librariesToCompile.removeFirst(); |
186 if (library.source is InSummarySource) continue; | 204 if (library.source is InSummarySource) continue; |
187 if (!compilingSdk && library.source.isInSystemLibrary) continue; | 205 if (!compilingSdk && library.source.isInSystemLibrary) continue; |
188 if (!libraries.add(library)) continue; | 206 if (!libraries.add(library)) continue; |
189 | 207 |
190 librariesToCompile.addAll(library.importedLibraries); | 208 librariesToCompile.addAll(library.importedLibraries); |
191 librariesToCompile.addAll(library.exportedLibraries); | 209 librariesToCompile.addAll(library.exportedLibraries); |
192 | 210 |
193 var tree = context.resolveCompilationUnit(library.source, library); | 211 var definingResult = await driver.getResult(library.source.fullName); |
194 trees.add(tree); | 212 trees.add(definingResult.unit); |
195 errors.addAll(context.computeErrors(library.source)); | 213 errors.addAll(definingResult.errors); |
214 lineInfoMap[definingResult.path] = definingResult.lineInfo; | |
196 | 215 |
197 for (var part in library.parts) { | 216 for (var part in library.parts) { |
198 trees.add(context.resolveCompilationUnit(part.source, library)); | 217 var partResult = await driver.getResult(part.source.fullName); |
199 errors.addAll(context.computeErrors(part.source)); | 218 trees.add(partResult.unit); |
219 errors.addAll(partResult.errors); | |
220 lineInfoMap[partResult.path] = partResult.lineInfo; | |
200 } | 221 } |
201 } | 222 } |
202 | 223 |
203 sortErrors(context, errors); | 224 sortErrors(driver.analysisOptions, errors); |
225 | |
226 _extensionTypes ??= await ExtensionTypeSet.create(driver); | |
204 | 227 |
205 var messages = <String>[]; | 228 var messages = <String>[]; |
206 for (var e in errors) { | 229 for (AnalysisError e in errors) { |
207 var m = formatError(context, e); | 230 var lineInfo = lineInfoMap[e.source.fullName]; |
231 var m = formatError(driver.analysisOptions, lineInfo, e); | |
208 if (m != null) messages.add(m); | 232 if (m != null) messages.add(m); |
209 } | 233 } |
210 | 234 |
211 if (!options.unsafeForceCompile && | 235 if (!options.unsafeForceCompile && |
212 errors.any((e) => _isFatalError(e, options))) { | 236 errors.any((e) => _isFatalError(e, options))) { |
213 return new JSModuleFile.invalid(unit.name, messages, options); | 237 return new JSModuleFile.invalid(unit.name, messages, options); |
214 } | 238 } |
215 var codeGenerator = | 239 var codeGenerator = await CodeGenerator.create( |
Jennifer Messerly
2017/03/17 18:33:38
I would rather keep async out of CodeGenerator, an
scheglov
2017/04/25 17:07:35
Done.
| |
216 new CodeGenerator(context, summaryData, options, _extensionTypes); | 240 driver, summaryData, options, _extensionTypes); |
217 return codeGenerator.compile(unit, trees, messages); | 241 return codeGenerator.compile(unit, trees, messages); |
218 } | 242 } |
219 } | 243 } |
220 | 244 |
221 class CompilerOptions { | 245 class CompilerOptions { |
222 /// Whether to emit the source mapping file. | 246 /// Whether to emit the source mapping file. |
223 /// | 247 /// |
224 /// This supports debugging the original source code instead of the generated | 248 /// This supports debugging the original source code instead of the generated |
225 /// code. | 249 /// code. |
226 final bool sourceMap; | 250 final bool sourceMap; |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 /// are implementation details that would just confuse users. | 623 /// are implementation details that would just confuse users. |
600 /// Normalize sdk urls to use "dart:" for more understandable stack traces. | 624 /// Normalize sdk urls to use "dart:" for more understandable stack traces. |
601 Map cleanupSdkSourcemap(Map sourceMap) { | 625 Map cleanupSdkSourcemap(Map sourceMap) { |
602 var map = new Map.from(sourceMap); | 626 var map = new Map.from(sourceMap); |
603 var list = new List.from(map['sources']); | 627 var list = new List.from(map['sources']); |
604 map['sources'] = map['sources'] | 628 map['sources'] = map['sources'] |
605 .map((url) => url.contains('/_internal/') ? null : url) | 629 .map((url) => url.contains('/_internal/') ? null : url) |
606 .toList(); | 630 .toList(); |
607 return map; | 631 return map; |
608 } | 632 } |
OLD | NEW |