Remove IncrementalResolvedAstGenerator.

It is not used anymore, and there is a compilation errors accidentally
introduced. So, I guess it is easier to remove it than to fix it.

R=ahe@google.com, paulberry@google.com, sigmund@google.com
BUG=

Review-Url: https://codereview.chromium.org/2892203003 .
This commit is contained in:
Konstantin Shcheglov 2017-05-19 15:07:23 -07:00
parent 54dcc29835
commit 658ff7ba99
4 changed files with 0 additions and 574 deletions

View file

@ -1,98 +0,0 @@
// Copyright (c) 2017, 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:async';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/incremental_resolved_ast_generator_impl.dart';
import 'compiler_options.dart';
/// Represents the difference between "old" and "new" states of a program.
///
/// Not intended to be implemented or extended by clients.
class DeltaLibraries {
/// The new state of the program, as a two-layer map.
///
/// The outer map key is the library URI. The inner map key is the
/// compilation unit (part) URI. The map values are the resolved compilation
/// units.
///
/// Libraries whose resolved AST is known to be unchanged since the last
/// [DeltaLibraries] are not included.
final Map<Uri, Map<Uri, CompilationUnit>> newState;
DeltaLibraries(this.newState);
/// TODO(paulberry): add information about libraries that were removed.
}
/// Interface for generating an initial resolved representation of a program and
/// keeping it up to date as incremental changes are made.
///
/// This class maintains an internal "previous program state"; each
/// time [computeDelta] is called, it updates the previous program state and
/// produces a representation of what has changed. When there are few changes,
/// a call to [computeDelta] should be much faster than compiling the whole
/// program from scratch.
///
/// This class also maintains a set of "valid sources", which is a (possibly
/// empty) subset of the sources constituting the previous program state. Files
/// in this set are assumed to be unchanged since the last call to
/// [computeDelta].
///
/// Behavior is undefined if the client does not obey the following concurrency
/// restrictions:
/// - no two invocations of [computeDelta] may be outstanding at any given time.
/// - neither [invalidate] nor [invalidateAll] may be called while an invocation
/// of [computeDelta] is outstanding.
///
/// Not intended to be implemented or extended by clients.
abstract class IncrementalResolvedAstGenerator {
/// Creates an [IncrementalResolvedAstGenerator] which is prepared to generate
/// resolved ASTs for the program whose main library is in the given
/// [source].
///
/// No file system access is performed by this constructor; the initial
/// "previous program state" is an empty program containing no code, and the
/// initial set of valid sources is empty. To obtain a resolved AST
/// representation of the program, call [computeDelta].
factory IncrementalResolvedAstGenerator(
Uri source, CompilerOptions options) =>
new IncrementalResolvedAstGeneratorImpl(
source, new ProcessedOptions(options));
/// Generates a resolved AST representation of the changes to the program,
/// assuming that all valid sources are unchanged since the last call to
/// [computeDelta].
///
/// Source files in the set of valid sources are guaranteed not to be re-read
/// from disk; they are assumed to be unchanged regardless of the state of the
/// filesystem.
///
/// If the future completes successfully, the previous file state is updated
/// and the set of valid sources is set to the set of all sources in the
/// program.
///
/// If the future completes with an error (due to errors in the compiled
/// source code), the caller may consider the previous file state and the set
/// of valid sources to be unchanged; this means that once the user fixes the
/// errors, it is safe to call [computeDelta] again.
Future<DeltaLibraries> computeDelta();
/// Remove any source file(s) associated with the given file path from the set
/// of valid sources. This guarantees that those files will be re-read on the
/// next call to [computeDelta]).
void invalidate(String path);
/// Remove all source files from the set of valid sources. This guarantees
/// that all files will be re-read on the next call to [computeDelta].
///
/// Note that this does not erase the previous program state; the next time
/// [computeDelta] is called, if parts of the program are discovered to be
/// unchanged, parts of the previous program state will still be re-used to
/// speed up compilation.
void invalidateAll();
}

View file

