Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: pkg/analyzer_cli/lib/src/build_mode.dart

Issue 2996773002: Decorate build mode with using PerformanceLog. (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/error/error.dart'; 10 import 'package:analyzer/error/error.dart';
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 /** 127 /**
128 * Analyzer used when the "--build-mode" option is supplied. 128 * Analyzer used when the "--build-mode" option is supplied.
129 */ 129 */
130 class BuildMode { 130 class BuildMode {
131 final ResourceProvider resourceProvider; 131 final ResourceProvider resourceProvider;
132 final CommandLineOptions options; 132 final CommandLineOptions options;
133 final AnalysisStats stats; 133 final AnalysisStats stats;
134 134
135 SummaryDataStore summaryDataStore; 135 SummaryDataStore summaryDataStore;
136 AnalysisOptions analysisOptions; 136 AnalysisOptions analysisOptions;
137 AnalysisDriver analysisDriver;
138 Map<Uri, File> uriToFileMap; 137 Map<Uri, File> uriToFileMap;
139 final List<Source> explicitSources = <Source>[]; 138 final List<Source> explicitSources = <Source>[];
140 final List<PackageBundle> unlinkedBundles = <PackageBundle>[]; 139 final List<PackageBundle> unlinkedBundles = <PackageBundle>[];
141 140
141 PerformanceLog logger = new PerformanceLog(null);
142 AnalysisDriver analysisDriver;
143
142 PackageBundleAssembler assembler; 144 PackageBundleAssembler assembler;
143 final Set<Source> processedSources = new Set<Source>(); 145 final Set<Source> processedSources = new Set<Source>();
144 final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{}; 146 final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
145 147
146 BuildMode(this.resourceProvider, this.options, this.stats); 148 BuildMode(this.resourceProvider, this.options, this.stats);
147 149
148 bool get _shouldOutputSummary => 150 bool get _shouldOutputSummary =>
149 options.buildSummaryOutput != null || 151 options.buildSummaryOutput != null ||
150 options.buildSummaryOutputSemantic != null; 152 options.buildSummaryOutputSemantic != null;
151 153
152 /** 154 /**
153 * Perform package analysis according to the given [options]. 155 * Perform package analysis according to the given [options].
154 */ 156 */
155 Future<ErrorSeverity> analyze() async { 157 Future<ErrorSeverity> analyze() async {
156 // Write initial progress message. 158 return await logger.runAsync('Analyze', () async {
157 if (!options.machineFormat) { 159 // Write initial progress message.
158 outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}..."); 160 if (!options.machineFormat) {
159 } 161 outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}...");
162 }
160 163
161 // Create the URI to file map. 164 // Create the URI to file map.
162 uriToFileMap = _createUriToFileMap(options.sourceFiles); 165 uriToFileMap = _createUriToFileMap(options.sourceFiles);
163 if (uriToFileMap == null) { 166 if (uriToFileMap == null) {
164 io.exitCode = ErrorSeverity.ERROR.ordinal;
165 return ErrorSeverity.ERROR;
166 }
167
168 // BuildMode expects sourceFiles in the format "<uri>|<filepath>",
169 // but the rest of the code base does not understand this format.
170 // Rewrite sourceFiles, stripping the "<uri>|" prefix, so that it
171 // does not cause problems with code that does not expect this format.
172 options.rewriteSourceFiles(options.sourceFiles
173 .map((String uriPipePath) =>
174 uriPipePath.substring(uriPipePath.indexOf('|') + 1))
175 .toList());
176
177 // Prepare the analysis driver.
178 try {
179 _createAnalysisDriver();
180 } on ConflictingSummaryException catch (e) {
181 errorSink.writeln('$e');
182 io.exitCode = ErrorSeverity.ERROR.ordinal;
183 return ErrorSeverity.ERROR;
184 }
185
186 // Add sources.
187 for (Uri uri in uriToFileMap.keys) {
188 File file = uriToFileMap[uri];
189 if (!file.exists) {
190 errorSink.writeln('File not found: ${file.path}');
191 io.exitCode = ErrorSeverity.ERROR.ordinal; 167 io.exitCode = ErrorSeverity.ERROR.ordinal;
192 return ErrorSeverity.ERROR; 168 return ErrorSeverity.ERROR;
193 } 169 }
194 Source source = new FileSource(file, uri);
195 explicitSources.add(source);
196 }
197 170
198 // Write summary. 171 // BuildMode expects sourceFiles in the format "<uri>|<filepath>",
199 assembler = new PackageBundleAssembler(); 172 // but the rest of the code base does not understand this format.
200 if (_shouldOutputSummary) { 173 // Rewrite sourceFiles, stripping the "<uri>|" prefix, so that it
201 // Prepare all unlinked units. 174 // does not cause problems with code that does not expect this format.
202 for (var src in explicitSources) { 175 options.rewriteSourceFiles(options.sourceFiles
203 await _prepareUnlinkedUnit('${src.uri}'); 176 .map((String uriPipePath) =>
177 uriPipePath.substring(uriPipePath.indexOf('|') + 1))
178 .toList());
179
180 // Prepare the analysis driver.
181 try {
182 logger.run('Prepare analysis driver', () {
183 _createAnalysisDriver();
184 });
185 } on ConflictingSummaryException catch (e) {
186 errorSink.writeln('$e');
187 io.exitCode = ErrorSeverity.ERROR.ordinal;
188 return ErrorSeverity.ERROR;
204 } 189 }
205 190
206 // Build and assemble linked libraries. 191 // Add sources.
207 if (!options.buildSummaryOnlyUnlinked) { 192 for (Uri uri in uriToFileMap.keys) {
208 // Prepare URIs of unlinked units that should be linked. 193 File file = uriToFileMap[uri];
209 var unlinkedUris = new Set<String>(); 194 if (!file.exists) {
210 for (var bundle in unlinkedBundles) { 195 errorSink.writeln('File not found: ${file.path}');
211 unlinkedUris.addAll(bundle.unlinkedUnitUris); 196 io.exitCode = ErrorSeverity.ERROR.ordinal;
197 return ErrorSeverity.ERROR;
212 } 198 }
213 for (var src in explicitSources) { 199 Source source = new FileSource(file, uri);
214 unlinkedUris.add('${src.uri}'); 200 explicitSources.add(source);
215 }
216 // Perform linking.
217 _computeLinkedLibraries(unlinkedUris);
218 assembler.recordDependencies(summaryDataStore);
219 } 201 }
220 202
221 // Write the whole package bundle. 203 // Write summary.
222 PackageBundleBuilder bundle = assembler.assemble(); 204 assembler = new PackageBundleAssembler();
223 if (options.buildSummaryOutput != null) { 205 if (_shouldOutputSummary) {
224 io.File file = new io.File(options.buildSummaryOutput); 206 await logger.runAsync('Build and write output summary', () async {
225 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); 207 // Prepare all unlinked units.
208 await logger.runAsync('Prepare unlinked units', () async {
209 for (var src in explicitSources) {
210 await _prepareUnlinkedUnit('${src.uri}');
211 }
212 });
213
214 // Build and assemble linked libraries.
215 if (!options.buildSummaryOnlyUnlinked) {
216 // Prepare URIs of unlinked units that should be linked.
217 var unlinkedUris = new Set<String>();
218 for (var bundle in unlinkedBundles) {
219 unlinkedUris.addAll(bundle.unlinkedUnitUris);
220 }
221 for (var src in explicitSources) {
222 unlinkedUris.add('${src.uri}');
223 }
224 // Perform linking.
225 _computeLinkedLibraries(unlinkedUris);
226 assembler.recordDependencies(summaryDataStore);
227 }
228
229 // Write the whole package bundle.
230 PackageBundleBuilder bundle = assembler.assemble();
231 if (options.buildSummaryOutput != null) {
232 io.File file = new io.File(options.buildSummaryOutput);
233 file.writeAsBytesSync(bundle.toBuffer(),
234 mode: io.FileMode.WRITE_ONLY);
235 }
236 if (options.buildSummaryOutputSemantic != null) {
237 bundle.flushInformative();
238 io.File file = new io.File(options.buildSummaryOutputSemantic);
239 file.writeAsBytesSync(bundle.toBuffer(),
240 mode: io.FileMode.WRITE_ONLY);
241 }
242 });
226 } 243 }
227 if (options.buildSummaryOutputSemantic != null) { 244
228 bundle.flushInformative(); 245 if (options.buildSummaryOnly) {
229 io.File file = new io.File(options.buildSummaryOutputSemantic); 246 return ErrorSeverity.NONE;
230 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); 247 } else {
248 // Process errors.
249 await _printErrors(outputPath: options.buildAnalysisOutput);
250 return await _computeMaxSeverity();
231 } 251 }
232 } 252 });
233
234 if (options.buildSummaryOnly) {
235 return ErrorSeverity.NONE;
236 } else {
237 // Process errors.
238 await _printErrors(outputPath: options.buildAnalysisOutput);
239 return await _computeMaxSeverity();
240 }
241 } 253 }
242 254
243 /** 255 /**
244 * Compute linked libraries for the given [libraryUris] using the linked 256 * Compute linked libraries for the given [libraryUris] using the linked
245 * libraries of the [summaryDataStore] and unlinked units in [uriToUnit], and 257 * libraries of the [summaryDataStore] and unlinked units in [uriToUnit], and
246 * add them to the [assembler]. 258 * add them to the [assembler].
247 */ 259 */
248 void _computeLinkedLibraries(Set<String> libraryUris) { 260 void _computeLinkedLibraries(Set<String> libraryUris) {
249 LinkedLibrary getDependency(String absoluteUri) => 261 logger.run('Link output summary', () {
250 summaryDataStore.linkedMap[absoluteUri]; 262 LinkedLibrary getDependency(String absoluteUri) =>
263 summaryDataStore.linkedMap[absoluteUri];
251 264
252 UnlinkedUnit getUnit(String absoluteUri) => 265 UnlinkedUnit getUnit(String absoluteUri) =>
253 summaryDataStore.unlinkedMap[absoluteUri] ?? uriToUnit[absoluteUri]; 266 summaryDataStore.unlinkedMap[absoluteUri] ?? uriToUnit[absoluteUri];
254 267
255 Map<String, LinkedLibraryBuilder> linkResult = link( 268 Map<String, LinkedLibraryBuilder> linkResult = link(
256 libraryUris, 269 libraryUris,
257 getDependency, 270 getDependency,
258 getUnit, 271 getUnit,
259 analysisDriver.declaredVariables.get, 272 analysisDriver.declaredVariables.get,
260 options.strongMode); 273 options.strongMode);
261 linkResult.forEach(assembler.addLinkedLibrary); 274 linkResult.forEach(assembler.addLinkedLibrary);
275 });
262 } 276 }
263 277
264 Future<ErrorSeverity> _computeMaxSeverity() async { 278 Future<ErrorSeverity> _computeMaxSeverity() async {
265 ErrorSeverity maxSeverity = ErrorSeverity.NONE; 279 ErrorSeverity maxSeverity = ErrorSeverity.NONE;
266 if (!options.buildSuppressExitCode) { 280 if (!options.buildSuppressExitCode) {
267 for (Source source in explicitSources) { 281 for (Source source in explicitSources) {
268 ErrorsResult result = await analysisDriver.getErrors(source.fullName); 282 ErrorsResult result = await analysisDriver.getErrors(source.fullName);
269 for (AnalysisError error in result.errors) { 283 for (AnalysisError error in result.errors) {
270 ErrorSeverity processedSeverity = determineProcessedSeverity( 284 ErrorSeverity processedSeverity = determineProcessedSeverity(
271 error, options, analysisDriver.analysisOptions); 285 error, options, analysisDriver.analysisOptions);
(...skipping 12 matching lines...) Expand all
284 recordDependencyInfo: _shouldOutputSummary); 298 recordDependencyInfo: _shouldOutputSummary);
285 299
286 // Adds a bundle at `path` to `summaryDataStore`. 300 // Adds a bundle at `path` to `summaryDataStore`.
287 PackageBundle addBundle(String path) { 301 PackageBundle addBundle(String path) {
288 var bundle = 302 var bundle =
289 new PackageBundle.fromBuffer(new io.File(path).readAsBytesSync()); 303 new PackageBundle.fromBuffer(new io.File(path).readAsBytesSync());
290 summaryDataStore.addBundle(path, bundle); 304 summaryDataStore.addBundle(path, bundle);
291 return bundle; 305 return bundle;
292 } 306 }
293 307
294 for (var path in options.buildSummaryInputs) { 308 int numInputs = options.buildSummaryInputs.length +
295 var bundle = addBundle(path); 309 options.buildSummaryUnlinkedInputs.length;
296 if (bundle.linkedLibraryUris.isEmpty && 310 logger.run('Add $numInputs input summaries', () {
297 bundle.unlinkedUnitUris.isNotEmpty) { 311 for (var path in options.buildSummaryInputs) {
298 throw new ArgumentError( 312 var bundle = addBundle(path);
299 'Got an unlinked summary for --build-summary-input at `$path`. ' 313 if (bundle.linkedLibraryUris.isEmpty &&
300 'Unlinked summaries should be provided with the ' 314 bundle.unlinkedUnitUris.isNotEmpty) {
301 '--build-summary-unlinked-input argument.'); 315 throw new ArgumentError(
316 'Got an unlinked summary for --build-summary-input at `$path`. '
317 'Unlinked summaries should be provided with the '
318 '--build-summary-unlinked-input argument.');
319 }
302 } 320 }
303 }
304 321
305 for (var path in options.buildSummaryUnlinkedInputs) { 322 for (var path in options.buildSummaryUnlinkedInputs) {
306 var bundle = addBundle(path); 323 var bundle = addBundle(path);
307 unlinkedBundles.add(bundle); 324 unlinkedBundles.add(bundle);
308 if (bundle.linkedLibraryUris.isNotEmpty) { 325 if (bundle.linkedLibraryUris.isNotEmpty) {
309 throw new ArgumentError( 326 throw new ArgumentError(
310 'Got a linked summary for --build-summary-input-unlinked at `$path`' 327 'Got a linked summary for --build-summary-input-unlinked at `$path `'
311 '. Linked bundles should be provided with the ' 328 '. Linked bundles should be provided with the '
312 '--build-summary-input argument.'); 329 '--build-summary-input argument.');
330 }
313 } 331 }
314 } 332 });
315 333
316 DartSdk sdk; 334 DartSdk sdk;
317 PackageBundle sdkBundle; 335 logger.run('Add SDK bundle', () {
318 if (options.dartSdkSummaryPath != null) { 336 PackageBundle sdkBundle;
319 SummaryBasedDartSdk summarySdk = new SummaryBasedDartSdk( 337 if (options.dartSdkSummaryPath != null) {
320 options.dartSdkSummaryPath, options.strongMode); 338 SummaryBasedDartSdk summarySdk = new SummaryBasedDartSdk(
321 sdk = summarySdk; 339 options.dartSdkSummaryPath, options.strongMode);
322 sdkBundle = summarySdk.bundle; 340 sdk = summarySdk;
323 } else { 341 sdkBundle = summarySdk.bundle;
324 FolderBasedDartSdk dartSdk = new FolderBasedDartSdk(resourceProvider, 342 } else {
325 resourceProvider.getFolder(options.dartSdkPath), options.strongMode); 343 FolderBasedDartSdk dartSdk = new FolderBasedDartSdk(
326 dartSdk.analysisOptions = 344 resourceProvider,
327 Driver.createAnalysisOptionsForCommandLineOptions( 345 resourceProvider.getFolder(options.dartSdkPath),
328 resourceProvider, options); 346 options.strongMode);
329 dartSdk.useSummary = !options.buildSummaryOnly; 347 dartSdk.analysisOptions =
330 sdk = dartSdk; 348 Driver.createAnalysisOptionsForCommandLineOptions(
331 sdkBundle = dartSdk.getSummarySdkBundle(options.strongMode); 349 resourceProvider, options);
332 } 350 dartSdk.useSummary = !options.buildSummaryOnly;
351 sdk = dartSdk;
352 sdkBundle = dartSdk.getSummarySdkBundle(options.strongMode);
353 }
333 354
334 // Include SDK bundle to avoid parsing SDK sources. 355 // Include SDK bundle to avoid parsing SDK sources.
335 summaryDataStore.addBundle(null, sdkBundle); 356 summaryDataStore.addBundle(null, sdkBundle);
357 });
336 358
337 var sourceFactory = new SourceFactory(<UriResolver>[ 359 var sourceFactory = new SourceFactory(<UriResolver>[
338 new DartUriResolver(sdk), 360 new DartUriResolver(sdk),
339 new InSummaryUriResolver(resourceProvider, summaryDataStore), 361 new InSummaryUriResolver(resourceProvider, summaryDataStore),
340 new ExplicitSourceResolver(uriToFileMap) 362 new ExplicitSourceResolver(uriToFileMap)
341 ]); 363 ]);
342 364
343 analysisOptions = Driver.createAnalysisOptionsForCommandLineOptions( 365 analysisOptions = Driver.createAnalysisOptionsForCommandLineOptions(
344 resourceProvider, options); 366 resourceProvider, options);
345 367
346 PerformanceLog logger = new PerformanceLog(null);
347 AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger); 368 AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger);
348 analysisDriver = new AnalysisDriver( 369 analysisDriver = new AnalysisDriver(
349 scheduler, 370 scheduler,
350 logger, 371 logger,
351 resourceProvider, 372 resourceProvider,
352 new MemoryByteStore(), 373 new MemoryByteStore(),
353 new FileContentOverlay(), 374 new FileContentOverlay(),
354 null, 375 null,
355 sourceFactory, 376 sourceFactory,
356 analysisOptions, 377 analysisOptions,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit); 427 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit);
407 uriToUnit[absoluteUri] = unlinkedUnit; 428 uriToUnit[absoluteUri] = unlinkedUnit;
408 assembler.addUnlinkedUnit(source, unlinkedUnit); 429 assembler.addUnlinkedUnit(source, unlinkedUnit);
409 } 430 }
410 431
411 /** 432 /**
412 * Print errors for all explicit sources. If [outputPath] is supplied, output 433 * Print errors for all explicit sources. If [outputPath] is supplied, output
413 * is sent to a new file at that path. 434 * is sent to a new file at that path.
414 */ 435 */
415 Future<Null> _printErrors({String outputPath}) async { 436 Future<Null> _printErrors({String outputPath}) async {
416 StringBuffer buffer = new StringBuffer(); 437 await logger.runAsync('Compute and print analysis errors', () async {
417 var severityProcessor = (AnalysisError error) => 438 StringBuffer buffer = new StringBuffer();
418 determineProcessedSeverity(error, options, analysisOptions); 439 var severityProcessor = (AnalysisError error) =>
419 ErrorFormatter formatter = options.machineFormat 440 determineProcessedSeverity(error, options, analysisOptions);
420 ? new MachineErrorFormatter(buffer, options, stats, 441 ErrorFormatter formatter = options.machineFormat
421 severityProcessor: severityProcessor) 442 ? new MachineErrorFormatter(buffer, options, stats,
422 : new HumanErrorFormatter(buffer, options, stats, 443 severityProcessor: severityProcessor)
423 severityProcessor: severityProcessor); 444 : new HumanErrorFormatter(buffer, options, stats,
424 for (Source source in explicitSources) { 445 severityProcessor: severityProcessor);
425 var result = await analysisDriver.getErrors(source.fullName); 446 for (Source source in explicitSources) {
426 var errorInfo = new AnalysisErrorInfoImpl(result.errors, result.lineInfo); 447 var result = await analysisDriver.getErrors(source.fullName);
427 formatter.formatErrors([errorInfo]); 448 var errorInfo =
428 } 449 new AnalysisErrorInfoImpl(result.errors, result.lineInfo);
429 formatter.flush(); 450 formatter.formatErrors([errorInfo]);
430 if (!options.machineFormat) { 451 }
431 stats.print(buffer); 452 formatter.flush();
432 } 453 if (!options.machineFormat) {
433 if (outputPath == null) { 454 stats.print(buffer);
434 StringSink sink = options.machineFormat ? errorSink : outSink; 455 }
435 sink.write(buffer); 456 if (outputPath == null) {
436 } else { 457 StringSink sink = options.machineFormat ? errorSink : outSink;
437 new io.File(outputPath).writeAsStringSync(buffer.toString()); 458 sink.write(buffer);
438 } 459 } else {
460 new io.File(outputPath).writeAsStringSync(buffer.toString());
461 }
462 });
439 } 463 }
440 } 464 }
441 465
442 /** 466 /**
443 * Instances of the class [ExplicitSourceResolver] map URIs to files on disk 467 * Instances of the class [ExplicitSourceResolver] map URIs to files on disk
444 * using a fixed mapping provided at construction time. 468 * using a fixed mapping provided at construction time.
445 */ 469 */
446 class ExplicitSourceResolver extends UriResolver { 470 class ExplicitSourceResolver extends UriResolver {
447 final Map<Uri, File> uriToFileMap; 471 final Map<Uri, File> uriToFileMap;
448 final Map<String, Uri> pathToUriMap; 472 final Map<String, Uri> pathToUriMap;
(...skipping 26 matching lines...) Expand all
475 * Build the inverse mapping of [uriToSourceMap]. 499 * Build the inverse mapping of [uriToSourceMap].
476 */ 500 */
477 static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) { 501 static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) {
478 Map<String, Uri> pathToUriMap = <String, Uri>{}; 502 Map<String, Uri> pathToUriMap = <String, Uri>{};
479 uriToSourceMap.forEach((Uri uri, File file) { 503 uriToSourceMap.forEach((Uri uri, File file) {
480 pathToUriMap[file.path] = uri; 504 pathToUriMap[file.path] = uri;
481 }); 505 });
482 return pathToUriMap; 506 return pathToUriMap;
483 } 507 }
484 } 508 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698