mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
Isolate the part of AnalysisDriver that manages the AnalysisContext.
I re-used the existing class _LibraryContext, but moved it to its own file and gave it a public API so that the rest of the AnalysisDriver doesn't have to deal with the AnalysisContext directly. R=scheglov@google.com Review-Url: https://codereview.chromium.org/2661023005 .
This commit is contained in:
parent
0e6eed24c5
commit
acf5b16a5f
2 changed files with 255 additions and 165 deletions
|
@ -13,10 +13,10 @@ import 'package:analyzer/error/error.dart';
|
|||
import 'package:analyzer/error/listener.dart';
|
||||
import 'package:analyzer/exception/exception.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/context/context.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/file_state.dart';
|
||||
import 'package:analyzer/src/dart/analysis/index.dart';
|
||||
import 'package:analyzer/src/dart/analysis/library_context.dart';
|
||||
import 'package:analyzer/src/dart/analysis/search.dart';
|
||||
import 'package:analyzer/src/dart/analysis/status.dart';
|
||||
import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
|
||||
|
@ -27,10 +27,6 @@ import 'package:analyzer/src/services/lint.dart';
|
|||
import 'package:analyzer/src/summary/api_signature.dart';
|
||||
import 'package:analyzer/src/summary/format.dart';
|
||||
import 'package:analyzer/src/summary/idl.dart';
|
||||
import 'package:analyzer/src/summary/link.dart';
|
||||
import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
||||
import 'package:analyzer/src/task/dart.dart' show COMPILATION_UNIT_ELEMENT;
|
||||
import 'package:analyzer/task/dart.dart' show LibrarySpecificUnit;
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/**
|
||||
|
@ -739,14 +735,12 @@ class AnalysisDriver {
|
|||
}
|
||||
|
||||
try {
|
||||
_LibraryContext libraryContext = _createLibraryContext(libraryFile);
|
||||
AnalysisContext analysisContext =
|
||||
_createAnalysisContext(libraryContext);
|
||||
LibraryContext libraryContext = _createLibraryContext(libraryFile);
|
||||
try {
|
||||
CompilationUnit resolvedUnit = analysisContext
|
||||
.resolveCompilationUnit2(file.source, libraryFile.source);
|
||||
List<AnalysisError> errors =
|
||||
analysisContext.computeErrors(file.source);
|
||||
var resolutionResult =
|
||||
libraryContext.resolveUnit(libraryFile.source, file.source);
|
||||
CompilationUnit resolvedUnit = resolutionResult.resolvedUnit;
|
||||
List<AnalysisError> errors = resolutionResult.errors;
|
||||
AnalysisDriverUnitIndexBuilder index = indexUnit(resolvedUnit);
|
||||
|
||||
// Store the result into the cache.
|
||||
|
@ -778,7 +772,7 @@ class AnalysisDriver {
|
|||
}
|
||||
return result;
|
||||
} finally {
|
||||
analysisContext.dispose();
|
||||
libraryContext.dispose();
|
||||
}
|
||||
} catch (exception, stackTrace) {
|
||||
String contextKey =
|
||||
|
@ -799,113 +793,29 @@ class AnalysisDriver {
|
|||
FileState libraryFile = file.library ?? file;
|
||||
|
||||
// Create the AnalysisContext to resynthesize elements in.
|
||||
_LibraryContext libraryContext = _createLibraryContext(libraryFile);
|
||||
AnalysisContext analysisContext = _createAnalysisContext(libraryContext);
|
||||
LibraryContext libraryContext = _createLibraryContext(libraryFile);
|
||||
|
||||
// Resynthesize the CompilationUnitElement in the context.
|
||||
try {
|
||||
return analysisContext.computeResult(
|
||||
new LibrarySpecificUnit(libraryFile.source, file.source),
|
||||
COMPILATION_UNIT_ELEMENT);
|
||||
return libraryContext.computeUnitElement(libraryFile.source, file.source);
|
||||
} finally {
|
||||
analysisContext.dispose();
|
||||
libraryContext.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) {
|
||||
AnalysisContextImpl analysisContext =
|
||||
AnalysisEngine.instance.createAnalysisContext();
|
||||
analysisContext.useSdkCachePartition = false;
|
||||
analysisContext.analysisOptions = _analysisOptions;
|
||||
analysisContext.declaredVariables.addAll(declaredVariables);
|
||||
analysisContext.sourceFactory = _sourceFactory.clone();
|
||||
analysisContext.contentCache = new _ContentCacheWrapper(_fsState);
|
||||
analysisContext.resultProvider =
|
||||
new InputPackagesResultProvider(analysisContext, libraryContext.store);
|
||||
return analysisContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the context in which the [library] should be analyzed it.
|
||||
* Return the context in which the [library] should be analyzed.
|
||||
*/
|
||||
_LibraryContext _createLibraryContext(FileState library) {
|
||||
return _logger.run('Create library context', () {
|
||||
Map<String, FileState> libraries = <String, FileState>{};
|
||||
SummaryDataStore store = new SummaryDataStore(const <String>[]);
|
||||
|
||||
if (_sdkBundle != null) {
|
||||
store.addBundle(null, _sdkBundle);
|
||||
}
|
||||
|
||||
void appendLibraryFiles(FileState library) {
|
||||
if (!libraries.containsKey(library.uriStr)) {
|
||||
// Serve 'dart:' URIs from the SDK bundle.
|
||||
if (_sdkBundle != null && library.uri.scheme == 'dart') {
|
||||
return;
|
||||
}
|
||||
|
||||
libraries[library.uriStr] = library;
|
||||
|
||||
// Append the defining unit.
|
||||
store.addUnlinkedUnit(library.uriStr, library.unlinked);
|
||||
|
||||
// Append parts.
|
||||
for (FileState part in library.partedFiles) {
|
||||
store.addUnlinkedUnit(part.uriStr, part.unlinked);
|
||||
}
|
||||
|
||||
// Append referenced libraries.
|
||||
library.importedFiles.forEach(appendLibraryFiles);
|
||||
library.exportedFiles.forEach(appendLibraryFiles);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.run('Append library files', () {
|
||||
return appendLibraryFiles(library);
|
||||
});
|
||||
|
||||
Set<String> libraryUrisToLink = new Set<String>();
|
||||
_logger.run('Load linked bundles', () {
|
||||
for (FileState library in libraries.values) {
|
||||
if (library.exists) {
|
||||
String key = '${library.transitiveSignature}.linked';
|
||||
List<int> bytes = _byteStore.get(key);
|
||||
if (bytes != null) {
|
||||
LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
|
||||
store.addLinkedLibrary(library.uriStr, linked);
|
||||
} else {
|
||||
libraryUrisToLink.add(library.uriStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
int numOfLoaded = libraries.length - libraryUrisToLink.length;
|
||||
_logger.writeln('Loaded $numOfLoaded linked bundles.');
|
||||
});
|
||||
|
||||
Map<String, LinkedLibraryBuilder> linkedLibraries = {};
|
||||
_logger.run('Link bundles', () {
|
||||
linkedLibraries = link(libraryUrisToLink, (String uri) {
|
||||
LinkedLibrary linkedLibrary = store.linkedMap[uri];
|
||||
return linkedLibrary;
|
||||
}, (String uri) {
|
||||
UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
|
||||
return unlinkedUnit;
|
||||
}, (_) => null, _analysisOptions.strongMode);
|
||||
_logger.writeln('Linked ${linkedLibraries.length} bundles.');
|
||||
});
|
||||
|
||||
linkedLibraries.forEach((uri, linkedBuilder) {
|
||||
FileState library = libraries[uri];
|
||||
String key = '${library.transitiveSignature}.linked';
|
||||
List<int> bytes = linkedBuilder.toBuffer();
|
||||
LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
|
||||
store.addLinkedLibrary(uri, linked);
|
||||
_byteStore.put(key, bytes);
|
||||
});
|
||||
|
||||
return new _LibraryContext(library, store);
|
||||
});
|
||||
}
|
||||
LibraryContext _createLibraryContext(FileState library) =>
|
||||
new LibraryContext.forSingleLibrary(
|
||||
library,
|
||||
_logger,
|
||||
_sdkBundle,
|
||||
_byteStore,
|
||||
_analysisOptions,
|
||||
declaredVariables,
|
||||
_sourceFactory,
|
||||
_fsState);
|
||||
|
||||
/**
|
||||
* Fill [_salt] with data.
|
||||
|
@ -1691,51 +1601,6 @@ class PerformanceLogSection {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [ContentCache] wrapper around [FileContentOverlay].
|
||||
*/
|
||||
class _ContentCacheWrapper implements ContentCache {
|
||||
final FileSystemState fsState;
|
||||
|
||||
_ContentCacheWrapper(this.fsState);
|
||||
|
||||
@override
|
||||
void accept(ContentCacheVisitor visitor) {
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
String getContents(Source source) {
|
||||
return _getFileForSource(source).content;
|
||||
}
|
||||
|
||||
@override
|
||||
bool getExists(Source source) {
|
||||
if (source.isInSystemLibrary) {
|
||||
return true;
|
||||
}
|
||||
return _getFileForSource(source).exists;
|
||||
}
|
||||
|
||||
@override
|
||||
int getModificationStamp(Source source) {
|
||||
if (source.isInSystemLibrary) {
|
||||
return 0;
|
||||
}
|
||||
return _getFileForSource(source).exists ? 0 : -1;
|
||||
}
|
||||
|
||||
@override
|
||||
String setContents(Source source, String contents) {
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
|
||||
FileState _getFileForSource(Source source) {
|
||||
String path = source.fullName;
|
||||
return fsState.getFileForPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an exception and its context.
|
||||
*/
|
||||
|
@ -1809,15 +1674,6 @@ class _FilesReferencingNameTask {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO(scheglov) document
|
||||
*/
|
||||
class _LibraryContext {
|
||||
final FileState file;
|
||||
final SummaryDataStore store;
|
||||
_LibraryContext(this.file, this.store);
|
||||
}
|
||||
|
||||
/**
|
||||
* Task that computes top-level declarations for a certain name in all
|
||||
* known libraries.
|
||||
|
|
234
pkg/analyzer/lib/src/dart/analysis/library_context.dart
Normal file
234
pkg/analyzer/lib/src/dart/analysis/library_context.dart
Normal file
|
@ -0,0 +1,234 @@
|
|||
// 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 'package:analyzer/context/declared_variables.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement;
|
||||
import 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/src/context/context.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/analysis/file_state.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart'
|
||||
show AnalysisContext, AnalysisEngine, AnalysisOptions;
|
||||
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/link.dart';
|
||||
import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
||||
import 'package:analyzer/src/task/dart.dart' show COMPILATION_UNIT_ELEMENT;
|
||||
import 'package:analyzer/task/dart.dart' show LibrarySpecificUnit;
|
||||
|
||||
/**
|
||||
* Context information necessary to analyze one or more libraries within an
|
||||
* [AnalysisDriver].
|
||||
*
|
||||
* Currently this is implemented as a wrapper around [AnalysisContext].
|
||||
* TODO(paulberry): make a front end API that this can make use of instead.
|
||||
*/
|
||||
class LibraryContext {
|
||||
/**
|
||||
* The [AnalysisContext] which is used to do the analysis.
|
||||
*/
|
||||
final AnalysisContext _analysisContext;
|
||||
|
||||
/**
|
||||
* Create a [LibraryContext] which is prepared to analyze [library].
|
||||
*/
|
||||
factory LibraryContext.forSingleLibrary(
|
||||
FileState library,
|
||||
PerformanceLog logger,
|
||||
PackageBundle sdkBundle,
|
||||
ByteStore byteStore,
|
||||
AnalysisOptions options,
|
||||
DeclaredVariables declaredVariables,
|
||||
SourceFactory sourceFactory,
|
||||
FileSystemState fsState) {
|
||||
return logger.run('Create library context', () {
|
||||
Map<String, FileState> libraries = <String, FileState>{};
|
||||
SummaryDataStore store = new SummaryDataStore(const <String>[]);
|
||||
|
||||
if (sdkBundle != null) {
|
||||
store.addBundle(null, sdkBundle);
|
||||
}
|
||||
|
||||
void appendLibraryFiles(FileState library) {
|
||||
if (!libraries.containsKey(library.uriStr)) {
|
||||
// Serve 'dart:' URIs from the SDK bundle.
|
||||
if (sdkBundle != null && library.uri.scheme == 'dart') {
|
||||
return;
|
||||
}
|
||||
|
||||
libraries[library.uriStr] = library;
|
||||
|
||||
// Append the defining unit.
|
||||
store.addUnlinkedUnit(library.uriStr, library.unlinked);
|
||||
|
||||
// Append parts.
|
||||
for (FileState part in library.partedFiles) {
|
||||
store.addUnlinkedUnit(part.uriStr, part.unlinked);
|
||||
}
|
||||
|
||||
// Append referenced libraries.
|
||||
library.importedFiles.forEach(appendLibraryFiles);
|
||||
library.exportedFiles.forEach(appendLibraryFiles);
|
||||
}
|
||||
}
|
||||
|
||||
logger.run('Append library files', () {
|
||||
return appendLibraryFiles(library);
|
||||
});
|
||||
|
||||
Set<String> libraryUrisToLink = new Set<String>();
|
||||
logger.run('Load linked bundles', () {
|
||||
for (FileState library in libraries.values) {
|
||||
if (library.exists) {
|
||||
String key = '${library.transitiveSignature}.linked';
|
||||
List<int> bytes = byteStore.get(key);
|
||||
if (bytes != null) {
|
||||
LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
|
||||
store.addLinkedLibrary(library.uriStr, linked);
|
||||
} else {
|
||||
libraryUrisToLink.add(library.uriStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
int numOfLoaded = libraries.length - libraryUrisToLink.length;
|
||||
logger.writeln('Loaded $numOfLoaded linked bundles.');
|
||||
});
|
||||
|
||||
Map<String, LinkedLibraryBuilder> linkedLibraries = {};
|
||||
logger.run('Link bundles', () {
|
||||
linkedLibraries = link(libraryUrisToLink, (String uri) {
|
||||
LinkedLibrary linkedLibrary = store.linkedMap[uri];
|
||||
return linkedLibrary;
|
||||
}, (String uri) {
|
||||
UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
|
||||
return unlinkedUnit;
|
||||
}, (_) => null, options.strongMode);
|
||||
logger.writeln('Linked ${linkedLibraries.length} bundles.');
|
||||
});
|
||||
|
||||
linkedLibraries.forEach((uri, linkedBuilder) {
|
||||
FileState library = libraries[uri];
|
||||
String key = '${library.transitiveSignature}.linked';
|
||||
List<int> bytes = linkedBuilder.toBuffer();
|
||||
LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
|
||||
store.addLinkedLibrary(uri, linked);
|
||||
byteStore.put(key, bytes);
|
||||
});
|
||||
|
||||
var analysisContext = _createAnalysisContext(
|
||||
options, declaredVariables, sourceFactory, fsState, store);
|
||||
|
||||
return new LibraryContext._(analysisContext);
|
||||
});
|
||||
}
|
||||
|
||||
LibraryContext._(this._analysisContext);
|
||||
|
||||
/**
|
||||
* Computes a [CompilationUnitElement] for the given library/unit pair.
|
||||
*/
|
||||
CompilationUnitElement computeUnitElement(
|
||||
Source librarySource, Source unitSource) {
|
||||
return _analysisContext.computeResult(
|
||||
new LibrarySpecificUnit(librarySource, unitSource),
|
||||
COMPILATION_UNIT_ELEMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up any persistent resources used by this [LibraryContext].
|
||||
*
|
||||
* Should be called once the [LibraryContext] is no longer needed.
|
||||
*/
|
||||
void dispose() {
|
||||
_analysisContext.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a resolved [CompilationUnit] and a list of [AnalysisError]s for
|
||||
* the given library/unit pair.
|
||||
*/
|
||||
ResolutionResult resolveUnit(Source librarySource, Source unitSource) {
|
||||
CompilationUnit resolvedUnit =
|
||||
_analysisContext.resolveCompilationUnit2(unitSource, librarySource);
|
||||
List<AnalysisError> errors = _analysisContext.computeErrors(unitSource);
|
||||
return new ResolutionResult(resolvedUnit, errors);
|
||||
}
|
||||
|
||||
static AnalysisContext _createAnalysisContext(
|
||||
AnalysisOptions _analysisOptions,
|
||||
DeclaredVariables declaredVariables,
|
||||
SourceFactory _sourceFactory,
|
||||
FileSystemState _fsState,
|
||||
SummaryDataStore store) {
|
||||
AnalysisContextImpl analysisContext =
|
||||
AnalysisEngine.instance.createAnalysisContext();
|
||||
analysisContext.useSdkCachePartition = false;
|
||||
analysisContext.analysisOptions = _analysisOptions;
|
||||
analysisContext.declaredVariables.addAll(declaredVariables);
|
||||
analysisContext.sourceFactory = _sourceFactory.clone();
|
||||
analysisContext.contentCache = new _ContentCacheWrapper(_fsState);
|
||||
analysisContext.resultProvider =
|
||||
new InputPackagesResultProvider(analysisContext, store);
|
||||
return analysisContext;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Container object holding the result of a call to
|
||||
* [LibraryContext.resolveUnit].
|
||||
*/
|
||||
class ResolutionResult {
|
||||
final CompilationUnit resolvedUnit;
|
||||
final List<AnalysisError> errors;
|
||||
|
||||
ResolutionResult(this.resolvedUnit, this.errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* [ContentCache] wrapper around [FileContentOverlay].
|
||||
*/
|
||||
class _ContentCacheWrapper implements ContentCache {
|
||||
final FileSystemState fsState;
|
||||
|
||||
_ContentCacheWrapper(this.fsState);
|
||||
|
||||
@override
|
||||
void accept(ContentCacheVisitor visitor) {
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
String getContents(Source source) {
|
||||
return _getFileForSource(source).content;
|
||||
}
|
||||
|
||||
@override
|
||||
bool getExists(Source source) {
|
||||
if (source.isInSystemLibrary) {
|
||||
return true;
|
||||
}
|
||||
return _getFileForSource(source).exists;
|
||||
}
|
||||
|
||||
@override
|
||||
int getModificationStamp(Source source) {
|
||||
if (source.isInSystemLibrary) {
|
||||
return 0;
|
||||
}
|
||||
return _getFileForSource(source).exists ? 0 : -1;
|
||||
}
|
||||
|
||||
@override
|
||||
String setContents(Source source, String contents) {
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
|
||||
FileState _getFileForSource(Source source) {
|
||||
String path = source.fullName;
|
||||
return fsState.getFileForPath(path);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue