Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Unified Diff: pkg/analyzer/lib/src/summary/incremental_cache.dart

Issue 2353693002: Remove incremental analysis cache. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/summary/idl.dart ('k') | pkg/analyzer/test/src/summary/incremental_cache_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/summary/incremental_cache.dart
diff --git a/pkg/analyzer/lib/src/summary/incremental_cache.dart b/pkg/analyzer/lib/src/summary/incremental_cache.dart
deleted file mode 100644
index 19a42259f7e6995ccd6d88d01e08edbef74aacce..0000000000000000000000000000000000000000
--- a/pkg/analyzer/lib/src/summary/incremental_cache.dart
+++ /dev/null
@@ -1,656 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:collection';
-import 'dart:convert';
-import 'dart:core';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/summarize_elements.dart';
-import 'package:convert/convert.dart';
-import 'package:crypto/crypto.dart';
-
-/**
- * The version of the incremental cache. It should be incremented every time
- * when any cache data structure is changed.
- */
-const int _VERSION = 1;
-
-/**
- * Compare the given file paths [a] and [b]. Because paths usually have long
- * equal prefix, comparison is done not as comparision of two generic [String]s.
- * Instead it starts from the ends of each strings.
- *
- * Return `-1` if [a] is ordered before [b], `1` if `this` is ordered after [b],
- * and zero if [a] and [b] are ordered together.
- */
-int comparePaths(String a, String b) {
- int thisLength = a.length;
- int otherLength = b.length;
- int len = (thisLength < otherLength) ? thisLength : otherLength;
- for (int i = 0; i < len; i++) {
- int thisCodeUnit = a.codeUnitAt(thisLength - 1 - i);
- int otherCodeUnit = b.codeUnitAt(otherLength - 1 - i);
- if (thisCodeUnit < otherCodeUnit) {
- return -1;
- }
- if (thisCodeUnit > otherCodeUnit) {
- return 1;
- }
- }
- if (thisLength < otherLength) {
- return -1;
- }
- if (thisLength > otherLength) {
- return 1;
- }
- return 0;
-}
-
-/**
- * Storage for cache data.
- */
-abstract class CacheStorage {
- /**
- * Compact the storage, e.g. remove unused entries.
- */
- void compact();
-
- /**
- * Return bytes for the given [key], `null` if [key] is not in the storage.
- */
- List<int> get(String key);
-
- /**
- * Associate the [key] with the given [bytes].
- *
- * If the [key] was already in the storage, its associated value is changed.
- * Otherwise the key-value pair is added to the storage.
- *
- * It is not guaranteed that data will always be accessible using [get], in
- * some implementations association may silently fail or become inaccessible
- * after some time.
- */
- void put(String key, List<int> bytes);
-}
-
-/**
- * A [Folder] based implementation of [CacheStorage].
- */
-class FolderCacheStorage implements CacheStorage {
- /**
- * The maximum number of entries to keep in the cache.
- */
- static const MAX_ENTRIES = 20000;
-
- /**
- * The folder to read and write files.
- */
- final Folder folder;
-
- /**
- * To ensure that operations of writing files are atomic we create a temporary
- * file with this name in the [folder] and then rename it once we are
- * done writing.
- */
- final String tempFileName;
-
- /**
- * The set of recently used entries, with the most recently used entries
- * on the bottom.
- */
- final LinkedHashSet<String> _recentEntries = new LinkedHashSet<String>();
-
- FolderCacheStorage(this.folder, this.tempFileName) {
- try {
- File file = folder.getChildAssumingFile('.entries');
- if (file.exists) {
- String entriesString = file.readAsStringSync();
- List<String> entriesLists = entriesString.split('\n');
- _recentEntries.addAll(entriesLists);
- }
- } catch (_) {}
- }
-
- @override
- void compact() {
- while (_recentEntries.length > MAX_ENTRIES) {
- String key = _recentEntries.first;
- _recentEntries.remove(key);
- try {
- folder.getChildAssumingFile(key).delete();
- } catch (_) {}
- }
- try {
- List<int> bytes = UTF8.encode(_recentEntries.join('\n'));
- folder.getChildAssumingFile('.entries').writeAsBytesSync(bytes);
- } catch (_) {}
- }
-
- @override
- List<int> get(String key) {
- Resource file = folder.getChild(key);
- if (file is File) {
- try {
- List<int> bytes = file.readAsBytesSync();
- _accessedKey(key);
- return bytes;
- } on FileSystemException {}
- }
- return null;
- }
-
- @override
- void put(String key, List<int> bytes) {
- String absPath = folder.getChild(key).path;
- File tempFile = folder.getChild(tempFileName);
- tempFile.writeAsBytesSync(bytes);
- try {
- tempFile.renameSync(absPath);
- _accessedKey(key);
- } catch (e) {}
- }
-
- /**
- * The given [key] was accessed, update recently used entries.
- */
- void _accessedKey(String key) {
- _recentEntries.remove(key);
- _recentEntries.add(key);
- }
-}
-
-/**
- * Cache of information to support incremental analysis.
- *
- * Note that currently this class is not intended for interactive use.
- */
-class IncrementalCache {
- /**
- * The storage for the cache data.
- */
- final CacheStorage storage;
-
- /**
- * The context in which this cache is used.
- */
- final AnalysisContext context;
-
- /**
- * Opaque data that reflects the current configuration, such as the [context]
- * options, and is mixed into the hashes.
- */
- final List<int> configSalt;
-
- final Map<Source, CacheSourceContent> _sourceContentMap =
- <Source, CacheSourceContent>{};
- final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{};
- final Map<Source, List<int>> _libraryClosureHashMap = <Source, List<int>>{};
- final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{};
-
- /**
- * Mapping from a library closure key to its [PackageBundle].
- */
- final Map<String, PackageBundle> _bundleMap = <String, PackageBundle>{};
-
- final Map<String, Source> _absoluteUriMap = <String, Source>{};
-
- IncrementalCache(this.storage, this.context, this.configSalt);
-
- /**
- * Clear internal caches so that we read from file system again.
- */
- void clearInternalCaches() {
- _sourceContentMap.clear();
- _libraryClosureMap.clear();
- _sourceContentHashMap.clear();
- _bundleMap.clear();
- }
-
- /**
- * Return all summaries that are required to provide results about the library
- * with the given [librarySource] from its summary. It includes all of the
- * bundles in the import/export closure of the library. If any of the
- * bundles are not in the cache, then `null` is returned. If any of the
- * [LibraryBundleWithId]s were already returned as a part of the closure of
- * another library, they are still included - it is up to the client to
- * decide whether a bundle should be used or not, but it is easy to do
- * using [LibraryBundleWithId.id].
- */
- List<LibraryBundleWithId> getLibraryClosureBundles(Source librarySource) {
- try {
- List<Source> closureSources = _getLibraryClosure(librarySource);
- List<LibraryBundleWithId> closureBundles = <LibraryBundleWithId>[];
- for (Source source in closureSources) {
- if (getSourceKind(source) == SourceKind.PART) {
- continue;
- }
- String key = _getLibraryBundleKey(source);
- PackageBundle bundle = _getLibraryBundle(key);
- if (bundle == null) {
- return null;
- }
- closureBundles.add(new LibraryBundleWithId(source, key, bundle));
- }
- return closureBundles;
- } catch (e) {
- return null;
- }
- }
-
- /**
- * Return the parts of the given [librarySource], or `null` if unknown.
- */
- List<Source> getLibraryParts(Source librarySource) {
- try {
- CacheSourceContent contentSource = _getCacheSourceContent(librarySource);
- if (contentSource != null) {
- return contentSource.partUris.map((String partUri) {
- Source partSource = _resolveUri(librarySource, partUri);
- if (partSource == null) {
- throw new StateError(
- 'Unable to resolve $partUri in $librarySource');
- }
- return partSource;
- }).toList();
- }
- } catch (e) {}
- return null;
- }
-
- /**
- * Return cached errors in the given [source] in the context of the given
- * [librarySource], or `null` if the cache does not have this information.
- */
- List<AnalysisError> getSourceErrorsInLibrary(
- Source librarySource, Source source) {
- try {
- String key = _getSourceErrorsKey(librarySource, source);
- List<int> bytes = storage.get(key);
- if (bytes == null) {
- return null;
- }
- CacheSourceErrorsInLibrary errorsObject =
- new CacheSourceErrorsInLibrary.fromBuffer(bytes);
- return errorsObject.errors
- .map((e) => _convertErrorFromCached(source, e))
- .toList();
- } catch (e) {
- return null;
- }
- }
-
- /**
- * Return the kind of the given [source], or `null` if unknown.
- */
- SourceKind getSourceKind(Source source) {
- try {
- CacheSourceContent contentSource = _getCacheSourceContent(source);
- if (contentSource != null) {
- if (contentSource.kind == CacheSourceKind.library) {
- return SourceKind.LIBRARY;
- }
- if (contentSource.kind == CacheSourceKind.part) {
- return SourceKind.PART;
- }
- }
- } catch (e) {}
- return null;
- }
-
- /**
- * Write information about the [libraryElement] into the cache.
- */
- void putLibrary(LibraryElement libraryElement) {
- _writeCacheSourceContents(libraryElement);
- String key = _getLibraryBundleKey(libraryElement.source);
- PackageBundleAssembler assembler = new PackageBundleAssembler();
- assembler.serializeLibraryElement(libraryElement);
- List<int> bytes = assembler.assemble().toBuffer();
- storage.put(key, bytes);
- }
-
- /**
- * Associate the given [errors] with the [source] in the [librarySource].
- */
- void putSourceErrorsInLibrary(
- Source librarySource, Source source, List<AnalysisError> errors) {
- CacheSourceErrorsInLibraryBuilder builder =
- new CacheSourceErrorsInLibraryBuilder(
- errors: errors.map(_convertErrorToCached).toList());
- String key = _getSourceErrorsKey(librarySource, source);
- List<int> bytes = builder.toBuffer();
- storage.put(key, bytes);
- }
-
- /**
- * Fill the whole source closure of the library with the given
- * [librarySource]. It includes defining units and parts of the library and
- * all its directly or indirectly imported or exported libraries.
- */
- void _appendLibraryClosure(Set<Source> closure, Source librarySource) {
- if (librarySource.isInSystemLibrary) {
- return;
- }
- if (closure.add(librarySource)) {
- CacheSourceContent contentSource = _getCacheSourceContent(librarySource);
- if (contentSource == null) {
- throw new StateError('No structure for $librarySource');
- }
- // Append parts.
- for (String partUri in contentSource.partUris) {
- Source partSource = _resolveUri(librarySource, partUri);
- if (partSource == null) {
- throw new StateError('Unable to resolve $partUri in $librarySource');
- }
- closure.add(partSource);
- }
- // Append imports and exports.
- void appendLibrarySources(String refUri) {
- Source refSource = _resolveUri(librarySource, refUri);
- if (refSource == null) {
- throw new StateError('Unable to resolve $refUri in $librarySource');
- }
- // If we have already the closure for the 'refSource', use it.
- // Otherwise, continue computing recursively.
- // It's not the most efficient algorithm, but in practice we might
- // visit each library multiple times only for the first top-level
- // bundle requested in `getLibraryClosureBundles`.
- List<Source> refClosure = _libraryClosureMap[refSource];
- if (refClosure != null) {
- closure.addAll(refClosure);
- } else {
- _appendLibraryClosure(closure, refSource);
- }
- }
-
- contentSource.importedUris.forEach(appendLibrarySources);
- contentSource.exportedUris.forEach(appendLibrarySources);
- }
- }
-
- List<int> _computeSaltedMD5OfBytes(addData(ByteConversionSink byteSink)) {
- Digest digest;
- ChunkedConversionSink<Digest> digestSink =
- new ChunkedConversionSink<Digest>.withCallback((List<Digest> digests) {
- digest = digests.single;
- });
- ByteConversionSink byteSink = md5.startChunkedConversion(digestSink);
- // Add data.
- addData(byteSink);
- byteSink.add(const <int>[_VERSION]);
- byteSink.add(configSalt);
- // Done.
- byteSink.close();
- return digest.bytes;
- }
-
- /**
- * Return the [AnalysisError] for the given [cachedError].
- */
- AnalysisError _convertErrorFromCached(
- Source source, CacheAnalysisError cachedError) {
- ErrorCode errorCode = _getErrorCode(cachedError);
- return new AnalysisError.forValues(
- source,
- cachedError.offset,
- cachedError.length,
- errorCode,
- cachedError.message,
- cachedError.correction);
- }
-
- /**
- * Return the [CacheAnalysisError] for the given [error].
- */
- CacheAnalysisError _convertErrorToCached(AnalysisError error) {
- return new CacheAnalysisErrorBuilder(
- errorCodeUniqueName: error.errorCode.uniqueName,
- offset: error.offset,
- length: error.length,
- message: error.message,
- correction: error.correction);
- }
-
- /**
- * Get the content based information about the given [source], maybe `null`
- * if the information is not in the cache.
- */
- CacheSourceContent _getCacheSourceContent(Source source) {
- CacheSourceContent content = _sourceContentMap[source];
- if (content == null) {
- String key = _getCacheSourceContentKey(source);
- List<int> bytes = storage.get(key);
- if (bytes == null) {
- return null;
- }
- content = new CacheSourceContent.fromBuffer(bytes);
- _sourceContentMap[source] = content;
- }
- return content;
- }
-
- /**
- * Return the key of the content based [source] information.
- */
- String _getCacheSourceContentKey(Source source) {
- List<int> hash = _getSourceContentHash(source);
- String hashStr = hex.encode(hash);
- return '$hashStr.content';
- }
-
- /**
- * Return the [ErrorCode] of the given [error], throws if not found.
- */
- ErrorCode _getErrorCode(CacheAnalysisError error) {
- String uniqueName = error.errorCodeUniqueName;
- ErrorCode errorCode = ErrorCode.byUniqueName(uniqueName);
- if (errorCode != null) {
- return errorCode;
- }
- throw new StateError('Unable to find ErrorCode: $uniqueName');
- }
-
- /**
- * Get the bundle for the given key.
- */
- PackageBundle _getLibraryBundle(String key) {
- PackageBundle bundle = _bundleMap[key];
- if (bundle == null) {
- List<int> bytes = storage.get(key);
- if (bytes == null) {
- return null;
- }
- bundle = new PackageBundle.fromBuffer(bytes);
- if (bundle.majorVersion != PackageBundleAssembler.currentMajorVersion ||
- bundle.minorVersion != PackageBundleAssembler.currentMinorVersion) {
- return null;
- }
- _bundleMap[key] = bundle;
- }
- return bundle;
- }
-
- /**
- * Return the key of the bundle of the [librarySource].
- */
- String _getLibraryBundleKey(Source librarySource) {
- List<int> hash = _getLibraryClosureHash(librarySource);
- String hashStr = hex.encode(hash);
- return '$hashStr.summary';
- }
-
- /**
- * Return the whole source closure of the library with the given
- * [librarySource]. It includes defining units and parts of the library and
- * of all its directly or indirectly imported or exported libraries.
- */
- List<Source> _getLibraryClosure(Source librarySource) {
- return _libraryClosureMap.putIfAbsent(librarySource, () {
- Set<Source> closureSet = new Set<Source>();
- _appendLibraryClosure(closureSet, librarySource);
- List<Source> closureList = closureSet.toList();
- closureList.sort((a, b) => comparePaths(a.fullName, b.fullName));
- return closureList;
- });
- }
-
- /**
- * Return the [context]-specific hash of the closure of the library with
- * the given [librarySource].
- */
- List<int> _getLibraryClosureHash(Source librarySource) {
- return _libraryClosureHashMap.putIfAbsent(librarySource, () {
- List<Source> closure = _getLibraryClosure(librarySource);
- return _computeSaltedMD5OfBytes((ByteConversionSink byteSink) {
- for (Source source in closure) {
- List<int> sourceHash = _getSourceContentHash(source);
- byteSink.add(sourceHash);
- }
- // When we sort closure sources for two libraries (A, B) we get exactly
- // the same list of sources for both A and B. So, their hash is exactly
- // the same. But we use it to store separate summary bundles for
- // separate libraries. Ideally would be nice to group these libraries
- // into a single summary bundle. But this would require delaying
- // saving bundles until we know all of them.
- // So, for now we make hashes for separate libraries unique be mixing
- // in the library source again.
- byteSink.add(_getSourceContentHash(librarySource));
- });
- });
- }
-
- /**
- * Compute a hash of the given [source] contents.
- */
- List<int> _getSourceContentHash(Source source) {
- return _sourceContentHashMap.putIfAbsent(source, () {
- String sourceText = source.contents.data;
- List<int> sourceBytes = UTF8.encode(sourceText);
- return md5.convert(sourceBytes).bytes;
- });
- }
-
- /**
- * Return the key for errors in the [source] in the [librarySource].
- */
- String _getSourceErrorsKey(Source librarySource, Source source) {
- List<int> hash = _computeSaltedMD5OfBytes((ByteConversionSink byteSink) {
- byteSink.add(_getLibraryClosureHash(librarySource));
- byteSink.add(_getSourceContentHash(source));
- });
- String hashStr = hex.encode(hash);
- return '$hashStr.errorsInLibrary';
- }
-
- /**
- * Return a source representing the URI that results from resolving the given
- * (possibly relative) [containedUri] against the URI associated with the
- * [containingSource], whether or not the resulting source exists, or `null`
- * if either the [containedUri] is invalid or if it cannot be resolved against
- * the [containingSource]'s URI.
- */
- Source _resolveUri(Source containingSource, String containedUri) {
- // Cache absolute URIs.
- if (containedUri.startsWith('dart:') ||
- containedUri.startsWith('package:')) {
- return _absoluteUriMap.putIfAbsent(containedUri, () {
- return context.sourceFactory.resolveUri(containingSource, containedUri);
- });
- }
- // Resolve relative URIs without caching.
- return context.sourceFactory.resolveUri(containingSource, containedUri);
- }
-
- /**
- * Write the content based information about the given [source].
- */
- void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) {
- if (!_sourceContentMap.containsKey(source)) {
- String key = _getCacheSourceContentKey(source);
- List<int> bytes = b.toBuffer();
- storage.put(key, bytes);
- // Put into the cache to avoid reading it later.
- _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes);
- }
- }
-
- /**
- * Write [CacheSourceContent] for every unit of the given [library] and its
- * direct and indirect imports/exports.
- */
- void _writeCacheSourceContents(LibraryElement library,
- [Set<LibraryElement> writtenLibraries]) {
- Source librarySource = library.source;
- // Stop recursion cycle.
- writtenLibraries ??= new Set<LibraryElement>();
- if (!writtenLibraries.add(library)) {
- return;
- }
- // Write parts.
- List<String> partUris = <String>[];
- for (CompilationUnitElement part in library.parts) {
- partUris.add(part.uri);
- Source partSource = part.source;
- if (context.getKindOf(partSource) == SourceKind.PART) {
- _writeCacheSourceContent(partSource,
- new CacheSourceContentBuilder(kind: CacheSourceKind.part));
- }
- }
- // Write imports.
- List<String> importUris = <String>[];
- for (ImportElement element in library.imports) {
- String uri = element.uri;
- if (uri != null) {
- importUris.add(uri);
- _writeCacheSourceContents(element.importedLibrary, writtenLibraries);
- }
- }
- // Write exports.
- List<String> exportUris = <String>[];
- for (ExportElement element in library.exports) {
- String uri = element.uri;
- if (uri != null) {
- exportUris.add(uri);
- _writeCacheSourceContents(element.exportedLibrary, writtenLibraries);
- }
- }
- // Write the library.
- _writeCacheSourceContent(
- librarySource,
- new CacheSourceContentBuilder(
- kind: CacheSourceKind.library,
- importedUris: importUris,
- exportedUris: exportUris,
- partUris: partUris));
- }
-}
-
-/**
- * The bundle for a source in the context.
- */
-class LibraryBundleWithId {
- /**
- * The source of the library this bundle is for.
- */
- final Source source;
-
- /**
- * The unique ID of the [bundle] of the [source] in the context.
- */
- final String id;
-
- /**
- * The payload bundle.
- */
- final PackageBundle bundle;
-
- LibraryBundleWithId(this.source, this.id, this.bundle);
-}
« no previous file with comments | « pkg/analyzer/lib/src/summary/idl.dart ('k') | pkg/analyzer/test/src/summary/incremental_cache_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698