mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:27:43 +00:00
context_builder refactoring copies
Copies of context building bits for context creation refactoring work. Change-Id: I2ee8d7e03a33bb6f450c190ad59459bbf87cef62 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/333122 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Phil Quitslund <pquitslund@google.com>
This commit is contained in:
parent
0544ecba9a
commit
e2aa60ddf3
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) 2018, 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/dart/analysis/analysis_context_collection.dart';
|
||||
import 'package:analyzer/dart/analysis/context_locator.dart';
|
||||
import 'package:analyzer/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/dart/analysis/declared_variables.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_builder.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
|
||||
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
|
||||
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
|
||||
import 'package:analyzer/src/dart/analysis/unlinked_unit_store.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
||||
import 'package:analyzer/src/generated/sdk.dart';
|
||||
import 'package:analyzer/src/summary2/kernel_compilation_service.dart';
|
||||
import 'package:analyzer/src/summary2/macro.dart';
|
||||
import 'package:analyzer/src/util/sdk.dart';
|
||||
|
||||
/// An implementation of [AnalysisContextCollection].
|
||||
class AnalysisContextCollectionImpl2 implements AnalysisContextCollection {
|
||||
/// The resource provider used to access the file system.
|
||||
final ResourceProvider resourceProvider;
|
||||
|
||||
/// The support for executing macros.
|
||||
late final MacroSupport macroSupport;
|
||||
|
||||
/// The shared container into which drivers record files ownership.
|
||||
final OwnedFiles ownedFiles = OwnedFiles();
|
||||
|
||||
/// The list of analysis contexts.
|
||||
@override
|
||||
final List<DriverBasedAnalysisContext> contexts = [];
|
||||
|
||||
/// Initialize a newly created analysis context manager.
|
||||
AnalysisContextCollectionImpl2({
|
||||
ByteStore? byteStore,
|
||||
Map<String, String>? declaredVariables,
|
||||
bool drainStreams = true,
|
||||
bool enableIndex = false,
|
||||
required List<String> includedPaths,
|
||||
List<String>? excludedPaths,
|
||||
List<String>? librarySummaryPaths,
|
||||
String? optionsFile,
|
||||
String? packagesFile,
|
||||
PerformanceLog? performanceLog,
|
||||
ResourceProvider? resourceProvider,
|
||||
bool retainDataForTesting = false,
|
||||
String? sdkPath,
|
||||
String? sdkSummaryPath,
|
||||
AnalysisDriverScheduler? scheduler,
|
||||
FileContentCache? fileContentCache,
|
||||
UnlinkedUnitStore? unlinkedUnitStore,
|
||||
InfoDeclarationStore? infoDeclarationStore,
|
||||
@Deprecated('Use updateAnalysisOptions2, which must be a function that '
|
||||
'accepts a second parameter')
|
||||
void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
|
||||
void Function({
|
||||
required AnalysisOptionsImpl analysisOptions,
|
||||
required ContextRoot contextRoot,
|
||||
required DartSdk sdk,
|
||||
})? updateAnalysisOptions2,
|
||||
MacroSupport? macroSupport,
|
||||
}) : resourceProvider =
|
||||
resourceProvider ?? PhysicalResourceProvider.INSTANCE {
|
||||
sdkPath ??= getSdkPath();
|
||||
|
||||
_throwIfAnyNotAbsoluteNormalizedPath(includedPaths);
|
||||
_throwIfNotAbsoluteNormalizedPath(sdkPath);
|
||||
|
||||
if (updateAnalysisOptions != null && updateAnalysisOptions2 != null) {
|
||||
throw ArgumentError(
|
||||
'Either updateAnalysisOptions or updateAnalysisOptions2 must be '
|
||||
'given, but not both.');
|
||||
}
|
||||
|
||||
this.macroSupport = macroSupport ??= KernelMacroSupport();
|
||||
|
||||
var contextLocator = ContextLocator(
|
||||
resourceProvider: this.resourceProvider,
|
||||
);
|
||||
var roots = contextLocator.locateRoots(
|
||||
includedPaths: includedPaths,
|
||||
excludedPaths: excludedPaths,
|
||||
optionsFile: optionsFile,
|
||||
packagesFile: packagesFile,
|
||||
);
|
||||
for (var root in roots) {
|
||||
var contextBuilder = ContextBuilderImpl(
|
||||
resourceProvider: this.resourceProvider,
|
||||
);
|
||||
var context = contextBuilder.createContext(
|
||||
byteStore: byteStore,
|
||||
contextRoot: root,
|
||||
declaredVariables: DeclaredVariables.fromMap(declaredVariables ?? {}),
|
||||
drainStreams: drainStreams,
|
||||
enableIndex: enableIndex,
|
||||
librarySummaryPaths: librarySummaryPaths,
|
||||
performanceLog: performanceLog,
|
||||
retainDataForTesting: retainDataForTesting,
|
||||
sdkPath: sdkPath,
|
||||
sdkSummaryPath: sdkSummaryPath,
|
||||
scheduler: scheduler,
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
updateAnalysisOptions: updateAnalysisOptions,
|
||||
updateAnalysisOptions2: updateAnalysisOptions2,
|
||||
fileContentCache: fileContentCache,
|
||||
unlinkedUnitStore: unlinkedUnitStore ?? UnlinkedUnitStoreImpl(),
|
||||
infoDeclarationStore: infoDeclarationStore,
|
||||
macroSupport: macroSupport,
|
||||
ownedFiles: ownedFiles,
|
||||
);
|
||||
contexts.add(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if the read state of configuration files is consistent
|
||||
/// with their current state on the file system. We use this as a work
|
||||
/// around an issue with watching for file system changes.
|
||||
bool get areWorkspacesConsistent {
|
||||
for (var analysisContext in contexts) {
|
||||
var contextRoot = analysisContext.contextRoot;
|
||||
var workspace = contextRoot.workspace;
|
||||
if (!workspace.isConsistentWithFileSystem) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
DriverBasedAnalysisContext contextFor(String path) {
|
||||
_throwIfNotAbsoluteNormalizedPath(path);
|
||||
|
||||
for (var context in contexts) {
|
||||
if (context.contextRoot.isAnalyzed(path)) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
throw StateError('Unable to find the context to $path');
|
||||
}
|
||||
|
||||
Future<void> dispose({
|
||||
bool forTesting = false,
|
||||
}) async {
|
||||
for (final analysisContext in contexts) {
|
||||
await analysisContext.driver.dispose2();
|
||||
}
|
||||
await macroSupport.dispose();
|
||||
// If there are other collections, they will have to start it again.
|
||||
if (!forTesting) {
|
||||
await KernelCompilationService.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// Check every element with [_throwIfNotAbsoluteNormalizedPath].
|
||||
void _throwIfAnyNotAbsoluteNormalizedPath(List<String> paths) {
|
||||
for (var path in paths) {
|
||||
_throwIfNotAbsoluteNormalizedPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// The driver supports only absolute normalized paths, this method is used
|
||||
/// to validate any input paths to prevent errors later.
|
||||
void _throwIfNotAbsoluteNormalizedPath(String path) {
|
||||
var pathContext = resourceProvider.pathContext;
|
||||
if (!pathContext.isAbsolute(path) || pathContext.normalize(path) != path) {
|
||||
throw ArgumentError(
|
||||
'Only absolute normalized paths are supported: $path');
|
||||
}
|
||||
}
|
||||
}
|
271
pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
Normal file
271
pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
Normal file
|
@ -0,0 +1,271 @@
|
|||
// Copyright (c) 2018, 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/dart/analysis/context_builder.dart';
|
||||
import 'package:analyzer/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/dart/analysis/declared_variables.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
|
||||
import 'package:analyzer/src/analysis_options/apply_options.dart';
|
||||
import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
|
||||
import 'package:analyzer/src/context/packages.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart'
|
||||
show ByteStore, MemoryByteStore;
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart'
|
||||
show
|
||||
AnalysisDriver,
|
||||
AnalysisDriverScheduler,
|
||||
AnalysisDriverTestView,
|
||||
OwnedFiles;
|
||||
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
|
||||
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
|
||||
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/performance_logger.dart'
|
||||
show PerformanceLog;
|
||||
import 'package:analyzer/src/dart/analysis/unlinked_unit_store.dart';
|
||||
import 'package:analyzer/src/dart/sdk/sdk.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
||||
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
|
||||
import 'package:analyzer/src/generated/source.dart';
|
||||
import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
|
||||
import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
||||
import 'package:analyzer/src/summary/summary_sdk.dart';
|
||||
import 'package:analyzer/src/summary2/macro.dart';
|
||||
import 'package:analyzer/src/summary2/package_bundle_format.dart';
|
||||
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
|
||||
import 'package:analyzer/src/util/sdk.dart';
|
||||
import 'package:analyzer/src/workspace/workspace.dart';
|
||||
|
||||
/// An implementation of a context builder.
|
||||
class ContextBuilderImpl2 implements ContextBuilder {
|
||||
/// The resource provider used to access the file system.
|
||||
final ResourceProvider resourceProvider;
|
||||
|
||||
/// Initialize a newly created context builder. If a [resourceProvider] is
|
||||
/// given, then it will be used to access the file system, otherwise the
|
||||
/// default resource provider will be used.
|
||||
ContextBuilderImpl2({ResourceProvider? resourceProvider})
|
||||
: resourceProvider =
|
||||
resourceProvider ?? PhysicalResourceProvider.INSTANCE;
|
||||
|
||||
@override
|
||||
DriverBasedAnalysisContext createContext({
|
||||
ByteStore? byteStore,
|
||||
required ContextRoot contextRoot,
|
||||
DeclaredVariables? declaredVariables,
|
||||
bool drainStreams = true,
|
||||
bool enableIndex = false,
|
||||
List<String>? librarySummaryPaths,
|
||||
PerformanceLog? performanceLog,
|
||||
bool retainDataForTesting = false,
|
||||
AnalysisDriverScheduler? scheduler,
|
||||
String? sdkPath,
|
||||
String? sdkSummaryPath,
|
||||
@Deprecated('Use updateAnalysisOptions2')
|
||||
void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
|
||||
void Function({
|
||||
required AnalysisOptionsImpl analysisOptions,
|
||||
required ContextRoot contextRoot,
|
||||
required DartSdk sdk,
|
||||
})? updateAnalysisOptions2,
|
||||
FileContentCache? fileContentCache,
|
||||
UnlinkedUnitStore? unlinkedUnitStore,
|
||||
InfoDeclarationStore? infoDeclarationStore,
|
||||
MacroSupport? macroSupport,
|
||||
OwnedFiles? ownedFiles,
|
||||
}) {
|
||||
// TODO(scheglov) Remove this, and make `sdkPath` required.
|
||||
sdkPath ??= getSdkPath();
|
||||
ArgumentError.checkNotNull(sdkPath, 'sdkPath');
|
||||
if (updateAnalysisOptions != null && updateAnalysisOptions2 != null) {
|
||||
throw ArgumentError(
|
||||
'Either updateAnalysisOptions or updateAnalysisOptions2 must be '
|
||||
'given, but not both.');
|
||||
}
|
||||
|
||||
byteStore ??= MemoryByteStore();
|
||||
performanceLog ??= PerformanceLog(null);
|
||||
|
||||
if (scheduler == null) {
|
||||
scheduler = AnalysisDriverScheduler(performanceLog);
|
||||
scheduler.start();
|
||||
}
|
||||
|
||||
SummaryDataStore? summaryData;
|
||||
if (librarySummaryPaths != null) {
|
||||
summaryData = SummaryDataStore();
|
||||
for (var summaryPath in librarySummaryPaths) {
|
||||
var bytes = resourceProvider.getFile(summaryPath).readAsBytesSync();
|
||||
var bundle = PackageBundleReader(bytes);
|
||||
summaryData.addBundle(summaryPath, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
var workspace = contextRoot.workspace;
|
||||
var sdk = _createSdk(
|
||||
workspace: workspace,
|
||||
sdkPath: sdkPath,
|
||||
sdkSummaryPath: sdkSummaryPath,
|
||||
);
|
||||
|
||||
// TODO(scheglov) Ensure that "librarySummaryPaths" not null only
|
||||
// when "sdkSummaryPath" is not null.
|
||||
if (sdk is SummaryBasedDartSdk) {
|
||||
summaryData?.addBundle(null, sdk.bundle);
|
||||
}
|
||||
|
||||
var sourceFactory = workspace.createSourceFactory(sdk, summaryData);
|
||||
|
||||
var options = _getAnalysisOptions(contextRoot, sourceFactory);
|
||||
if (updateAnalysisOptions != null) {
|
||||
updateAnalysisOptions(options);
|
||||
} else if (updateAnalysisOptions2 != null) {
|
||||
updateAnalysisOptions2(
|
||||
analysisOptions: options,
|
||||
contextRoot: contextRoot,
|
||||
sdk: sdk,
|
||||
);
|
||||
}
|
||||
|
||||
final analysisContext =
|
||||
DriverBasedAnalysisContext(resourceProvider, contextRoot);
|
||||
|
||||
var driver = AnalysisDriver(
|
||||
scheduler: scheduler,
|
||||
logger: performanceLog,
|
||||
resourceProvider: resourceProvider,
|
||||
byteStore: byteStore,
|
||||
sourceFactory: sourceFactory,
|
||||
analysisOptions: options,
|
||||
packages: _createPackageMap(
|
||||
contextRoot: contextRoot,
|
||||
),
|
||||
analysisContext: analysisContext,
|
||||
enableIndex: enableIndex,
|
||||
externalSummaries: summaryData,
|
||||
retainDataForTesting: retainDataForTesting,
|
||||
fileContentCache: fileContentCache,
|
||||
unlinkedUnitStore: unlinkedUnitStore,
|
||||
infoDeclarationStore: infoDeclarationStore,
|
||||
macroSupport: macroSupport,
|
||||
declaredVariables: declaredVariables,
|
||||
testView: retainDataForTesting ? AnalysisDriverTestView() : null,
|
||||
ownedFiles: ownedFiles,
|
||||
);
|
||||
|
||||
// AnalysisDriver reports results into streams.
|
||||
// We need to drain these streams to avoid memory leak.
|
||||
if (drainStreams) {
|
||||
driver.results.drain<void>();
|
||||
driver.exceptions.drain<void>();
|
||||
}
|
||||
|
||||
return analysisContext;
|
||||
}
|
||||
|
||||
/// Return [Packages] to analyze the [contextRoot].
|
||||
///
|
||||
/// TODO(scheglov) Get [Packages] from [Workspace]?
|
||||
Packages _createPackageMap({
|
||||
required ContextRoot contextRoot,
|
||||
}) {
|
||||
var packagesFile = contextRoot.packagesFile;
|
||||
if (packagesFile != null) {
|
||||
return parsePackageConfigJsonFile(resourceProvider, packagesFile);
|
||||
} else {
|
||||
return Packages.empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the SDK that should be used to analyze code.
|
||||
DartSdk _createSdk({
|
||||
required Workspace workspace,
|
||||
String? sdkPath,
|
||||
String? sdkSummaryPath,
|
||||
}) {
|
||||
if (sdkSummaryPath != null) {
|
||||
var file = resourceProvider.getFile(sdkSummaryPath);
|
||||
var bytes = file.readAsBytesSync();
|
||||
return SummaryBasedDartSdk.forBundle(
|
||||
PackageBundleReader(bytes),
|
||||
);
|
||||
}
|
||||
|
||||
var folderSdk = FolderBasedDartSdk(
|
||||
resourceProvider,
|
||||
resourceProvider.getFolder(sdkPath!),
|
||||
);
|
||||
|
||||
{
|
||||
// TODO(scheglov) We already had partial SourceFactory in ContextLocatorImpl.
|
||||
var partialSourceFactory = workspace.createSourceFactory(null, null);
|
||||
var embedderYamlSource = partialSourceFactory.forUri(
|
||||
'package:sky_engine/_embedder.yaml',
|
||||
);
|
||||
if (embedderYamlSource != null) {
|
||||
var embedderYamlPath = embedderYamlSource.fullName;
|
||||
var libFolder = resourceProvider.getFile(embedderYamlPath).parent;
|
||||
var locator = EmbedderYamlLocator.forLibFolder(libFolder);
|
||||
var embedderMap = locator.embedderYamls;
|
||||
if (embedderMap.isNotEmpty) {
|
||||
return EmbedderSdk(
|
||||
resourceProvider,
|
||||
embedderMap,
|
||||
languageVersion: folderSdk.languageVersion,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return folderSdk;
|
||||
}
|
||||
|
||||
/// Return the `pubspec.yaml` file that should be used when analyzing code in
|
||||
/// the [contextRoot], possibly `null`.
|
||||
///
|
||||
/// TODO(scheglov) Get it from [Workspace]?
|
||||
File? _findPubspecFile(ContextRoot contextRoot) {
|
||||
for (var current in contextRoot.root.withAncestors) {
|
||||
var file = current.getChildAssumingFile(file_paths.pubspecYaml);
|
||||
if (file.exists) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Return the analysis options that should be used to analyze code in the
|
||||
/// [contextRoot].
|
||||
///
|
||||
/// TODO(scheglov) We have already loaded it once in [ContextLocatorImpl].
|
||||
AnalysisOptionsImpl _getAnalysisOptions(
|
||||
ContextRoot contextRoot,
|
||||
SourceFactory sourceFactory,
|
||||
) {
|
||||
var options = AnalysisOptionsImpl();
|
||||
|
||||
var optionsFile = contextRoot.optionsFile;
|
||||
if (optionsFile != null) {
|
||||
try {
|
||||
var provider = AnalysisOptionsProvider(sourceFactory);
|
||||
var optionsMap = provider.getOptionsFromFile(optionsFile);
|
||||
options.applyOptions(optionsMap);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
var pubspecFile = _findPubspecFile(contextRoot);
|
||||
if (pubspecFile != null) {
|
||||
var extractor = SdkConstraintExtractor(pubspecFile);
|
||||
var sdkVersionConstraint = extractor.constraint();
|
||||
if (sdkVersionConstraint != null) {
|
||||
options.sdkVersionConstraint = sdkVersionConstraint;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ class DriverBasedAnalysisContext implements AnalysisContext {
|
|||
this.resourceProvider,
|
||||
this.contextRoot, [
|
||||
@Deprecated('AnalysisDriver will set itself, remove this')
|
||||
AnalysisDriver? analysisDriver,
|
||||
AnalysisDriver? analysisDriver,
|
||||
]);
|
||||
|
||||
@override
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
// Copyright (c) 2018, 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/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
|
||||
import 'package:analyzer/src/dart/analysis/analysis_context_collection2.dart';
|
||||
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
|
||||
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
|
||||
import 'package:linter/src/rules.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(AnalysisContextCollectionTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class AnalysisContextCollectionTest with ResourceProviderMixin {
|
||||
Folder get sdkRoot => newFolder('/sdk');
|
||||
|
||||
void setUp() {
|
||||
createMockSdk(
|
||||
resourceProvider: resourceProvider,
|
||||
root: sdkRoot,
|
||||
);
|
||||
registerLintRules();
|
||||
}
|
||||
|
||||
test_contextFor_noContext() {
|
||||
var collection = _newCollection(includedPaths: [convertPath('/root')]);
|
||||
expect(
|
||||
() => collection.contextFor(convertPath('/other/test.dart')),
|
||||
throwsStateError,
|
||||
);
|
||||
}
|
||||
|
||||
test_contextFor_notAbsolute() {
|
||||
var collection = _newCollection(includedPaths: [convertPath('/root')]);
|
||||
expect(
|
||||
() => collection.contextFor(convertPath('test.dart')),
|
||||
throwsArgumentError,
|
||||
);
|
||||
}
|
||||
|
||||
test_contextFor_notNormalized() {
|
||||
var collection = _newCollection(includedPaths: [convertPath('/root')]);
|
||||
expect(
|
||||
() => collection.contextFor(convertPath('/test/lib/../lib/test.dart')),
|
||||
throwsArgumentError,
|
||||
);
|
||||
}
|
||||
|
||||
test_new_analysisOptions_includes() {
|
||||
var rootFolder = newFolder('/home/test');
|
||||
var fooFolder = newFolder('/home/packages/foo');
|
||||
newFile('${fooFolder.path}/lib/included.yaml', r'''
|
||||
linter:
|
||||
rules:
|
||||
- empty_statements
|
||||
''');
|
||||
|
||||
var packageConfigFileBuilder = PackageConfigFileBuilder()
|
||||
..add(name: 'foo', rootPath: fooFolder.path);
|
||||
newPackageConfigJsonFile(
|
||||
rootFolder.path,
|
||||
packageConfigFileBuilder.toContent(toUriStr: toUriStr),
|
||||
);
|
||||
|
||||
newAnalysisOptionsYamlFile(rootFolder.path, r'''
|
||||
include: package:foo/included.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- unnecessary_parenthesis
|
||||
''');
|
||||
|
||||
var collection = _newCollection(includedPaths: [rootFolder.path]);
|
||||
var analysisContext = collection.contextFor(rootFolder.path);
|
||||
var analysisOptions = analysisContext.analysisOptions;
|
||||
|
||||
expect(
|
||||
analysisOptions.lintRules.map((e) => e.name),
|
||||
unorderedEquals(['empty_statements', 'unnecessary_parenthesis']),
|
||||
);
|
||||
}
|
||||
|
||||
test_new_analysisOptions_lintRules() {
|
||||
var rootFolder = newFolder('/home/test');
|
||||
newAnalysisOptionsYamlFile(rootFolder.path, r'''
|
||||
linter:
|
||||
rules:
|
||||
- non_existent_lint_rule
|
||||
- unnecessary_parenthesis
|
||||
''');
|
||||
|
||||
var collection = _newCollection(includedPaths: [rootFolder.path]);
|
||||
var analysisContext = collection.contextFor(rootFolder.path);
|
||||
var analysisOptions = analysisContext.analysisOptions;
|
||||
|
||||
expect(
|
||||
analysisOptions.lintRules.map((e) => e.name),
|
||||
unorderedEquals(['unnecessary_parenthesis']),
|
||||
);
|
||||
}
|
||||
|
||||
test_new_includedPaths_notAbsolute() {
|
||||
expect(
|
||||
() => AnalysisContextCollectionImpl(includedPaths: ['root']),
|
||||
throwsArgumentError,
|
||||
);
|
||||
}
|
||||
|
||||
test_new_includedPaths_notNormalized() {
|
||||
expect(
|
||||
() => AnalysisContextCollectionImpl(
|
||||
includedPaths: [convertPath('/root/lib/../lib')]),
|
||||
throwsArgumentError,
|
||||
);
|
||||
}
|
||||
|
||||
test_new_outer_inner() {
|
||||
var outerFolder = newFolder('/test/outer');
|
||||
newFile('/test/outer/lib/outer.dart', '');
|
||||
|
||||
var innerFolder = newFolder('/test/outer/inner');
|
||||
newAnalysisOptionsYamlFile('/test/outer/inner', '');
|
||||
newFile('/test/outer/inner/inner.dart', '');
|
||||
|
||||
var collection = _newCollection(includedPaths: [outerFolder.path]);
|
||||
|
||||
expect(collection.contexts, hasLength(2));
|
||||
|
||||
var outerContext = collection.contexts
|
||||
.singleWhere((c) => c.contextRoot.root == outerFolder);
|
||||
var innerContext = collection.contexts
|
||||
.singleWhere((c) => c.contextRoot.root == innerFolder);
|
||||
expect(innerContext, isNot(same(outerContext)));
|
||||
|
||||
// Outer and inner contexts own corresponding files.
|
||||
expect(collection.contextFor(convertPath('/test/outer/lib/outer.dart')),
|
||||
same(outerContext));
|
||||
expect(collection.contextFor(convertPath('/test/outer/inner/inner.dart')),
|
||||
same(innerContext));
|
||||
|
||||
// The file does not have to exist, during creation, or at all.
|
||||
expect(collection.contextFor(convertPath('/test/outer/lib/outer2.dart')),
|
||||
same(outerContext));
|
||||
expect(collection.contextFor(convertPath('/test/outer/inner/inner2.dart')),
|
||||
same(innerContext));
|
||||
}
|
||||
|
||||
test_new_sdkPath_notAbsolute() {
|
||||
expect(
|
||||
() => AnalysisContextCollectionImpl(
|
||||
includedPaths: ['/root'], sdkPath: 'sdk'),
|
||||
throwsArgumentError,
|
||||
);
|
||||
}
|
||||
|
||||
test_new_sdkPath_notNormalized() {
|
||||
expect(
|
||||
() => AnalysisContextCollectionImpl(
|
||||
includedPaths: [convertPath('/root')], sdkPath: '/home/sdk/../sdk'),
|
||||
throwsArgumentError,
|
||||
);
|
||||
}
|
||||
|
||||
AnalysisContextCollectionImpl2 _newCollection(
|
||||
{required List<String> includedPaths}) {
|
||||
return AnalysisContextCollectionImpl2(
|
||||
resourceProvider: resourceProvider,
|
||||
includedPaths: includedPaths,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
}
|
||||
}
|
249
pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
Normal file
249
pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
Normal file
|
@ -0,0 +1,249 @@
|
|||
// Copyright (c) 2018, 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/dart/analysis/analysis_context.dart';
|
||||
import 'package:analyzer/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/dart/analysis/declared_variables.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/context/packages.dart';
|
||||
import 'package:analyzer/src/context/source.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_builder.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_builder2.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_locator.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
||||
import 'package:analyzer/src/generated/source.dart';
|
||||
import 'package:analyzer/src/source/package_map_resolver.dart';
|
||||
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
|
||||
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
|
||||
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
|
||||
import 'package:analyzer/src/workspace/basic.dart';
|
||||
import 'package:analyzer/src/workspace/blaze.dart';
|
||||
import 'package:analyzer/src/workspace/pub.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(ContextBuilderImplTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ContextBuilderImplTest with ResourceProviderMixin {
|
||||
late final ContextBuilderImpl2 contextBuilder;
|
||||
late final ContextRoot contextRoot;
|
||||
|
||||
Folder get sdkRoot => newFolder('/sdk');
|
||||
|
||||
void assertEquals(DeclaredVariables actual, DeclaredVariables expected) {
|
||||
Iterable<String> actualNames = actual.variableNames;
|
||||
Iterable<String> expectedNames = expected.variableNames;
|
||||
expect(actualNames, expectedNames);
|
||||
for (String name in expectedNames) {
|
||||
expect(actual.get(name), expected.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
void setUp() {
|
||||
createMockSdk(
|
||||
resourceProvider: resourceProvider,
|
||||
root: sdkRoot,
|
||||
);
|
||||
|
||||
var folder = newFolder('/home/test');
|
||||
contextBuilder = ContextBuilderImpl2(resourceProvider: resourceProvider);
|
||||
var workspace =
|
||||
BasicWorkspace.find(resourceProvider, Packages.empty, folder.path);
|
||||
contextRoot = ContextRootImpl(resourceProvider, folder, workspace);
|
||||
}
|
||||
|
||||
void test_analysisOptions_invalid() {
|
||||
var projectPath = convertPath('/home/test');
|
||||
newAnalysisOptionsYamlFile(projectPath, ';');
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
var analysisOptions = analysisContext.analysisOptionsImpl;
|
||||
_expectEqualOptions(analysisOptions, AnalysisOptionsImpl());
|
||||
}
|
||||
|
||||
void test_analysisOptions_languageOptions() {
|
||||
var projectPath = convertPath('/home/test');
|
||||
newAnalysisOptionsYamlFile(
|
||||
projectPath,
|
||||
AnalysisOptionsFileConfig(
|
||||
strictRawTypes: true,
|
||||
).toContent(),
|
||||
);
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
var analysisOptions = analysisContext.analysisOptionsImpl;
|
||||
_expectEqualOptions(
|
||||
analysisOptions,
|
||||
AnalysisOptionsImpl()..strictRawTypes = true,
|
||||
);
|
||||
}
|
||||
|
||||
void test_analysisOptions_sdkVersionConstraint_hasPubspec_hasSdk() {
|
||||
var projectPath = convertPath('/home/test');
|
||||
newPubspecYamlFile(projectPath, '''
|
||||
environment:
|
||||
sdk: ^2.1.0
|
||||
''');
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
var analysisOptions = analysisContext.analysisOptionsImpl;
|
||||
expect(analysisOptions.sdkVersionConstraint.toString(), '^2.1.0');
|
||||
}
|
||||
|
||||
void test_analysisOptions_sdkVersionConstraint_noPubspec() {
|
||||
var projectPath = convertPath('/home/test');
|
||||
newFile('$projectPath/lib/a.dart', '');
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
var analysisOptions = analysisContext.driver.analysisOptions;
|
||||
expect(analysisOptions.sdkVersionConstraint, isNull);
|
||||
}
|
||||
|
||||
test_createContext_declaredVariables() {
|
||||
DeclaredVariables declaredVariables =
|
||||
DeclaredVariables.fromMap({'foo': 'true'});
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
declaredVariables: declaredVariables,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
assertEquals(context.driver.declaredVariables, declaredVariables);
|
||||
}
|
||||
|
||||
test_createContext_declaredVariables_sdkPath() {
|
||||
DeclaredVariables declaredVariables =
|
||||
DeclaredVariables.fromMap({'bar': 'true'});
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
declaredVariables: declaredVariables,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
assertEquals(context.driver.declaredVariables, declaredVariables);
|
||||
expect(
|
||||
context.driver.sourceFactory.dartSdk!.mapDartUri('dart:core')!.fullName,
|
||||
sdkRoot.getChildAssumingFile('lib/core/core.dart').path,
|
||||
);
|
||||
}
|
||||
|
||||
test_createContext_defaults() {
|
||||
AnalysisContext context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
}
|
||||
|
||||
test_createContext_sdkPath() {
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
expect(
|
||||
context.driver.sourceFactory.dartSdk!.mapDartUri('dart:core')!.fullName,
|
||||
sdkRoot.getChildAssumingFile('lib/core/core.dart').path,
|
||||
);
|
||||
}
|
||||
|
||||
test_createContext_sdkRoot() {
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot, sdkPath: sdkRoot.path);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
expect(context.sdkRoot, sdkRoot);
|
||||
}
|
||||
|
||||
void test_sourceFactory_blazeWorkspace() {
|
||||
var projectPath = convertPath('/workspace/my/module');
|
||||
newFile('/workspace/${file_paths.blazeWorkspaceMarker}', '');
|
||||
newFolder('/workspace/blaze-bin');
|
||||
newFolder('/workspace/blaze-genfiles');
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
expect(analysisContext.contextRoot.workspace, isA<BlazeWorkspace>());
|
||||
|
||||
expect(
|
||||
analysisContext.uriResolvers,
|
||||
unorderedEquals([
|
||||
isA<DartUriResolver>(),
|
||||
isA<BlazePackageUriResolver>(),
|
||||
isA<BlazeFileUriResolver>(),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
void test_sourceFactory_pubWorkspace() {
|
||||
var projectPath = convertPath('/home/my');
|
||||
newFile('/home/my/pubspec.yaml', '');
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
expect(analysisContext.contextRoot.workspace, isA<PubWorkspace>());
|
||||
|
||||
expect(
|
||||
analysisContext.uriResolvers,
|
||||
unorderedEquals([
|
||||
isA<DartUriResolver>(),
|
||||
isA<PackageMapUriResolver>(),
|
||||
isA<ResourceUriResolver>(),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
/// Return a single expected analysis context at the [path].
|
||||
DriverBasedAnalysisContext _createSingleAnalysisContext(String path) {
|
||||
var roots = ContextLocatorImpl(
|
||||
resourceProvider: resourceProvider,
|
||||
).locateRoots(includedPaths: [path]);
|
||||
|
||||
return ContextBuilderImpl(
|
||||
resourceProvider: resourceProvider,
|
||||
).createContext(
|
||||
contextRoot: roots.single,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
}
|
||||
|
||||
static void _expectEqualOptions(
|
||||
AnalysisOptionsImpl actual,
|
||||
AnalysisOptionsImpl expected,
|
||||
) {
|
||||
// TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
|
||||
expect(actual.enableTiming, expected.enableTiming);
|
||||
expect(actual.lint, expected.lint);
|
||||
expect(actual.warning, expected.warning);
|
||||
expect(
|
||||
actual.lintRules.map((l) => l.name),
|
||||
unorderedEquals(expected.lintRules.map((l) => l.name)),
|
||||
);
|
||||
expect(
|
||||
actual.propagateLinterExceptions, expected.propagateLinterExceptions);
|
||||
expect(actual.strictInference, expected.strictInference);
|
||||
expect(actual.strictRawTypes, expected.strictRawTypes);
|
||||
}
|
||||
}
|
||||
|
||||
extension on DriverBasedAnalysisContext {
|
||||
AnalysisOptionsImpl get analysisOptionsImpl {
|
||||
return driver.analysisOptions as AnalysisOptionsImpl;
|
||||
}
|
||||
|
||||
List<UriResolver> get uriResolvers {
|
||||
return (driver.sourceFactory as SourceFactoryImpl).resolvers;
|
||||
}
|
||||
}
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import 'analysis_context_collection2_test.dart' as analysis_context_collection2;
|
||||
import 'analysis_context_collection_test.dart' as analysis_context_collection;
|
||||
import 'analysis_options_map_test.dart' as analysis_options_map;
|
||||
import 'byte_store_test.dart' as byte_store_test;
|
||||
import 'cache_test.dart' as cache_test;
|
||||
import 'context_builder2_test.dart' as context_builder2;
|
||||
import 'context_builder_test.dart' as context_builder;
|
||||
import 'context_locator2_test.dart' as context_locator2;
|
||||
import 'context_locator_test.dart' as context_locator;
|
||||
|
@ -35,10 +37,12 @@ import 'uri_converter_test.dart' as uri_converter;
|
|||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
analysis_context_collection.main();
|
||||
analysis_context_collection2.main();
|
||||
analysis_options_map.main();
|
||||
byte_store_test.main();
|
||||
cache_test.main();
|
||||
context_builder.main();
|
||||
context_builder2.main();
|
||||
context_locator.main();
|
||||
context_locator2.main();
|
||||
context_root.main();
|
||||
|
|
Loading…
Reference in a new issue