@ -7,7 +7,6 @@ import 'dart:io';
import 'package:front_end/file_system.dart';
import 'package:front_end/incremental_kernel_generator.dart';
import 'package:front_end/incremental_resolved_ast_generator.dart';
import 'package:front_end/src/base/api_signature.dart';
import 'package:front_end/src/base/performace_logger.dart';
import 'package:front_end/src/base/processed_options.dart';

View file

@ -1,303 +0,0 @@
// Copyright (c) 2017, 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:async';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/util/absolute_path.dart';
import 'package:front_end/incremental_resolved_ast_generator.dart';
import 'package:front_end/src/base/file_repository.dart';
import 'package:front_end/src/base/performace_logger.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/base/resolve_relative_uri.dart';
import 'package:front_end/src/base/source.dart';
import 'package:front_end/src/dependency_grapher_impl.dart';
import 'package:front_end/src/incremental/byte_store.dart';
import 'package:path/src/context.dart';
dynamic unimplemented() {
// TODO(paulberry): get rid of this.
throw new UnimplementedError();
}
/// Implementation of [IncrementalKernelGenerator].
///
/// Theory of operation: this class is a thin wrapper around
/// [driver.AnalysisDriver]. When the client requests a new delta, we forward
/// the request to the analysis driver. When the client calls an invalidate
/// method, we ensure that the proper files will be re-read next time a delta is
/// requested.
///
/// Note that the analysis driver expects to be able to read file contents
/// synchronously based on filesystem path rather than asynchronously based on
/// URI, so the file contents are first read into memory using the asynchronous
/// FileSystem API, and then these are fed into the analysis driver using a
/// proxy implementation of [ResourceProvider]. TODO(paulberry): make this (and
/// other proxies in this file) unnecessary.
class IncrementalResolvedAstGeneratorImpl
implements IncrementalResolvedAstGenerator {
driver.AnalysisDriverScheduler _scheduler;
final _fileRepository = new FileRepository();
_ResourceProviderProxy _resourceProvider;
driver.AnalysisDriver _driver;
bool _isInitialized = false;
final ProcessedOptions _options;
final Uri _source;
bool _schedulerStarted = false;
final _fileState = <Uri, String>{};
IncrementalResolvedAstGeneratorImpl(this._source, this._options);
@override
Future<DeltaLibraries> computeDelta() async {
if (!_isInitialized) {
await init();
}
// The analysis driver doesn't currently support an asynchronous file API,
// so we have to find all the files first to read their contents.
// TODO(paulberry): this is an unnecessary source of duplicate work and
// should be eliminated ASAP.
var graph =
await graphForProgram([_source], _options, fileReader: _fileReader);
// TODO(paulberry): collect no-longer-referenced files from _fileState and
// _fileRepository.
var libraries = <Uri, Map<Uri, CompilationUnit>>{};
if (!_schedulerStarted) {
_scheduler.start();
_schedulerStarted = true;
}
for (var libraryCycle in graph.topologicallySortedCycles) {
for (var libraryUri in libraryCycle.libraries.keys) {
var libraryNode = libraryCycle.libraries[libraryUri];
for (var partUri in libraryNode.parts) {
// TODO(paulberry): resolve the part URI.
_fileReader(partUri, partUri);
}
}
for (var libraryUri in libraryCycle.libraries.keys) {
var libraryNode = libraryCycle.libraries[libraryUri];
var result =
await _driver.getResult(_fileRepository.pathForUri(libraryUri));
// TODO(paulberry): handle errors.
var units = {libraryUri: result.unit};
for (var partUri in libraryNode.parts) {
// Really we ought to have a driver API that lets us request a
// specific part of a given library. Otherwise we will run into
// problems if a part is included in multiple libraries.
// TODO(paulberry): address this.
var partResult =
await _driver.getResult(_fileRepository.pathForUri(partUri));
// TODO(paulberry): handle errors.
units[partUri] = partResult.unit;
}
libraries[libraryUri] = units;
}
}
_driver.addFile(_fileRepository.pathForUri(_source));
// TODO(paulberry): stop the scheduler
return new DeltaLibraries(libraries);
}
Future<Null> init() async {
// TODO(paulberry): can we just use null?
var performanceLog = new PerformanceLog(new _NullStringSink());
_scheduler = new driver.AnalysisDriverScheduler(performanceLog);
_resourceProvider = new _ResourceProviderProxy(_fileRepository);
// TODO(paulberry): MemoryByteStore leaks memory (it never discards data).
// Do something better here.
var byteStore = new MemoryByteStore();
// TODO(paulberry): can we just use null?
var fileContentOverlay = new FileContentOverlay();
var sdkContext = new AnalysisContextImpl();
var sdkBundle = await _options.getSdkSummary();
var dartSdk = new _DartSdkProxy(sdkBundle, sdkContext, _fileRepository);
sdkContext.sourceFactory =
new SourceFactory([new DartUriResolver(dartSdk)]);
var sourceFactory = new _SourceFactoryProxy(dartSdk, _fileRepository);
var analysisOptions = new AnalysisOptionsImpl();
_driver = new driver.AnalysisDriver(
_scheduler,
performanceLog,
_resourceProvider,
byteStore,
fileContentOverlay,
null,
sourceFactory,
analysisOptions,
sdkBundle: sdkBundle);
_isInitialized = true;
}
@override
void invalidate(String path) {
throw new UnimplementedError();
}
@override
void invalidateAll() {
_fileState.clear();
_fileRepository.clearContents();
// TODO(paulberry): verify that this has an effect (requires a multi-file
// test).
if (_isInitialized) {
_driver.knownFiles.forEach(_driver.changeFile);
}
}
Future<String> _fileReader(Uri originalUri, Uri resolvedUri) async {
String contents = _fileState[resolvedUri] ??=
await _options.fileSystem.entityForUri(resolvedUri).readAsString();
_fileRepository.store(originalUri, contents);
return contents;
}
}
class _DartSdkProxy implements DartSdk {
final PackageBundle summary;
final AnalysisContext context;
final FileRepository _fileRepository;
_DartSdkProxy(this.summary, this.context, this._fileRepository);
@override
PackageBundle getLinkedBundle() => summary;
@override
Source mapDartUri(String uriString) {
var uri = Uri.parse(uriString);
return new _SourceProxy(
uri, _fileRepository.pathForUri(uri, allocate: true));
}
noSuchMethod(Invocation invocation) => unimplemented();
}
class _FileProxy implements File {
final _SourceProxy _source;
final _ResourceProviderProxy _resourceProvider;
_FileProxy(this._source, this._resourceProvider);
@override
String get path => _source.fullName;
@override
String get shortName => path;
@override
Source createSource([Uri uri]) {
assert(uri == null);
return _source;
}
noSuchMethod(Invocation invocation) => unimplemented();
@override
String readAsStringSync() {
return _resourceProvider._fileRepository.contentsForPath(path);
}
}
/// A string sink that ignores everything written to it.
class _NullStringSink implements StringSink {
void write(Object obj) {}
void writeAll(Iterable objects, [String separator = ""]) {}
void writeCharCode(int charCode) {}
void writeln([Object obj = ""]) {}
}
class _ResourceProviderProxy implements ResourceProvider {
final FileRepository _fileRepository;
_ResourceProviderProxy(this._fileRepository);
@override
AbsolutePathContext get absolutePathContext => throw new UnimplementedError();
@override
Context get pathContext => throw new UnimplementedError();
@override
File getFile(String path) {
return new _FileProxy(
new _SourceProxy(_fileRepository.uriForPath(path), path), this);
}
@override
Folder getFolder(String path) => throw new UnimplementedError();
@override
Future<List<int>> getModificationTimes(List<Source> sources) =>
throw new UnimplementedError();
@override
Resource getResource(String path) => throw new UnimplementedError();
@override
Folder getStateLocation(String pluginId) => throw new UnimplementedError();
}
class _SourceFactoryProxy implements SourceFactory {
@override
final DartSdk dartSdk;
final FileRepository _fileRepository;
@override
AnalysisContext context;
_SourceFactoryProxy(this.dartSdk, this._fileRepository);
@override
SourceFactory clone() => new _SourceFactoryProxy(dartSdk, _fileRepository);
@override
Source forUri(String absoluteUri) {
Uri uri = Uri.parse(absoluteUri);
return forUri2(uri);
}
@override
Source forUri2(Uri absoluteUri) {
return new _SourceProxy(
absoluteUri, _fileRepository.pathForUri(absoluteUri, allocate: true));
}
noSuchMethod(Invocation invocation) => unimplemented();
Source resolveUri(Source containingSource, String containedUri) {
// TODO(paulberry): re-use code from dependency_grapher_impl, and support
// SDK URI resolution logic.
String absoluteUri =
resolveRelativeUri(containingSource?.uri, Uri.parse(containedUri))
.toString();
return forUri(absoluteUri);
}
@override
Uri restoreUri(Source source) => source.uri;
}
class _SourceProxy extends BasicSource {
@override
final String fullName;
_SourceProxy(Uri uri, this.fullName) : super(uri);
int get modificationStamp => 0;
noSuchMethod(Invocation invocation) => unimplemented();
}

