Chromium Code Reviews| Index: pkg/analyzer/lib/src/dart/analysis/driver.dart | 
| diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart | 
| index 85d2b396364d69ed68c2b01e52a6b9f107509ceb..e009131b80dfd8d73e7e03b09bf11648019260ff 100644 | 
| --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart | 
| +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart | 
| @@ -236,7 +236,8 @@ class AnalysisDriver { | 
| for (String path in _priorityFiles) { | 
| if (_filesToAnalyze.remove(path)) { | 
| _File file = _fileForPath(path); | 
| - AnalysisResult result = _computeAnalysisResult(file); | 
| + AnalysisResult result = | 
| + _computeAnalysisResult(file, withUnit: true); | 
| yield result; | 
| break; | 
| } | 
| @@ -252,7 +253,7 @@ class AnalysisDriver { | 
| if (_filesToAnalyze.isNotEmpty) { | 
| String path = _removeFirst(_filesToAnalyze); | 
| _File file = _fileForPath(path); | 
| - AnalysisResult result = _computeAnalysisResult(file); | 
| + AnalysisResult result = _computeAnalysisResult(file, withUnit: false); | 
| yield result; | 
| // Repeat the processing loop. | 
| _hasWork.notify(); | 
| @@ -366,10 +367,32 @@ class AnalysisDriver { | 
| /** | 
| * Compute the [AnalysisResult] for the [file]. | 
| + * | 
| + * The result will have the fully resolved unit only if [withUnit] is `true`. | 
| */ | 
| - AnalysisResult _computeAnalysisResult(_File file) { | 
| + AnalysisResult _computeAnalysisResult(_File file, {bool withUnit: false}) { | 
| + // If we don't need to the fully resolved unit, check for a cached result. | 
| + if (!withUnit) { | 
| + AnalysisResult result = _getCachedAnalysisResult(file); | 
| + if (result != null) { | 
| + return result; | 
| + } | 
| + } | 
| + | 
| + // We need the fully resolved unit, or the result is not cached. | 
| return _logger.run('Compute analysis result for $file', () { | 
| _LibraryContext libraryContext = _createLibraryContext(file); | 
| + | 
| + // We recomputed the dependency hash, and we might have a cached result. | 
| + 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.
 
 | 
| + AnalysisResult result = _getCachedAnalysisResult(file); | 
| + if (result != null) { | 
| + _logger.writeln('Return the cached analysis result.'); | 
| + return result; | 
| + } | 
| + } | 
| + | 
| + // Still no result, compute and store it. | 
| AnalysisContext analysisContext = _createAnalysisContext(libraryContext); | 
| try { | 
| analysisContext.setContents(file.source, file.content); | 
| @@ -377,6 +400,25 @@ class AnalysisDriver { | 
| CompilationUnit resolvedUnit = | 
| analysisContext.resolveCompilationUnit2(file.source, file.source); | 
| List<AnalysisError> errors = analysisContext.computeErrors(file.source); | 
| + | 
| + // Store the result into the cache. | 
| + { | 
| + List<int> bytes = new AnalysisDriverResolvedUnitBuilder( | 
| + errors: errors | 
| + .map((error) => new AnalysisDriverUnitErrorBuilder( | 
| + offset: error.offset, | 
| + length: error.length, | 
| + uniqueName: error.errorCode.uniqueName, | 
| + message: error.message, | 
| + correction: error.correction)) | 
| + .toList()) | 
| + .toBuffer(); | 
| + String key = _getResolvedUnitKey(file); | 
| + _byteStore.put(key, bytes); | 
| + } | 
| + | 
| + // Return the full result. | 
| + _logger.writeln('Computed new analysis result.'); | 
| return new AnalysisResult(file.path, file.uri, file.content, | 
| file.contentHash, resolvedUnit, errors); | 
| } finally { | 
| @@ -527,6 +569,47 @@ class AnalysisDriver { | 
| } | 
| /** | 
| + * If we know the dependency signature for the [file], try to load the | 
| + * analysis result from the cache. Return `null` if not found. | 
| + */ | 
| + AnalysisResult _getCachedAnalysisResult(_File file) { | 
| + String key = _getResolvedUnitKey(file); | 
| + if (key != null) { | 
| + List<int> bytes = _byteStore.get(key); | 
| + if (bytes != null) { | 
| + var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes); | 
| + List<AnalysisError> errors = unit.errors | 
| + .map((error) => new AnalysisError.forValues( | 
| + file.source, | 
| + error.offset, | 
| + error.length, | 
| + ErrorCode.byUniqueName(error.uniqueName), | 
| + error.message, | 
| + error.correction)) | 
| + .toList(); | 
| + return new AnalysisResult( | 
| + file.path, file.uri, null, file.contentHash, null, errors); | 
| + } | 
| + } | 
| + return null; | 
| + } | 
| + | 
| + /** | 
| + * Return the key to store fully resolved results for the [file] into the | 
| + * cache. Return `null` if the dependency signature is not known yet. | 
| + */ | 
| + String _getResolvedUnitKey(_File file) { | 
| + String dependencyHash = _dependencySignatureMap[file.uri]; | 
| + if (dependencyHash != null) { | 
| + ApiSignature signature = new ApiSignature(); | 
| + signature.addString(dependencyHash); | 
| + signature.addString(file.contentHash); | 
| + return '${signature.toHex()}.resolved'; | 
| + } | 
| + return null; | 
| + } | 
| + | 
| + /** | 
| * Verify the API signature for the file with the given [path], and decide | 
| * which linked libraries should be invalidated, and files reanalyzed. | 
| * |