Add a byte store that can be shared for use with Cider.

Change-Id: I492aebb476aa7e681eb4d7d5bff995d12917c9b4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150684
Commit-Queue: Keerti Parthasarathy <keertip@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Keerti Parthasarathy 2020-06-11 02:42:25 +00:00 committed by commit-bot@chromium.org
parent 24b33dae89
commit e62b89c56d
4 changed files with 112 additions and 53 deletions

View file

@ -0,0 +1,55 @@
// Copyright (c) 2020, 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 'package:collection/collection.dart';
/**
* Store of bytes associated with string keys and a hash.
*
* Each key must be not longer than 100 characters and consist of only `[a-z]`,
* `[0-9]`, `.` and `_` characters. The key cannot be an empty string, the
* literal `.`, or contain the sequence `..`.
*
* Note that associations are not guaranteed to be persistent. The value
* associated with a key can change or become `null` at any point in time.
*/
abstract class CiderByteStore {
/**
* Return the bytes associated with the errors for given [key] and [signature].
* Return `null` if the association does not exist.
*/
List<int> get(String key, List<int> signature);
/**
* Associate the given [bytes] with the [key] and [digest].
*/
void put(String key, List<int> signature, List<int> bytes);
}
class CiderMemoryByteStore implements CiderByteStore {
final Map<String, _CiderCacheEntry> _map = {};
@override
List<int> get(String key, List<int> signature) {
var entry = _map[key];
if (entry != null &&
const ListEquality().equals(entry.signature, signature)) {
return entry.bytes;
}
return null;
}
@override
void put(String key, List<int> signature, List<int> bytes) {
_map[key] = _CiderCacheEntry(signature, bytes);
}
}
class _CiderCacheEntry {
final List<int> signature;
final List<int> bytes;
_CiderCacheEntry(this.signature, this.bytes);
}

View file

