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