OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library analyzer_cli.src.build_mode; | 5 library analyzer_cli.src.build_mode; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; | 10 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 final AnalysisStats stats; | 129 final AnalysisStats stats; |
130 | 130 |
131 SummaryDataStore summaryDataStore; | 131 SummaryDataStore summaryDataStore; |
132 InternalAnalysisContext context; | 132 InternalAnalysisContext context; |
133 Map<Uri, File> uriToFileMap; | 133 Map<Uri, File> uriToFileMap; |
134 final List<Source> explicitSources = <Source>[]; | 134 final List<Source> explicitSources = <Source>[]; |
135 final List<PackageBundle> unlinkedBundles = <PackageBundle>[]; | 135 final List<PackageBundle> unlinkedBundles = <PackageBundle>[]; |
136 | 136 |
137 PackageBundleAssembler assembler; | 137 PackageBundleAssembler assembler; |
138 final Set<Source> processedSources = new Set<Source>(); | 138 final Set<Source> processedSources = new Set<Source>(); |
139 final Map<Uri, UnlinkedUnit> uriToUnit = <Uri, UnlinkedUnit>{}; | 139 final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{}; |
140 | 140 |
141 BuildMode(this.resourceProvider, this.options, this.stats); | 141 BuildMode(this.resourceProvider, this.options, this.stats); |
142 | 142 |
143 bool get _shouldOutputSummary => | 143 bool get _shouldOutputSummary => |
144 options.buildSummaryOutput != null || | 144 options.buildSummaryOutput != null || |
145 options.buildSummaryOutputSemantic != null; | 145 options.buildSummaryOutputSemantic != null; |
146 | 146 |
147 /** | 147 /** |
148 * Perform package analysis according to the given [options]. | 148 * Perform package analysis according to the given [options]. |
149 */ | 149 */ |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 AnalysisResult analysisResult = context.performAnalysisTask(); | 199 AnalysisResult analysisResult = context.performAnalysisTask(); |
200 if (!analysisResult.hasMoreWork) { | 200 if (!analysisResult.hasMoreWork) { |
201 break; | 201 break; |
202 } | 202 } |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 // Write summary. | 206 // Write summary. |
207 assembler = new PackageBundleAssembler(); | 207 assembler = new PackageBundleAssembler(); |
208 if (_shouldOutputSummary) { | 208 if (_shouldOutputSummary) { |
209 if (options.buildSummaryOnlyUnlinked) { | 209 // Prepare all unlinked units. |
210 for (var src in explicitSources) { | 210 for (var src in explicitSources) { |
211 // Note: This adds the unit to the assembler if it needed to be | 211 _prepareUnlinkedUnit('${src.uri}'); |
212 // computed, so we don't need to explicitly do that. | 212 } |
213 _unlinkedUnitForUri('${src.uri}'); | 213 |
214 } | 214 // Build and assemble linked libraries. |
215 } else { | 215 if (!options.buildSummaryOnlyUnlinked) { |
216 Set<String> unlinkedUris = | 216 // Prepare URIs of unlinked units that should be linked. |
217 explicitSources.map((Source s) => s.uri.toString()).toSet(); | 217 var unlinkedUris = new Set<String>(); |
218 for (var bundle in unlinkedBundles) { | 218 for (var bundle in unlinkedBundles) { |
219 unlinkedUris.addAll(bundle.unlinkedUnitUris); | 219 unlinkedUris.addAll(bundle.unlinkedUnitUris); |
220 } | 220 } |
221 | 221 for (var src in explicitSources) { |
222 _serializeAstBasedSummary(unlinkedUris); | 222 unlinkedUris.add('${src.uri}'); |
| 223 } |
| 224 // Perform linking. |
| 225 _computeLinkedLibraries(unlinkedUris); |
223 assembler.recordDependencies(summaryDataStore); | 226 assembler.recordDependencies(summaryDataStore); |
224 } | 227 } |
| 228 |
225 // Write the whole package bundle. | 229 // Write the whole package bundle. |
226 PackageBundleBuilder bundle = assembler.assemble(); | 230 PackageBundleBuilder bundle = assembler.assemble(); |
227 if (options.buildSummaryOutput != null) { | 231 if (options.buildSummaryOutput != null) { |
228 io.File file = new io.File(options.buildSummaryOutput); | 232 io.File file = new io.File(options.buildSummaryOutput); |
229 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); | 233 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); |
230 } | 234 } |
231 if (options.buildSummaryOutputSemantic != null) { | 235 if (options.buildSummaryOutputSemantic != null) { |
232 bundle.flushInformative(); | 236 bundle.flushInformative(); |
233 io.File file = new io.File(options.buildSummaryOutputSemantic); | 237 io.File file = new io.File(options.buildSummaryOutputSemantic); |
234 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); | 238 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); |
235 } | 239 } |
236 } | 240 } |
237 | 241 |
238 if (options.buildSummaryOnly) { | 242 if (options.buildSummaryOnly) { |
239 return ErrorSeverity.NONE; | 243 return ErrorSeverity.NONE; |
240 } else { | 244 } else { |
241 // Process errors. | 245 // Process errors. |
242 _printErrors(outputPath: options.buildAnalysisOutput); | 246 _printErrors(outputPath: options.buildAnalysisOutput); |
243 return _computeMaxSeverity(); | 247 return _computeMaxSeverity(); |
244 } | 248 } |
245 } | 249 } |
246 | 250 |
| 251 /** |
| 252 * Compute linked libraries for the given [libraryUris] using the linked |
| 253 * libraries of the [summaryDataStore] and unlinked units in [uriToUnit], and |
| 254 * add them to the [assembler]. |
| 255 */ |
| 256 void _computeLinkedLibraries(Set<String> libraryUris) { |
| 257 LinkedLibrary getDependency(String absoluteUri) => |
| 258 summaryDataStore.linkedMap[absoluteUri]; |
| 259 |
| 260 UnlinkedUnit getUnit(String absoluteUri) => |
| 261 summaryDataStore.unlinkedMap[absoluteUri] ?? uriToUnit[absoluteUri]; |
| 262 |
| 263 Map<String, LinkedLibraryBuilder> linkResult = link( |
| 264 libraryUris, |
| 265 getDependency, |
| 266 getUnit, |
| 267 context.declaredVariables.get, |
| 268 options.strongMode); |
| 269 linkResult.forEach(assembler.addLinkedLibrary); |
| 270 } |
| 271 |
247 ErrorSeverity _computeMaxSeverity() { | 272 ErrorSeverity _computeMaxSeverity() { |
248 ErrorSeverity maxSeverity = ErrorSeverity.NONE; | 273 ErrorSeverity maxSeverity = ErrorSeverity.NONE; |
249 if (!options.buildSuppressExitCode) { | 274 if (!options.buildSuppressExitCode) { |
250 for (Source source in explicitSources) { | 275 for (Source source in explicitSources) { |
251 AnalysisErrorInfo errorInfo = context.getErrors(source); | 276 AnalysisErrorInfo errorInfo = context.getErrors(source); |
252 for (AnalysisError error in errorInfo.errors) { | 277 for (AnalysisError error in errorInfo.errors) { |
253 ErrorSeverity processedSeverity = determineProcessedSeverity( | 278 ErrorSeverity processedSeverity = determineProcessedSeverity( |
254 error, options, context.analysisOptions); | 279 error, options, context.analysisOptions); |
255 if (processedSeverity != null) { | 280 if (processedSeverity != null) { |
256 maxSeverity = maxSeverity.max(processedSeverity); | 281 maxSeverity = maxSeverity.max(processedSeverity); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 return null; | 380 return null; |
356 } | 381 } |
357 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); | 382 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); |
358 String path = sourceFile.substring(pipeIndex + 1); | 383 String path = sourceFile.substring(pipeIndex + 1); |
359 uriToFileMap[uri] = resourceProvider.getFile(path); | 384 uriToFileMap[uri] = resourceProvider.getFile(path); |
360 } | 385 } |
361 return uriToFileMap; | 386 return uriToFileMap; |
362 } | 387 } |
363 | 388 |
364 /** | 389 /** |
| 390 * Ensure that the [UnlinkedUnit] for [absoluteUri] is available. |
| 391 * |
| 392 * If the unit is in the input [summaryDataStore], do nothing. |
| 393 * |
| 394 * Otherwise compute it and store into the [uriToUnit] and [assembler]. |
| 395 */ |
| 396 void _prepareUnlinkedUnit(String absoluteUri) { |
| 397 // Maybe an input package contains the source. |
| 398 if (summaryDataStore.unlinkedMap[absoluteUri] != null) { |
| 399 return; |
| 400 } |
| 401 // Parse the source and serialize its AST. |
| 402 Uri uri = Uri.parse(absoluteUri); |
| 403 Source source = context.sourceFactory.forUri2(uri); |
| 404 if (!source.exists()) { |
| 405 // TODO(paulberry): we should report a warning/error because DDC |
| 406 // compilations are unlikely to work. |
| 407 return; |
| 408 } |
| 409 CompilationUnit unit = context.computeResult(source, PARSED_UNIT); |
| 410 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); |
| 411 uriToUnit[absoluteUri] = unlinkedUnit; |
| 412 assembler.addUnlinkedUnit(source, unlinkedUnit); |
| 413 } |
| 414 |
| 415 /** |
365 * Print errors for all explicit sources. If [outputPath] is supplied, output | 416 * Print errors for all explicit sources. If [outputPath] is supplied, output |
366 * is sent to a new file at that path. | 417 * is sent to a new file at that path. |
367 */ | 418 */ |
368 void _printErrors({String outputPath}) { | 419 void _printErrors({String outputPath}) { |
369 StringBuffer buffer = new StringBuffer(); | 420 StringBuffer buffer = new StringBuffer(); |
370 var severityProcessor = (AnalysisError error) => | 421 var severityProcessor = (AnalysisError error) => |
371 determineProcessedSeverity(error, options, context.analysisOptions); | 422 determineProcessedSeverity(error, options, context.analysisOptions); |
372 ErrorFormatter formatter = options.machineFormat | 423 ErrorFormatter formatter = options.machineFormat |
373 ? new MachineErrorFormatter(buffer, options, stats, | 424 ? new MachineErrorFormatter(buffer, options, stats, |
374 severityProcessor: severityProcessor) | 425 severityProcessor: severityProcessor) |
375 : new HumanErrorFormatter(buffer, options, stats, | 426 : new HumanErrorFormatter(buffer, options, stats, |
376 severityProcessor: severityProcessor); | 427 severityProcessor: severityProcessor); |
377 for (Source source in explicitSources) { | 428 for (Source source in explicitSources) { |
378 AnalysisErrorInfo errorInfo = context.getErrors(source); | 429 AnalysisErrorInfo errorInfo = context.getErrors(source); |
379 formatter.formatErrors([errorInfo]); | 430 formatter.formatErrors([errorInfo]); |
380 } | 431 } |
381 formatter.flush(); | 432 formatter.flush(); |
382 if (!options.machineFormat) { | 433 if (!options.machineFormat) { |
383 stats.print(buffer); | 434 stats.print(buffer); |
384 } | 435 } |
385 if (outputPath == null) { | 436 if (outputPath == null) { |
386 StringSink sink = options.machineFormat ? errorSink : outSink; | 437 StringSink sink = options.machineFormat ? errorSink : outSink; |
387 sink.write(buffer); | 438 sink.write(buffer); |
388 } else { | 439 } else { |
389 new io.File(outputPath).writeAsStringSync(buffer.toString()); | 440 new io.File(outputPath).writeAsStringSync(buffer.toString()); |
390 } | 441 } |
391 } | 442 } |
392 | |
393 /** | |
394 * Serialize the package with the given [sources] into [assembler] using only | |
395 * their ASTs and [LinkedUnit]s of input packages. | |
396 */ | |
397 void _serializeAstBasedSummary(Set<String> unlinkedUris) { | |
398 LinkedLibrary _getDependency(String absoluteUri) => | |
399 summaryDataStore.linkedMap[absoluteUri]; | |
400 | |
401 Map<String, LinkedLibraryBuilder> linkResult = link( | |
402 unlinkedUris, | |
403 _getDependency, | |
404 _unlinkedUnitForUri, | |
405 context.declaredVariables.get, | |
406 options.strongMode); | |
407 linkResult.forEach(assembler.addLinkedLibrary); | |
408 } | |
409 | |
410 /** | |
411 * Returns the [UnlinkedUnit] for [absoluteUri], either by computing it or | |
412 * using the stored one in [uriToUnit]. | |
413 * | |
414 * If the [UnlinkedUnit] needed to be computed, it will also be added to the | |
415 * [assembler]. | |
416 */ | |
417 UnlinkedUnit _unlinkedUnitForUri(String absoluteUri) { | |
418 // Maybe an input package contains the source. | |
419 { | |
420 UnlinkedUnit unlinkedUnit = summaryDataStore.unlinkedMap[absoluteUri]; | |
421 if (unlinkedUnit != null) { | |
422 return unlinkedUnit; | |
423 } | |
424 } | |
425 // Parse the source and serialize its AST. | |
426 Uri uri = Uri.parse(absoluteUri); | |
427 Source source = context.sourceFactory.forUri2(uri); | |
428 if (!source.exists()) { | |
429 // TODO(paulberry): we should report a warning/error because DDC | |
430 // compilations are unlikely to work. | |
431 return null; | |
432 } | |
433 return uriToUnit.putIfAbsent(uri, () { | |
434 CompilationUnit unit = context.computeResult(source, PARSED_UNIT); | |
435 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); | |
436 assembler.addUnlinkedUnit(source, unlinkedUnit); | |
437 return unlinkedUnit; | |
438 }); | |
439 } | |
440 } | 443 } |
441 | 444 |
442 /** | 445 /** |
443 * Instances of the class [ExplicitSourceResolver] map URIs to files on disk | 446 * Instances of the class [ExplicitSourceResolver] map URIs to files on disk |
444 * using a fixed mapping provided at construction time. | 447 * using a fixed mapping provided at construction time. |
445 */ | 448 */ |
446 class ExplicitSourceResolver extends UriResolver { | 449 class ExplicitSourceResolver extends UriResolver { |
447 final Map<Uri, File> uriToFileMap; | 450 final Map<Uri, File> uriToFileMap; |
448 final Map<String, Uri> pathToUriMap; | 451 final Map<String, Uri> pathToUriMap; |
449 | 452 |
(...skipping 25 matching lines...) Expand all Loading... |
475 * Build the inverse mapping of [uriToSourceMap]. | 478 * Build the inverse mapping of [uriToSourceMap]. |
476 */ | 479 */ |
477 static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) { | 480 static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) { |
478 Map<String, Uri> pathToUriMap = <String, Uri>{}; | 481 Map<String, Uri> pathToUriMap = <String, Uri>{}; |
479 uriToSourceMap.forEach((Uri uri, File file) { | 482 uriToSourceMap.forEach((Uri uri, File file) { |
480 pathToUriMap[file.path] = uri; | 483 pathToUriMap[file.path] = uri; |
481 }); | 484 }); |
482 return pathToUriMap; | 485 return pathToUriMap; |
483 } | 486 } |
484 } | 487 } |
OLD | NEW |