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:
pq 2023-11-01 04:17:41 +00:00 committed by Commit Queue
parent 0544ecba9a
commit e2aa60ddf3
6 changed files with 884 additions and 1 deletions

View file

@ -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');
}
}
}

View 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;
}
}

View file

@ -28,7 +28,7 @@ class DriverBasedAnalysisContext implements AnalysisContext {
this.resourceProvider,
this.contextRoot, [
@Deprecated('AnalysisDriver will set itself, remove this')
AnalysisDriver? analysisDriver,
AnalysisDriver? analysisDriver,
]);
@override

View file

@ -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,
);
}
}

View 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;
}
}

View file

@ -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();