@ -11,10 +11,10 @@ import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
@ -27,7 +27,6 @@ import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/link.dart' as graph
show DependencyWalker, Node;
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:collection/collection.dart';
import 'package:convert/convert.dart';
/// Ensure that the [FileState.libraryCycle] for the [file] and anything it
@ -168,16 +167,7 @@ class FileState {
// Prepare bytes of the unlinked bundle - existing or new.
List<int> bytes;
{
bytes = _fsState._byteStore.get(unlinkedKey);
// unlinked summary should be updated if contents have changed, can be
// seen if file digest has changed.
if (bytes != null) {
var ciderUnlinkedUnit = CiderUnlinkedUnit.fromBuffer(bytes);
if (!const ListEquality()
.equals(ciderUnlinkedUnit.contentDigest, _digest)) {
bytes = null;
}
}
bytes = _fsState._byteStore.get(unlinkedKey, _digest);
if (bytes == null || bytes.isEmpty) {
var content = _fsState.timers.read.run(() {
@ -189,7 +179,7 @@ class FileState {
_fsState.timers.unlinked.run(() {
var unlinkedBuilder = serializeAstCiderUnlinked(_digest, unit);
bytes = unlinkedBuilder.toBuffer();
_fsState._byteStore.put(unlinkedKey, bytes);
_fsState._byteStore.put(unlinkedKey, _digest, bytes);
});
_fsState.timers.prefetch.run(() {
@ -377,7 +367,7 @@ class FileState {
class FileSystemState {
final PerformanceLog _logger;
final ResourceProvider _resourceProvider;
final MemoryByteStore _byteStore;
final CiderByteStore _byteStore;
final SourceFactory _sourceFactory;
final AnalysisOptions _analysisOptions;
final Uint32List _linkedSalt;

View file

@ -19,6 +19,7 @@ import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/micro/analysis_context.dart';
import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
import 'package:analyzer/src/dart/micro/library_analyzer.dart';
import 'package:analyzer/src/dart/micro/library_graph.dart';
import 'package:analyzer/src/generated/engine.dart'
@ -33,7 +34,6 @@ import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:yaml/yaml.dart';
@ -47,7 +47,7 @@ class FileContext {
class FileResolver {
final PerformanceLog logger;
final ResourceProvider resourceProvider;
final MemoryByteStore byteStore;
CiderByteStore byteStore;
final SourceFactory sourceFactory;
/*
@ -76,22 +76,48 @@ class FileResolver {
_LibraryContext libraryContext;
FileResolver(
this.logger,
this.resourceProvider,
this.byteStore,
this.sourceFactory,
this.getFileDigest,
this.prefetchFiles, {
FileResolver.from({
@required PerformanceLog logger,
@required ResourceProvider resourceProvider,
@required SourceFactory sourceFactory,
@required String Function(String path) getFileDigest,
@required void Function(List<String> paths) prefetchFiles,
@required Workspace workspace,
CiderByteStore byteStore,
Duration libraryContextResetTimeout = const Duration(seconds: 60),
}) : this.workspace = workspace {
}) : this.logger = logger,
this.sourceFactory = sourceFactory,
this.resourceProvider = resourceProvider,
this.getFileDigest = getFileDigest,
this.prefetchFiles = prefetchFiles,
this.workspace = workspace {
byteStore ??= CiderMemoryByteStore();
this.byteStore = byteStore;
_libraryContextReset = _LibraryContextReset(
fileResolver: this,
resetTimeout: libraryContextResetTimeout,
);
}
FileResolver(
PerformanceLog logger,
ResourceProvider resourceProvider,
@deprecated ByteStore byteStore,
SourceFactory sourceFactory,
String Function(String path) getFileDigest,
void Function(List<String> paths) prefetchFiles, {
@required Workspace workspace,
Duration libraryContextResetTimeout = const Duration(seconds: 60),
}) : this.from(
logger: logger,
resourceProvider: resourceProvider,
sourceFactory: sourceFactory,
getFileDigest: getFileDigest,
prefetchFiles: prefetchFiles,
workspace: workspace,
libraryContextResetTimeout: libraryContextResetTimeout,
);
FeatureSet get defaultFeatureSet => FeatureSet.fromEnableFlags([]);
/// Update the resolver to reflect the fact that the file with the given
@ -134,16 +160,13 @@ class FileResolver {
var errorsSignature = errorsSignatureBuilder.toByteList();
var errorsKey = file.path + '.errors';
var bytes = byteStore.get(errorsKey);
var bytes = byteStore.get(errorsKey, errorsSignature);
List<AnalysisError> errors;
if (bytes != null) {
var data = CiderUnitErrors.fromBuffer(bytes);
if (const ListEquality().equals(data.signature, errorsSignature)) {
errors = data.errors.map((error) {
return ErrorEncoding.decode(file.source, error);
}).toList();
}
errors = data.errors.map((error) {
return ErrorEncoding.decode(file.source, error);
}).toList();
}
if (errors == null) {
@ -154,7 +177,7 @@ class FileResolver {
signature: errorsSignature,
errors: errors.map((ErrorEncoding.encode)).toList(),
).toBuffer();
byteStore.put(errorsKey, bytes);
byteStore.put(errorsKey, errorsSignature, bytes);
}
return ErrorsResultImpl(
@ -412,7 +435,7 @@ class FileResolverTestView {
class _LibraryContext {
final PerformanceLog logger;
final ResourceProvider resourceProvider;
final MemoryByteStore byteStore;
final CiderByteStore byteStore;
final MicroContextObjects contextObjects;
LinkedElementFactory elementFactory;
@ -451,15 +474,7 @@ class _LibraryContext {
cycle.directDependencies.forEach(loadBundle);
var key = cycle.cyclePathsHash;
var bytes = byteStore.get(key);
// check to see if any of the sources have changed
if (bytes != null) {
var hash = CiderLinkedLibraryCycle.fromBuffer(bytes).signature;
if (!const ListEquality().equals(hash, cycle.signature)) {
bytes = null;
}
}
var bytes = byteStore.get(key, cycle.signature);
if (bytes == null) {
librariesLinkedTimer.start();
@ -510,7 +525,7 @@ class _LibraryContext {
bytes = serializeBundle(cycle.signature, linkResult).toBuffer();
byteStore.put(key, bytes);
byteStore.put(key, cycle.signature, bytes);
bytesPut += bytes.length;
librariesLinkedTimer.stop();

View file

@ -5,8 +5,8 @@
import 'dart:convert';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
import 'package:analyzer/src/dart/micro/resolve_file.dart';
import 'package:analyzer/src/test_utilities/find_element.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
@ -22,7 +22,7 @@ import '../resolution/resolution.dart';
class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
static final String _testFile = '/workspace/dart/test/lib/test.dart';
final ByteStore byteStore = MemoryByteStore();
final CiderByteStore byteStore = CiderMemoryByteStore();
final StringBuffer logBuffer = StringBuffer();
PerformanceLog logger;
@ -44,15 +44,14 @@ class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
convertPath(_testFile),
);
fileResolver = FileResolver(
logger,
resourceProvider,
byteStore,
workspace.createSourceFactory(sdk, null),
(String path) => _getDigest(path),
null,
fileResolver = FileResolver.from(
logger: logger,
resourceProvider: resourceProvider,
byteStore: byteStore,
sourceFactory: workspace.createSourceFactory(sdk, null),
getFileDigest: (String path) => _getDigest(path),
workspace: workspace,
libraryContextResetTimeout: null,
prefetchFiles: null,
);
fileResolver.testView = FileResolverTestView();
}