mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 16:59:47 +00:00
Revert "options map support scaffolding in driver"
This reverts commit 717ce7a69c
.
Reason for revert: breaking Google3
Original change's description:
> options map support scaffolding in driver
>
> Konstantin and I chatted a bit about this so at least some of it shouldn't be too surprising to him but please do feel free to grab me to chat.
>
> That said a few pointers would be handy. Notably, this change:
>
> * introduces a new `SharedOptionsOptionsMap` for use in SDK drivers (and preserve current semantics)
> * this is currently public but will be private once driver is more evolved to accommodate multiple options files
> * removes the shared `_analysisOptions` from the analysis driver with a baby step to using the one shared in SharedOptionsOptionsMap
> * removes context_builder and collection v2 experiments (and tests)
> * I'll harvest some more functionality from these in future changes but for now they're distracting and hard to maintain
>
> This work is all to setup moving analysis options awareness into file state objects which will allow us to remove `sdkVersionConstraint` info from options (finally) and a host of other good stuff (see https://github.com/dart-lang/sdk/issues/54124).
>
>
>
> Change-Id: Ic4278184016d1018b4b5b1c6ac5ba9e2546927a5
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/344860
> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
> Commit-Queue: Phil Quitslund <pquitslund@google.com>
Change-Id: Ia988c5c9cd328d0adce3d8e6ff019e389819a957
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/344960
Auto-Submit: Phil Quitslund <pquitslund@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
437767f4ae
commit
3e319ba752
|
@ -6,7 +6,6 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/context/packages.dart';
|
||||
import 'package:analyzer/src/dart/analysis/analysis_options_map.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
|
||||
|
@ -50,7 +49,6 @@ Future<Uint8List> buildSdkSummary({
|
|||
|
||||
final logger = PerformanceLog(StringBuffer());
|
||||
final scheduler = AnalysisDriverScheduler(logger);
|
||||
final optionsMap = AnalysisOptionsMap.forSharedOptions(AnalysisOptionsImpl());
|
||||
final analysisDriver = AnalysisDriver(
|
||||
scheduler: scheduler,
|
||||
logger: logger,
|
||||
|
@ -59,7 +57,7 @@ Future<Uint8List> buildSdkSummary({
|
|||
sourceFactory: SourceFactory([
|
||||
DartUriResolver(sdk),
|
||||
]),
|
||||
analysisOptionsMap: optionsMap,
|
||||
analysisOptions: AnalysisOptionsImpl(),
|
||||
packages: Packages({}),
|
||||
);
|
||||
scheduler.start();
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
|
|||
import 'package:analyzer/dart/analysis/session.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/context/packages.dart';
|
||||
import 'package:analyzer/src/dart/analysis/analysis_options_map.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
|
||||
|
@ -54,15 +53,13 @@ AnalysisDriverForPackageBuild createAnalysisDriver({
|
|||
|
||||
var logger = PerformanceLog(null);
|
||||
var scheduler = AnalysisDriverScheduler(logger);
|
||||
var sharedOptions = analysisOptions as AnalysisOptionsImpl;
|
||||
var optionsMap = AnalysisOptionsMap.forSharedOptions(sharedOptions);
|
||||
var driver = AnalysisDriver(
|
||||
scheduler: scheduler,
|
||||
logger: logger,
|
||||
resourceProvider: resourceProvider,
|
||||
byteStore: byteStore ?? MemoryByteStore(),
|
||||
sourceFactory: sourceFactory,
|
||||
analysisOptionsMap: optionsMap,
|
||||
analysisOptions: analysisOptions as AnalysisOptionsImpl,
|
||||
externalSummaries: dataStore,
|
||||
packages: packages,
|
||||
);
|
||||
|
|
|
@ -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_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_builder2.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_locator2.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 = ContextLocatorImpl2(
|
||||
resourceProvider: this.resourceProvider,
|
||||
);
|
||||
var roots = contextLocator.locateRoots(
|
||||
includedPaths: includedPaths,
|
||||
excludedPaths: excludedPaths,
|
||||
optionsFile: optionsFile,
|
||||
packagesFile: packagesFile,
|
||||
);
|
||||
for (var root in roots) {
|
||||
var contextBuilder = ContextBuilderImpl2(
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,61 +2,29 @@
|
|||
// 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_options.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/clients/build_resolvers/build_resolvers.dart';
|
||||
|
||||
/// Instances of the class [AnalysisOptionsMap] map [File]s under analysis to
|
||||
/// their corresponding [AnalysisOptions].
|
||||
/// Instances of the class [AnalysisOptionsMap] map [File]s under analysis to their
|
||||
/// corresponding [AnalysisOptions].
|
||||
class AnalysisOptionsMap {
|
||||
final List<OptionsMapEntry> entries = [];
|
||||
|
||||
/// Create an empty [AnalysisOptionsMap] instance.
|
||||
AnalysisOptionsMap();
|
||||
// TODO(pq): final backing representation TBD.
|
||||
final List<({Folder folder, AnalysisOptions options})> _entries = [];
|
||||
|
||||
/// Map this [folder] to the given [options].
|
||||
void add(Folder folder, AnalysisOptions options) {
|
||||
entries.add(OptionsMapEntry(folder, options));
|
||||
_entries.add((folder: folder, options: options));
|
||||
// Sort entries by (reverse) containment (for now).
|
||||
entries.sort((e1, e2) => e1.folder.contains(e2.folder.path) ? 1 : -1);
|
||||
_entries.sort((e1, e2) => e1.folder.contains(e2.folder.path) ? 1 : -1);
|
||||
}
|
||||
|
||||
/// Get the [AnalysisOptions] instance for the given [file] (or `null` if none
|
||||
/// has been set).
|
||||
AnalysisOptions? getOptions(File file) {
|
||||
for (var entry in entries) {
|
||||
for (var entry in _entries) {
|
||||
if (entry.folder.contains(file.path)) return entry.options;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Create an [AnalysisOptionsMap] that holds one set of [sharedOptions] for all
|
||||
/// associated files.
|
||||
// TODO(pq): replace w/ a factory constructor when SharedOptionsOptionsMap is made private
|
||||
static SharedOptionsOptionsMap forSharedOptions(
|
||||
AnalysisOptionsImpl sharedOptions) =>
|
||||
SharedOptionsOptionsMap(sharedOptions);
|
||||
}
|
||||
|
||||
/// Instances of [OptionsMapEntry] associate [Folder]s with their
|
||||
/// corresponding [AnalysisOptions].
|
||||
class OptionsMapEntry {
|
||||
/// The folder containing an options file.
|
||||
final Folder folder;
|
||||
|
||||
/// The corresponding options object.
|
||||
final AnalysisOptions options;
|
||||
|
||||
/// Create a new entry for the give [folder] and corresponding [options];
|
||||
OptionsMapEntry(this.folder, this.options);
|
||||
}
|
||||
|
||||
// TODO(pq): make private when no longer referenced.
|
||||
class SharedOptionsOptionsMap extends AnalysisOptionsMap {
|
||||
/// The [entries] list is empty but that's OK. We'll always just return
|
||||
/// the shared options.
|
||||
final AnalysisOptionsImpl sharedOptions;
|
||||
SharedOptionsOptionsMap(this.sharedOptions);
|
||||
@override
|
||||
AnalysisOptions getOptions(File file) => sharedOptions;
|
||||
}
|
||||
|
|
|
@ -11,10 +11,8 @@ 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/analysis_options_map.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart'
|
||||
show ByteStore, MemoryByteStore;
|
||||
import 'package:analyzer/src/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart'
|
||||
show
|
||||
AnalysisDriver,
|
||||
|
@ -130,18 +128,17 @@ class ContextBuilderImpl implements ContextBuilder {
|
|||
sdk: sdk,
|
||||
);
|
||||
}
|
||||
// TODO(pq): replace w/ a map created directly via `_createOptionsMap`
|
||||
var analysisOptionsMap = AnalysisOptionsMap.forSharedOptions(options);
|
||||
|
||||
final analysisContext =
|
||||
DriverBasedAnalysisContext(resourceProvider, contextRoot);
|
||||
|
||||
var driver = AnalysisDriver(
|
||||
scheduler: scheduler,
|
||||
logger: performanceLog,
|
||||
resourceProvider: resourceProvider,
|
||||
byteStore: byteStore,
|
||||
sourceFactory: sourceFactory,
|
||||
analysisOptionsMap: analysisOptionsMap,
|
||||
analysisOptions: options,
|
||||
packages: _createPackageMap(
|
||||
contextRoot: contextRoot,
|
||||
),
|
||||
|
@ -168,66 +165,6 @@ class ContextBuilderImpl implements ContextBuilder {
|
|||
return analysisContext;
|
||||
}
|
||||
|
||||
/// Create an [AnalysisOptionsMap] for the given [contextRoot].
|
||||
// ignore: unused_element
|
||||
AnalysisOptionsMap _createOptionsMap(
|
||||
ContextRoot contextRoot,
|
||||
SourceFactory sourceFactory,
|
||||
@Deprecated("Use 'updateAnalysisOptions2' instead")
|
||||
void Function(AnalysisOptionsImpl p1)? updateAnalysisOptions,
|
||||
void Function(
|
||||
{required AnalysisOptionsImpl analysisOptions,
|
||||
required ContextRoot contextRoot,
|
||||
required DartSdk sdk})?
|
||||
updateAnalysisOptions2,
|
||||
DartSdk sdk) {
|
||||
var map = AnalysisOptionsMap();
|
||||
var provider = AnalysisOptionsProvider(sourceFactory);
|
||||
var pubspecFile = _findPubspecFile(contextRoot);
|
||||
|
||||
void updateOptions(AnalysisOptionsImpl options) {
|
||||
if (pubspecFile != null) {
|
||||
var extractor = SdkConstraintExtractor(pubspecFile);
|
||||
var sdkVersionConstraint = extractor.constraint();
|
||||
if (sdkVersionConstraint != null) {
|
||||
// TODO(pq): remove
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
options.sdkVersionConstraint = sdkVersionConstraint;
|
||||
}
|
||||
}
|
||||
if (updateAnalysisOptions != null) {
|
||||
updateAnalysisOptions(options);
|
||||
} else if (updateAnalysisOptions2 != null) {
|
||||
updateAnalysisOptions2(
|
||||
analysisOptions: options,
|
||||
contextRoot: contextRoot,
|
||||
sdk: sdk,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var optionsMappings =
|
||||
(contextRoot as ContextRootImpl).optionsFileMap.entries;
|
||||
|
||||
// If there are no options files, we still want to propagate sdk constraints
|
||||
// and options updates to the context root.
|
||||
if (optionsMappings.isEmpty) {
|
||||
var options = AnalysisOptionsImpl();
|
||||
updateOptions(options);
|
||||
map.add(contextRoot.root, options);
|
||||
} else {
|
||||
for (var entry in optionsMappings) {
|
||||
var options = AnalysisOptionsImpl();
|
||||
var optionsYaml = provider.getOptionsFromFile(entry.value);
|
||||
options.applyOptions(optionsYaml);
|
||||
updateOptions(options);
|
||||
map.add(entry.key, options);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/// Return [Packages] to analyze the [contextRoot].
|
||||
///
|
||||
// TODO(scheglov): Get [Packages] from [Workspace]?
|
||||
|
|
337
pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
Normal file
337
pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
Normal file
|
@ -0,0 +1,337 @@
|
|||
// 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/analysis_options_map.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart'
|
||||
show ByteStore, MemoryByteStore;
|
||||
import 'package:analyzer/src/dart/analysis/context_root.dart';
|
||||
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);
|
||||
|
||||
// TODO(pq): remove
|
||||
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 analysisOptionsMap = _createOptionsMap(contextRoot, sourceFactory,
|
||||
updateAnalysisOptions, updateAnalysisOptions2, sdk);
|
||||
|
||||
var driver = AnalysisDriver(
|
||||
scheduler: scheduler,
|
||||
logger: performanceLog,
|
||||
resourceProvider: resourceProvider,
|
||||
byteStore: byteStore,
|
||||
sourceFactory: sourceFactory,
|
||||
analysisOptions: options,
|
||||
analysisOptionsMap: analysisOptionsMap,
|
||||
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;
|
||||
}
|
||||
|
||||
AnalysisOptionsMap _createOptionsMap(
|
||||
ContextRoot contextRoot,
|
||||
SourceFactory sourceFactory,
|
||||
void Function(AnalysisOptionsImpl p1)? updateAnalysisOptions,
|
||||
void Function(
|
||||
{required AnalysisOptionsImpl analysisOptions,
|
||||
required ContextRoot contextRoot,
|
||||
required DartSdk sdk})?
|
||||
updateAnalysisOptions2,
|
||||
DartSdk sdk) {
|
||||
var map = AnalysisOptionsMap();
|
||||
var provider = AnalysisOptionsProvider(sourceFactory);
|
||||
var pubspecFile = _findPubspecFile(contextRoot);
|
||||
|
||||
void updateOptions(AnalysisOptionsImpl options) {
|
||||
if (pubspecFile != null) {
|
||||
var extractor = SdkConstraintExtractor(pubspecFile);
|
||||
var sdkVersionConstraint = extractor.constraint();
|
||||
if (sdkVersionConstraint != null) {
|
||||
// TODO(pq): remove
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
options.sdkVersionConstraint = sdkVersionConstraint;
|
||||
}
|
||||
}
|
||||
if (updateAnalysisOptions != null) {
|
||||
updateAnalysisOptions(options);
|
||||
} else if (updateAnalysisOptions2 != null) {
|
||||
updateAnalysisOptions2(
|
||||
analysisOptions: options,
|
||||
contextRoot: contextRoot,
|
||||
sdk: sdk,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var optionsMappings =
|
||||
(contextRoot as ContextRootImpl).optionsFileMap.entries;
|
||||
|
||||
// If there are no options files, we still want to propagate sdk constraints
|
||||
// and options updates to the context root.
|
||||
if (optionsMappings.isEmpty) {
|
||||
var options = AnalysisOptionsImpl();
|
||||
updateOptions(options);
|
||||
map.add(contextRoot.root, options);
|
||||
} else {
|
||||
for (var entry in optionsMappings) {
|
||||
var options = AnalysisOptionsImpl();
|
||||
var optionsYaml = provider.getOptionsFromFile(entry.value);
|
||||
options.applyOptions(optionsYaml);
|
||||
updateOptions(options);
|
||||
map.add(entry.key, options);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
// TODO(pq): remove
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
options.sdkVersionConstraint = sdkVersionConstraint;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ import 'package:analyzer/src/diagnostic/diagnostic.dart';
|
|||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/exception/exception.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart'
|
||||
show AnalysisContext, AnalysisEngine, AnalysisOptions;
|
||||
show AnalysisContext, AnalysisEngine, AnalysisOptions, AnalysisOptionsImpl;
|
||||
import 'package:analyzer/src/generated/source.dart' show SourceFactory;
|
||||
import 'package:analyzer/src/lint/registry.dart' as linter;
|
||||
import 'package:analyzer/src/summary/api_signature.dart';
|
||||
|
@ -130,6 +130,9 @@ class AnalysisDriver {
|
|||
|
||||
late final StoredFileContentStrategy _fileContentStrategy;
|
||||
|
||||
/// The analysis options to analyze with.
|
||||
final AnalysisOptionsImpl _analysisOptions;
|
||||
|
||||
/// The [Packages] object with packages and their language versions.
|
||||
final Packages _packages;
|
||||
|
||||
|
@ -238,7 +241,6 @@ class AnalysisDriver {
|
|||
|
||||
final AnalysisDriverTestView? testView;
|
||||
|
||||
// TODO(pq): replace with an analysis options map.
|
||||
late FeatureSetProvider featureSetProvider;
|
||||
|
||||
late FileSystemState _fsState;
|
||||
|
@ -267,8 +269,9 @@ class AnalysisDriver {
|
|||
bool _disposed = false;
|
||||
|
||||
/// A map that associates files to corresponding analysis options.
|
||||
// TODO(pq): retype to OptionsOptionsMap
|
||||
final SharedOptionsOptionsMap analysisOptionsMap;
|
||||
// TODO(pq): his will replace the single [_analysisOptions] instance.
|
||||
// ignore: unused_field
|
||||
final AnalysisOptionsMap? _analysisOptionsMap;
|
||||
|
||||
/// Create a new instance of [AnalysisDriver].
|
||||
///
|
||||
|
@ -280,11 +283,13 @@ class AnalysisDriver {
|
|||
required ResourceProvider resourceProvider,
|
||||
required ByteStore byteStore,
|
||||
required SourceFactory sourceFactory,
|
||||
required AnalysisOptionsImpl analysisOptions,
|
||||
required Packages packages,
|
||||
required this.analysisOptionsMap,
|
||||
this.macroSupport,
|
||||
this.ownedFiles,
|
||||
this.analysisContext,
|
||||
// TODO(pq): to replace analysis options instance
|
||||
AnalysisOptionsMap? analysisOptionsMap,
|
||||
FileContentCache? fileContentCache,
|
||||
UnlinkedUnitStore? unlinkedUnitStore,
|
||||
InfoDeclarationStore? infoDeclarationStore,
|
||||
|
@ -301,6 +306,8 @@ class AnalysisDriver {
|
|||
_unlinkedUnitStore = unlinkedUnitStore ?? UnlinkedUnitStoreImpl(),
|
||||
_infoDeclarationStore =
|
||||
infoDeclarationStore ?? NoOpInfoDeclarationStore(),
|
||||
_analysisOptions = analysisOptions,
|
||||
_analysisOptionsMap = analysisOptionsMap,
|
||||
_logger = logger,
|
||||
_packages = packages,
|
||||
_sourceFactory = sourceFactory,
|
||||
|
@ -323,7 +330,7 @@ class AnalysisDriver {
|
|||
|
||||
/// Return the analysis options used to control analysis.
|
||||
@Deprecated("Use 'getAnalysisOptionsForFile(file)' instead")
|
||||
AnalysisOptions get analysisOptions => analysisOptionsMap.sharedOptions;
|
||||
AnalysisOptions get analysisOptions => _analysisOptions;
|
||||
|
||||
/// Return the current analysis session.
|
||||
AnalysisSessionImpl get currentSession {
|
||||
|
@ -333,8 +340,8 @@ class AnalysisDriver {
|
|||
/// Return a list of the names of all the plugins enabled in analysis options
|
||||
/// in this driver.
|
||||
List<String> get enabledPluginNames =>
|
||||
// TODO(pq): get this value from a union of all the plugins enabled in the `analysisOptionsMap`
|
||||
analysisOptionsMap.sharedOptions.enabledPluginNames;
|
||||
// TODO(pq): get this value from a union of all the plugins enabled in the `_analysisOptionsMap`
|
||||
_analysisOptions.enabledPluginNames;
|
||||
|
||||
/// Return the stream that produces [ExceptionResult]s.
|
||||
Stream<ExceptionResult> get exceptions => _exceptionController.stream;
|
||||
|
@ -365,7 +372,7 @@ class AnalysisDriver {
|
|||
logger: _logger,
|
||||
byteStore: _byteStore,
|
||||
infoDeclarationStore: _infoDeclarationStore,
|
||||
analysisOptions: analysisOptionsMap.sharedOptions,
|
||||
analysisOptions: _analysisOptions,
|
||||
declaredVariables: declaredVariables,
|
||||
sourceFactory: _sourceFactory,
|
||||
macroSupport: macroSupport,
|
||||
|
@ -683,7 +690,8 @@ class AnalysisDriver {
|
|||
}
|
||||
|
||||
AnalysisOptions getAnalysisOptionsForFile(File file) =>
|
||||
analysisOptionsMap.getOptions(file);
|
||||
// TODO(pq): replace w/ _analysisOptionsMap?.getOptions(file)
|
||||
_analysisOptions;
|
||||
|
||||
/// Return the cached [ResolvedUnitResult] for the Dart file with the given
|
||||
/// [path]. If there is no cached result, return `null`. Usually only results
|
||||
|
@ -1581,14 +1589,14 @@ class AnalysisDriver {
|
|||
void _createFileTracker() {
|
||||
_fillSalt();
|
||||
|
||||
var sharedOptions = analysisOptionsMap.sharedOptions;
|
||||
featureSetProvider = FeatureSetProvider.build(
|
||||
sourceFactory: sourceFactory,
|
||||
resourceProvider: _resourceProvider,
|
||||
packages: _packages,
|
||||
packageDefaultFeatureSet: sharedOptions.contextFeatures,
|
||||
nonPackageDefaultLanguageVersion: sharedOptions.nonPackageLanguageVersion,
|
||||
nonPackageDefaultFeatureSet: sharedOptions.nonPackageFeatureSet,
|
||||
packageDefaultFeatureSet: _analysisOptions.contextFeatures,
|
||||
nonPackageDefaultLanguageVersion:
|
||||
_analysisOptions.nonPackageLanguageVersion,
|
||||
nonPackageDefaultFeatureSet: _analysisOptions.nonPackageFeatureSet,
|
||||
);
|
||||
|
||||
_fsState = FileSystemState(
|
||||
|
@ -1680,7 +1688,7 @@ class AnalysisDriver {
|
|||
void _fillSaltForElements() {
|
||||
var buffer = ApiSignature();
|
||||
buffer.addInt(DATA_VERSION);
|
||||
buffer.addUint32List(analysisOptionsMap.sharedOptions.signatureForElements);
|
||||
buffer.addUint32List(_analysisOptions.signatureForElements);
|
||||
_addDeclaredVariablesToSignature(buffer);
|
||||
_saltForElements = buffer.toUint32List();
|
||||
}
|
||||
|
@ -1690,7 +1698,7 @@ class AnalysisDriver {
|
|||
buffer.addInt(DATA_VERSION);
|
||||
buffer.addBool(enableIndex);
|
||||
buffer.addBool(enableDebugResolutionMarkers);
|
||||
buffer.addUint32List(analysisOptionsMap.sharedOptions.signature);
|
||||
buffer.addUint32List(_analysisOptions.signature);
|
||||
_addDeclaredVariablesToSignature(buffer);
|
||||
|
||||
var workspace = analysisContext?.contextRoot.workspace;
|
||||
|
@ -1703,7 +1711,7 @@ class AnalysisDriver {
|
|||
var buffer = ApiSignature();
|
||||
buffer.addInt(DATA_VERSION);
|
||||
buffer.addBool(enableIndex);
|
||||
buffer.addUint32List(analysisOptionsMap.sharedOptions.unlinkedSignature);
|
||||
buffer.addUint32List(_analysisOptions.unlinkedSignature);
|
||||
_saltForUnlinked = buffer.toUint32List();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
// 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_options.dart';
|
||||
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(AnalysisContextCollection2Test);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class AnalysisContextCollection2Test 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),
|
||||
);
|
||||
|
||||
var optionsFile = 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.getAnalysisOptionsForFile(optionsFile);
|
||||
|
||||
expect(
|
||||
analysisOptions.lintRules.map((e) => e.name),
|
||||
unorderedEquals(['empty_statements', 'unnecessary_parenthesis']),
|
||||
);
|
||||
}
|
||||
|
||||
test_new_analysisOptions_lintRules() {
|
||||
var rootFolder = newFolder('/home/test');
|
||||
var optionsFile = 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.getAnalysisOptionsForFile(optionsFile);
|
||||
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
@FailingTest(reason: 'Pending analysis options map implementation')
|
||||
test_new_outer_inner() {
|
||||
// OUTER
|
||||
var outerFolder = newFolder('/test/outer');
|
||||
newAnalysisOptionsYamlFile('/test/outer', r'''
|
||||
linter:
|
||||
rules:
|
||||
- always_specify_types
|
||||
''');
|
||||
var outerFile = newFile('/test/outer/lib/outer.dart', '');
|
||||
|
||||
// INNER
|
||||
newFolder('/test/outer/inner');
|
||||
newAnalysisOptionsYamlFile('/test/outer/inner', r'''
|
||||
linter:
|
||||
rules:
|
||||
- camel_case_types
|
||||
''');
|
||||
var innerFile = newFile('/test/outer/inner/inner.dart', '');
|
||||
|
||||
var collection = _newCollection(includedPaths: [outerFolder.path]);
|
||||
expect(collection.contexts, hasLength(1));
|
||||
var context = collection.contexts.first;
|
||||
|
||||
// Files with different analysis options, share a single context.
|
||||
expect(collection.contextFor(convertPath('/test/outer/lib/outer.dart')),
|
||||
same(context));
|
||||
expect(collection.contextFor(convertPath('/test/outer/inner/inner.dart')),
|
||||
same(context));
|
||||
|
||||
// But have their own analysis options.
|
||||
var outerOptions = context.getAnalysisOptionsForFile(outerFile);
|
||||
expectContainsExactly(
|
||||
outerOptions,
|
||||
lints: ['always_specify_types'],
|
||||
);
|
||||
|
||||
var innerOptions = context.getAnalysisOptionsForFile(innerFile);
|
||||
expectContainsExactly(
|
||||
innerOptions,
|
||||
lints: ['camel_case_types'],
|
||||
);
|
||||
|
||||
// Files do not have to exist, during creation, or at all.
|
||||
expect(collection.contextFor(convertPath('/test/outer/lib/outer2.dart')),
|
||||
same(context));
|
||||
expect(collection.contextFor(convertPath('/test/outer/inner/inner2.dart')),
|
||||
same(context));
|
||||
}
|
||||
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
static void expectContainsExactly(AnalysisOptions? options,
|
||||
{List<String>? lints}) {
|
||||
expect(options, isNotNull);
|
||||
if (lints != null) {
|
||||
var rules = options!.lintRules.map((e) => e.name);
|
||||
expect(rules, unorderedEquals(lints));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,6 @@ import 'package:analyzer/dart/analysis/results.dart';
|
|||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/source/source.dart';
|
||||
import 'package:analyzer/src/context/packages.dart';
|
||||
import 'package:analyzer/src/dart/analysis/analysis_options_map.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
|
||||
|
@ -78,8 +77,7 @@ class BaseAnalysisDriverTest with ResourceProviderMixin {
|
|||
PackageMapUriResolver(resourceProvider, packageMap),
|
||||
ResourceUriResolver(resourceProvider)
|
||||
]),
|
||||
analysisOptionsMap:
|
||||
AnalysisOptionsMap.forSharedOptions(createAnalysisOptions()),
|
||||
analysisOptions: createAnalysisOptions(),
|
||||
packages: Packages({
|
||||
'test': Package(
|
||||
name: 'test',
|
||||
|
|
226
pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
Normal file
226
pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
Normal file
|
@ -0,0 +1,226 @@
|
|||
// 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_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_builder2.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_locator2.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(ContextBuilderImplTest2);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ContextBuilderImplTest2 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');
|
||||
var optionsFile = newAnalysisOptionsYamlFile(projectPath, ';');
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
var analysisOptions =
|
||||
analysisContext.getAnalysisOptionsImplForFile(optionsFile);
|
||||
_expectEqualOptions(analysisOptions, AnalysisOptionsImpl());
|
||||
}
|
||||
|
||||
void test_analysisOptions_languageOptions() {
|
||||
var projectPath = convertPath('/home/test');
|
||||
var optionsFile = newAnalysisOptionsYamlFile(
|
||||
projectPath,
|
||||
AnalysisOptionsFileConfig(
|
||||
strictRawTypes: true,
|
||||
).toContent(),
|
||||
);
|
||||
|
||||
var analysisContext = _createSingleAnalysisContext(projectPath);
|
||||
var analysisOptions =
|
||||
analysisContext.getAnalysisOptionsImplForFile(optionsFile);
|
||||
_expectEqualOptions(
|
||||
analysisOptions,
|
||||
AnalysisOptionsImpl()..strictRawTypes = true,
|
||||
);
|
||||
}
|
||||
|
||||
test_createContext_declaredVariables() {
|
||||
DeclaredVariables declaredVariables =
|
||||
DeclaredVariables.fromMap({'foo': 'true'});
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
declaredVariables: declaredVariables,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
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.allAnalysisOptions, hasLength(1));
|
||||
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() {
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
expect(context.allAnalysisOptions, hasLength(1));
|
||||
expect(context.contextRoot, contextRoot);
|
||||
}
|
||||
|
||||
test_createContext_sdkPath() {
|
||||
var context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
sdkPath: sdkRoot.path,
|
||||
);
|
||||
expect(context.allAnalysisOptions, hasLength(1));
|
||||
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.allAnalysisOptions, hasLength(1));
|
||||
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 = ContextLocatorImpl2(
|
||||
resourceProvider: resourceProvider,
|
||||
).locateRoots(includedPaths: [path]);
|
||||
|
||||
return ContextBuilderImpl2(
|
||||
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 {
|
||||
List<UriResolver> get uriResolvers {
|
||||
return (driver.sourceFactory as SourceFactoryImpl).resolvers;
|
||||
}
|
||||
|
||||
AnalysisOptionsImpl getAnalysisOptionsImplForFile(File file) =>
|
||||
getAnalysisOptionsForFile(file) as AnalysisOptionsImpl;
|
||||
}
|
|
@ -12,7 +12,6 @@ import 'package:analyzer/error/error.dart';
|
|||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/source/source.dart';
|
||||
import 'package:analyzer/src/context/packages.dart';
|
||||
import 'package:analyzer/src/dart/analysis/analysis_options_map.dart';
|
||||
import 'package:analyzer/src/dart/analysis/byte_store.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
|
||||
|
@ -714,8 +713,7 @@ class AnalysisDriverSchedulerTest with ResourceProviderMixin {
|
|||
sourceFactory: SourceFactory(
|
||||
[DartUriResolver(sdk), ResourceUriResolver(resourceProvider)],
|
||||
),
|
||||
analysisOptionsMap:
|
||||
AnalysisOptionsMap.forSharedOptions(AnalysisOptionsImpl()),
|
||||
analysisOptions: AnalysisOptionsImpl(),
|
||||
packages: Packages.empty,
|
||||
);
|
||||
driver.results.listen((result) {
|
||||
|
|
|
@ -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