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 8931939e2c2489b2a3df293b4dd1861d4a155ba7..626db924cc635a829c56eb9cf91b95750a78008a 100644 |
| --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart |
| +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart |
| @@ -209,6 +209,11 @@ class AnalysisDriver { |
| final _resultController = new StreamController<AnalysisResult>(); |
| /** |
| + * Resolution signatures of the most recently produced results for files. |
| + */ |
| + final Map<String, String> _lastProducedSignatures = {}; |
| + |
| + /** |
| * Cached results for [_priorityFiles]. |
| */ |
| final Map<String, AnalysisResult> _priorityResults = {}; |
| @@ -697,7 +702,9 @@ class AnalysisDriver { |
| * analyzed anyway, even without a library. |
| */ |
| AnalysisResult _computeAnalysisResult(String path, |
| - {bool withUnit: false, bool asIsIfPartWithoutLibrary: false}) { |
| + {bool withUnit: false, |
| + bool asIsIfPartWithoutLibrary: false, |
| + bool skipIfSameSignature: false}) { |
|
Brian Wilkerson
2017/02/18 17:40:03
Document what "skipIfSameSignature" does.
scheglov
2017/02/18 20:15:45
Done.
|
| FileState file = _fileTracker.fsState.getFileForPath(path); |
| // Prepare the library - the file itself, or the known library. |
| @@ -710,12 +717,23 @@ class AnalysisDriver { |
| } |
| } |
| + // Prepare the signature and key. |
| + String signature = _getResolvedUnitSignature(library, file); |
| + String key = _getResolvedUnitKey(signature); |
| + |
| + // Skip reading if the signature, so errors, are the same as the last time. |
| + if (skipIfSameSignature) { |
| + assert(!withUnit); |
| + if (_lastProducedSignatures[path] == signature) { |
| + return AnalysisResult._SAME_ERRORS; |
| + } |
| + } |
| + |
| // If we don't need the fully resolved unit, check for the cached result. |
| if (!withUnit) { |
| - String key = _getResolvedUnitKey(library, file); |
| List<int> bytes = _byteStore.get(key); |
| if (bytes != null) { |
| - return _getAnalysisResultFromBytes(file, bytes); |
| + return _getAnalysisResultFromBytes(file, signature, bytes); |
| } |
| } |
| @@ -737,8 +755,12 @@ class AnalysisDriver { |
| Map<FileState, UnitAnalysisResult> results = analyzer.analyze(); |
| for (FileState unitFile in results.keys) { |
| UnitAnalysisResult unitResult = results[unitFile]; |
| - List<int> unitBytes = _storeResolvedUnit( |
| - library, unitFile, unitResult.unit, unitResult.errors); |
| + List<int> unitBytes = |
| + _serializeResolvedUnit(unitResult.unit, unitResult.errors); |
| + String unitSignature = |
| + _getResolvedUnitSignature(library, unitFile); |
| + String unitKey = _getResolvedUnitKey(unitSignature); |
| + _byteStore.put(unitKey, unitBytes); |
| if (unitFile == file) { |
| bytes = unitBytes; |
| resolvedUnit = unitResult.unit; |
| @@ -751,12 +773,14 @@ class AnalysisDriver { |
| List<AnalysisError> errors = resolutionResult.errors; |
| // Store the result into the cache. |
| - bytes = _storeResolvedUnit(library, file, resolvedUnit, errors); |
| + bytes = _serializeResolvedUnit(resolvedUnit, errors); |
| + _byteStore.put(key, bytes); |
| } |
| // Return the result, full or partial. |
| _logger.writeln('Computed new analysis result.'); |
| - AnalysisResult result = _getAnalysisResultFromBytes(file, bytes, |
| + AnalysisResult result = _getAnalysisResultFromBytes( |
| + file, signature, bytes, |
| content: withUnit ? file.content : null, |
| withErrors: _fileTracker.addedFiles.contains(path), |
| resolvedUnit: withUnit ? resolvedUnit : null); |
| @@ -847,7 +871,8 @@ class AnalysisDriver { |
| * Load the [AnalysisResult] for the given [file] from the [bytes]. Set |
| * optional [content] and [resolvedUnit]. |
| */ |
| - AnalysisResult _getAnalysisResultFromBytes(FileState file, List<int> bytes, |
| + AnalysisResult _getAnalysisResultFromBytes( |
| + FileState file, String signature, List<int> bytes, |
| {String content, bool withErrors: true, CompilationUnit resolvedUnit}) { |
| var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes); |
| List<AnalysisError> errors = withErrors |
| @@ -862,6 +887,7 @@ class AnalysisDriver { |
| content, |
| file.contentHash, |
| file.lineInfo, |
| + signature, |
| resolvedUnit, |
| errors, |
| unit.index); |
| @@ -888,11 +914,9 @@ class AnalysisDriver { |
| } |
| /** |
| - * Return the key to store fully resolved results for the [file] in the |
| - * [library] into the cache. |
| + * Return the key to store fully resolved results for the [signature]. |
| */ |
| - String _getResolvedUnitKey(FileState library, FileState file) { |
| - String signature = _getResolvedUnitSignature(library, file); |
| + String _getResolvedUnitKey(String signature) { |
| return '$signature.resolved'; |
| } |
| @@ -1045,15 +1069,20 @@ class AnalysisDriver { |
| } |
| } |
| + // Analyze a general file. |
| if (_fileTracker.hasPendingFiles) { |
| - // Analyze a general file. |
| String path = _fileTracker.anyPendingFile; |
| try { |
| - AnalysisResult result = _computeAnalysisResult(path, withUnit: false); |
| + AnalysisResult result = _computeAnalysisResult(path, |
| + withUnit: false, skipIfSameSignature: true); |
| if (result == null) { |
| _partsToAnalyze.add(path); |
| + } else if (result == AnalysisResult._SAME_ERRORS) { |
| + // We found that the set of errors is the same as we produced the |
| + // last time, so we don't need to produce it again now. |
| } else { |
| _resultController.add(result); |
| + _lastProducedSignatures[result.path] = result.signature; |
| } |
| } catch (exception, stackTrace) { |
| _reportException(path, exception, stackTrace); |
| @@ -1113,6 +1142,25 @@ class AnalysisDriver { |
| _exceptionController.add(new ExceptionResult(path, caught, contextKey)); |
| } |
| + /** |
| + * Serialize the given [resolvedUnit] errors and index into bytes. |
| + */ |
| + List<int> _serializeResolvedUnit( |
| + CompilationUnit resolvedUnit, List<AnalysisError> errors) { |
| + AnalysisDriverUnitIndexBuilder index = indexUnit(resolvedUnit); |
| + return 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(), |
| + index: index) |
| + .toBuffer(); |
| + } |
| + |
| String _storeExceptionContext( |
| String path, FileState libraryFile, exception, StackTrace stackTrace) { |
| if (allowedNumberOfContextsToWrite <= 0) { |
| @@ -1161,30 +1209,6 @@ class AnalysisDriver { |
| return null; |
| } |
| } |
| - |
| - /** |
| - * Store the fully resolved results for the [file] in the [library] into the |
| - * cache and return the stored bytes. |
| - */ |
| - List<int> _storeResolvedUnit(FileState library, FileState file, |
| - CompilationUnit resolvedUnit, List<AnalysisError> errors) { |
| - AnalysisDriverUnitIndexBuilder index = indexUnit(resolvedUnit); |
| - |
| - String key = _getResolvedUnitKey(library, file); |
| - 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(), |
| - index: index) |
| - .toBuffer(); |
| - _byteStore.put(key, bytes); |
| - return bytes; |
| - } |
| } |
| /** |
| @@ -1385,6 +1409,9 @@ class AnalysisDriverTestView { |
| * any previously returned result, even inside of the same library. |
| */ |
| class AnalysisResult { |
| + static final _SAME_ERRORS = new AnalysisResult( |
| + null, null, null, null, null, null, null, null, null, null, null, null); |
|
Brian Wilkerson
2017/02/18 17:40:03
As I understand it, the effect of this CL is to ma
scheglov
2017/02/18 20:15:45
Done.
|
| + |
| /** |
| * The [AnalysisDriver] that produced this result. |
| */ |
| @@ -1428,6 +1455,13 @@ class AnalysisResult { |
| final LineInfo lineInfo; |
| /** |
| + * The signature of the result based on the content of the file, and the |
| + * transitive closure of files imported and exported by the the library of |
| + * the requested file. |
| + */ |
| + final String signature; |
| + |
| + /** |
| * The fully resolved compilation unit for the [content]. |
| */ |
| final CompilationUnit unit; |
| @@ -1451,6 +1485,7 @@ class AnalysisResult { |
| this.content, |
| this.contentHash, |
| this.lineInfo, |
| + this.signature, |
| this.unit, |
| this.errors, |
| this._index); |