View file

@ -1,172 +0,0 @@
// Copyright (c) 2017, 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:async';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:front_end/compiler_options.dart';
import 'package:front_end/incremental_resolved_ast_generator.dart';
import 'package:front_end/memory_file_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(IncrementalResolvedAstGeneratorTest);
});
}
final _sdkSummary = _readSdkSummary();
List<int> _readSdkSummary() {
var resourceProvider = PhysicalResourceProvider.INSTANCE;
var sdk = new FolderBasedDartSdk(resourceProvider,
FolderBasedDartSdk.defaultSdkDirectory(resourceProvider))
..useSummary = true;
var path = resourceProvider.pathContext
.join(sdk.directory.path, 'lib', '_internal', 'strong.sum');
return resourceProvider.getFile(path).readAsBytesSync();
}
@reflectiveTest
class IncrementalResolvedAstGeneratorTest {
static final sdkSummaryUri = Uri.parse('special:sdk_summary');
/// Virtual filesystem for testing.
final fileSystem = new MemoryFileSystem(Uri.parse('file:///'));
/// The object under test.
IncrementalResolvedAstGenerator incrementalResolvedAstGenerator;
Future<Map<Uri, Map<Uri, CompilationUnit>>> getInitialProgram(
Uri startingUri) async {
fileSystem.entityForUri(sdkSummaryUri).writeAsBytesSync(_sdkSummary);
incrementalResolvedAstGenerator = new IncrementalResolvedAstGenerator(
startingUri,
new CompilerOptions()
..fileSystem = fileSystem
..chaseDependencies = true
..sdkSummary = sdkSummaryUri
..packagesFileUri = new Uri());
return (await incrementalResolvedAstGenerator.computeDelta()).newState;
}
test_incrementalUpdate_referenceToCore() async {
writeFiles({'/foo.dart': 'main() { print(1); }'});
var fooUri = Uri.parse('file:///foo.dart');
var initialProgram = await getInitialProgram(fooUri);
expect(initialProgram.keys, unorderedEquals([fooUri]));
void _checkMain(CompilationUnit unit, int expectedArgument) {
var mainStatements = _getFunctionStatements(_getFunction(unit, 'main'));
expect(mainStatements, hasLength(1));
_checkPrintLiteralInt(mainStatements[0], expectedArgument);
}
_checkMain(initialProgram[fooUri][fooUri], 1);
writeFiles({'/foo.dart': 'main() { print(2); }'});
// Verify that the file isn't actually reread until invalidate is called.
var deltaProgram1 = await incrementalResolvedAstGenerator.computeDelta();
// TODO(paulberry): since there is no delta, computeDelta should return an
// empty map.
// expect(deltaProgram1.newState, isEmpty);
expect(deltaProgram1.newState.keys, unorderedEquals([fooUri]));
_checkMain(deltaProgram1.newState[fooUri][fooUri], 1);
incrementalResolvedAstGenerator.invalidateAll();
var deltaProgram2 = await incrementalResolvedAstGenerator.computeDelta();
expect(deltaProgram2.newState.keys, unorderedEquals([fooUri]));
_checkMain(deltaProgram2.newState[fooUri][fooUri], 2);
}
test_invalidateAllBeforeInitialProgram() async {
incrementalResolvedAstGenerator = new IncrementalResolvedAstGenerator(
Uri.parse('file:///foo.dart'),
new CompilerOptions()
..fileSystem = fileSystem
..chaseDependencies = true
..packagesFileUri = new Uri());
incrementalResolvedAstGenerator.invalidateAll();
}
test_part() async {
writeFiles({
'/foo.dart': 'library foo; part "bar.dart"; main() { print(1); f(); }',
'/bar.dart': 'part of foo; f() { print(2); }'
});
var fooUri = Uri.parse('file:///foo.dart');
var barUri = Uri.parse('file:///bar.dart');
var initialProgram = await getInitialProgram(fooUri);
expect(initialProgram.keys, unorderedEquals([fooUri]));
expect(initialProgram[fooUri].keys, unorderedEquals([fooUri, barUri]));
var mainStatements = _getFunctionStatements(
_getFunction(initialProgram[fooUri][fooUri], 'main'));
var fDeclaration = _getFunction(initialProgram[fooUri][barUri], 'f');
var fStatements = _getFunctionStatements(fDeclaration);
expect(mainStatements, hasLength(2));
_checkPrintLiteralInt(mainStatements[0], 1);
_checkFunctionCall(mainStatements[1],
resolutionMap.elementDeclaredByFunctionDeclaration(fDeclaration));
expect(fStatements, hasLength(1));
_checkPrintLiteralInt(fStatements[0], 2);
// TODO(paulberry): now test incremental updates
}
/// Write the given file contents to the virtual filesystem.
void writeFiles(Map<String, String> contents) {
contents.forEach((path, text) {
fileSystem
.entityForUri(Uri.parse('file://$path'))
.writeAsStringSync(text);
});
}
void _checkFunctionCall(Statement statement, Element expectedTarget) {
expect(statement, new isInstanceOf<ExpressionStatement>());
var expressionStatement = statement as ExpressionStatement;
expect(
expressionStatement.expression, new isInstanceOf<MethodInvocation>());
var methodInvocation = expressionStatement.expression as MethodInvocation;
expect(
resolutionMap.staticElementForIdentifier(methodInvocation.methodName),
expectedTarget);
}
void _checkPrintLiteralInt(Statement statement, int expectedArgument) {
expect(statement, new isInstanceOf<ExpressionStatement>());
var expressionStatement = statement as ExpressionStatement;
expect(
expressionStatement.expression, new isInstanceOf<MethodInvocation>());
var methodInvocation = expressionStatement.expression as MethodInvocation;
expect(methodInvocation.methodName.name, 'print');
var printElement =
resolutionMap.staticElementForIdentifier(methodInvocation.methodName);
expect(printElement, isNotNull);
expect(printElement.library.source.uri, Uri.parse('dart:core'));
expect(methodInvocation.argumentList.arguments, hasLength(1));
expect(methodInvocation.argumentList.arguments[0],
new isInstanceOf<IntegerLiteral>());
var integerLiteral =
methodInvocation.argumentList.arguments[0] as IntegerLiteral;
expect(integerLiteral.value, expectedArgument);
}
FunctionDeclaration _getFunction(CompilationUnit unit, String name) {
for (var declaration in unit.declarations) {
if (declaration is FunctionDeclaration && declaration.name.name == name) {
return declaration;
}
}
throw fail('No function declaration found with name "$name"');
}
NodeList<Statement> _getFunctionStatements(FunctionDeclaration function) {
var body = function.functionExpression.body;
expect(body, new isInstanceOf<BlockFunctionBody>());
return (body as BlockFunctionBody).block.statements;
}
}