Chromium Code Reviews| 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 |