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:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:convert'; | 7 import 'dart:convert'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 } | 229 } |
230 | 230 |
231 // TODO(scheglov) analyze requested files | 231 // TODO(scheglov) analyze requested files |
232 | 232 |
233 // Analyze a priority file. | 233 // Analyze a priority file. |
234 if (_priorityFiles.isNotEmpty) { | 234 if (_priorityFiles.isNotEmpty) { |
235 bool analyzed = false; | 235 bool analyzed = false; |
236 for (String path in _priorityFiles) { | 236 for (String path in _priorityFiles) { |
237 if (_filesToAnalyze.remove(path)) { | 237 if (_filesToAnalyze.remove(path)) { |
238 _File file = _fileForPath(path); | 238 _File file = _fileForPath(path); |
239 AnalysisResult result = _computeAnalysisResult(file); | 239 AnalysisResult result = |
240 _computeAnalysisResult(file, withUnit: true); | |
240 yield result; | 241 yield result; |
241 break; | 242 break; |
242 } | 243 } |
243 } | 244 } |
244 // Repeat the processing loop. | 245 // Repeat the processing loop. |
245 if (analyzed) { | 246 if (analyzed) { |
246 _hasWork.notify(); | 247 _hasWork.notify(); |
247 continue; | 248 continue; |
248 } | 249 } |
249 } | 250 } |
250 | 251 |
251 // Analyze a general file. | 252 // Analyze a general file. |
252 if (_filesToAnalyze.isNotEmpty) { | 253 if (_filesToAnalyze.isNotEmpty) { |
253 String path = _removeFirst(_filesToAnalyze); | 254 String path = _removeFirst(_filesToAnalyze); |
254 _File file = _fileForPath(path); | 255 _File file = _fileForPath(path); |
255 AnalysisResult result = _computeAnalysisResult(file); | 256 AnalysisResult result = _computeAnalysisResult(file, withUnit: false); |
256 yield result; | 257 yield result; |
257 // Repeat the processing loop. | 258 // Repeat the processing loop. |
258 _hasWork.notify(); | 259 _hasWork.notify(); |
259 continue; | 260 continue; |
260 } | 261 } |
261 | 262 |
262 // There is nothing to do. | 263 // There is nothing to do. |
263 analysisSection.exit(); | 264 analysisSection.exit(); |
264 analysisSection = null; | 265 analysisSection = null; |
265 } | 266 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 * | 360 * |
360 * We need to clean this up. | 361 * We need to clean this up. |
361 */ | 362 */ |
362 void _addToStoreUnlinked( | 363 void _addToStoreUnlinked( |
363 SummaryDataStore store, String uri, UnlinkedUnit unlinked) { | 364 SummaryDataStore store, String uri, UnlinkedUnit unlinked) { |
364 store.unlinkedMap[uri] = unlinked; | 365 store.unlinkedMap[uri] = unlinked; |
365 } | 366 } |
366 | 367 |
367 /** | 368 /** |
368 * Compute the [AnalysisResult] for the [file]. | 369 * Compute the [AnalysisResult] for the [file]. |
370 * | |
371 * The result will have the fully resolved unit only if [withUnit] is `true`. | |
369 */ | 372 */ |
370 AnalysisResult _computeAnalysisResult(_File file) { | 373 AnalysisResult _computeAnalysisResult(_File file, {bool withUnit: false}) { |
374 // If we don't need to the fully resolved unit, check for a cached result. | |
375 if (!withUnit) { | |
376 AnalysisResult result = _getCachedAnalysisResult(file); | |
377 if (result != null) { | |
378 return result; | |
379 } | |
380 } | |
381 | |
382 // We need the fully resolved unit, or the result is not cached. | |
371 return _logger.run('Compute analysis result for $file', () { | 383 return _logger.run('Compute analysis result for $file', () { |
372 _LibraryContext libraryContext = _createLibraryContext(file); | 384 _LibraryContext libraryContext = _createLibraryContext(file); |
385 | |
386 // We recomputed the dependency hash, and we might have a cached result. | |
387 if (!withUnit) { | |
Paul Berry
2016/10/31 17:02:53
AFAICT this block will never execute, since the sa
scheglov
2016/10/31 17:07:06
Both this block and the block in lines 375-380 use
Paul Berry
2016/10/31 21:35:34
Ok, I understand now. Thanks.
| |
388 AnalysisResult result = _getCachedAnalysisResult(file); | |
389 if (result != null) { | |
390 _logger.writeln('Return the cached analysis result.'); | |
391 return result; | |
392 } | |
393 } | |
394 | |
395 // Still no result, compute and store it. | |
373 AnalysisContext analysisContext = _createAnalysisContext(libraryContext); | 396 AnalysisContext analysisContext = _createAnalysisContext(libraryContext); |
374 try { | 397 try { |
375 analysisContext.setContents(file.source, file.content); | 398 analysisContext.setContents(file.source, file.content); |
376 // TODO(scheglov) Add support for parts. | 399 // TODO(scheglov) Add support for parts. |
377 CompilationUnit resolvedUnit = | 400 CompilationUnit resolvedUnit = |
378 analysisContext.resolveCompilationUnit2(file.source, file.source); | 401 analysisContext.resolveCompilationUnit2(file.source, file.source); |
379 List<AnalysisError> errors = analysisContext.computeErrors(file.source); | 402 List<AnalysisError> errors = analysisContext.computeErrors(file.source); |
403 | |
404 // Store the result into the cache. | |
405 { | |
406 List<int> bytes = new AnalysisDriverResolvedUnitBuilder( | |
407 errors: errors | |
408 .map((error) => new AnalysisDriverUnitErrorBuilder( | |
409 offset: error.offset, | |
410 length: error.length, | |
411 uniqueName: error.errorCode.uniqueName, | |
412 message: error.message, | |
413 correction: error.correction)) | |
414 .toList()) | |
415 .toBuffer(); | |
416 String key = _getResolvedUnitKey(file); | |
417 _byteStore.put(key, bytes); | |
418 } | |
419 | |
420 // Return the full result. | |
421 _logger.writeln('Computed new analysis result.'); | |
380 return new AnalysisResult(file.path, file.uri, file.content, | 422 return new AnalysisResult(file.path, file.uri, file.content, |
381 file.contentHash, resolvedUnit, errors); | 423 file.contentHash, resolvedUnit, errors); |
382 } finally { | 424 } finally { |
383 analysisContext.dispose(); | 425 analysisContext.dispose(); |
384 } | 426 } |
385 }); | 427 }); |
386 } | 428 } |
387 | 429 |
388 AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) { | 430 AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) { |
389 AnalysisContextImpl analysisContext = | 431 AnalysisContextImpl analysisContext = |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 * Return the [_File] for the given [path] in [_sourceFactory]. | 562 * Return the [_File] for the given [path] in [_sourceFactory]. |
521 */ | 563 */ |
522 _File _fileForPath(String path) { | 564 _File _fileForPath(String path) { |
523 Source fileSource = _resourceProvider.getFile(path).createSource(); | 565 Source fileSource = _resourceProvider.getFile(path).createSource(); |
524 Uri uri = _sourceFactory.restoreUri(fileSource); | 566 Uri uri = _sourceFactory.restoreUri(fileSource); |
525 Source source = _resourceProvider.getFile(path).createSource(uri); | 567 Source source = _resourceProvider.getFile(path).createSource(uri); |
526 return new _File.forResolution(this, source); | 568 return new _File.forResolution(this, source); |
527 } | 569 } |
528 | 570 |
529 /** | 571 /** |
572 * If we know the dependency signature for the [file], try to load the | |
573 * analysis result from the cache. Return `null` if not found. | |
574 */ | |
575 AnalysisResult _getCachedAnalysisResult(_File file) { | |
576 String key = _getResolvedUnitKey(file); | |
577 if (key != null) { | |
578 List<int> bytes = _byteStore.get(key); | |
579 if (bytes != null) { | |
580 var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes); | |
581 List<AnalysisError> errors = unit.errors | |
582 .map((error) => new AnalysisError.forValues( | |
583 file.source, | |
584 error.offset, | |
585 error.length, | |
586 ErrorCode.byUniqueName(error.uniqueName), | |
587 error.message, | |
588 error.correction)) | |
589 .toList(); | |
590 return new AnalysisResult( | |
591 file.path, file.uri, null, file.contentHash, null, errors); | |
592 } | |
593 } | |
594 return null; | |
595 } | |
596 | |
597 /** | |
598 * Return the key to store fully resolved results for the [file] into the | |
599 * cache. Return `null` if the dependency signature is not known yet. | |
600 */ | |
601 String _getResolvedUnitKey(_File file) { | |
602 String dependencyHash = _dependencySignatureMap[file.uri]; | |
603 if (dependencyHash != null) { | |
604 ApiSignature signature = new ApiSignature(); | |
605 signature.addString(dependencyHash); | |
606 signature.addString(file.contentHash); | |
607 return '${signature.toHex()}.resolved'; | |
608 } | |
609 return null; | |
610 } | |
611 | |
612 /** | |
530 * Verify the API signature for the file with the given [path], and decide | 613 * Verify the API signature for the file with the given [path], and decide |
531 * which linked libraries should be invalidated, and files reanalyzed. | 614 * which linked libraries should be invalidated, and files reanalyzed. |
532 * | 615 * |
533 * TODO(scheglov) I see that adding a local var changes (full) API signature. | 616 * TODO(scheglov) I see that adding a local var changes (full) API signature. |
534 */ | 617 */ |
535 void _verifyApiSignatureOfChangedFile(String path) { | 618 void _verifyApiSignatureOfChangedFile(String path) { |
536 _logger.run('Verify API signature of $path', () { | 619 _logger.run('Verify API signature of $path', () { |
537 String oldSignature = _fileApiSignatureMap[path]; | 620 String oldSignature = _fileApiSignatureMap[path]; |
538 // Compute the new API signature. | 621 // Compute the new API signature. |
539 // _File.forResolution() also updates the content hash in the cache. | 622 // _File.forResolution() also updates the content hash in the cache. |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 } | 1082 } |
1000 } | 1083 } |
1001 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | 1084 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { |
1002 referenced.exported.add(export.uri); | 1085 referenced.exported.add(export.uri); |
1003 } | 1086 } |
1004 return referenced; | 1087 return referenced; |
1005 } | 1088 } |
1006 | 1089 |
1007 _ReferencedUris._(); | 1090 _ReferencedUris._(); |
1008 } | 1091 } |
OLD | NEW |