add option map awareness to `FeatureSetProvider`
Change-Id: I639825e54f0469d6fc475f7ab25386da7435fea6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345565
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 174cb3e..46d83ee 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -1568,14 +1568,10 @@
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,
);
_fsState = FileSystemState(
@@ -1589,6 +1585,7 @@
_saltForUnlinked,
_saltForElements,
featureSetProvider,
+ analysisOptionsMap,
fileContentStrategy: _fileContentStrategy,
unlinkedUnitStore: _unlinkedUnitStore,
prefetchFiles: null,
diff --git a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
index 0dd1f4a..ff030a8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -16,9 +16,7 @@
final AllowedExperiments _allowedExperiments;
final ResourceProvider _resourceProvider;
final Packages _packages;
- final FeatureSet _packageDefaultFeatureSet;
- final Version _nonPackageDefaultLanguageVersion;
- final FeatureSet _nonPackageDefaultFeatureSet;
+
final Map<String, FeatureSet> _cachedFeatureSets = {};
FeatureSetProvider._({
@@ -26,16 +24,10 @@
required AllowedExperiments allowedExperiments,
required ResourceProvider resourceProvider,
required Packages packages,
- required FeatureSet packageDefaultFeatureSet,
- required Version nonPackageDefaultLanguageVersion,
- required FeatureSet nonPackageDefaultFeatureSet,
}) : _sdkLanguageVersion = sdkLanguageVersion,
_allowedExperiments = allowedExperiments,
_resourceProvider = resourceProvider,
- _packages = packages,
- _packageDefaultFeatureSet = packageDefaultFeatureSet,
- _nonPackageDefaultLanguageVersion = nonPackageDefaultLanguageVersion,
- _nonPackageDefaultFeatureSet = nonPackageDefaultFeatureSet;
+ _packages = packages;
FeatureSet featureSetForExperiments(List<String> experiments) {
String key = experiments.join("|");
@@ -52,7 +44,12 @@
/// [FeatureSet] of this version. The reason is that we allow libraries to
/// "upgrade" to higher version than the default package language version,
/// and want this to preserve experimental features.
- FeatureSet getFeatureSet(String path, Uri uri) {
+ FeatureSet getFeatureSet(
+ String path,
+ Uri uri, {
+ required FeatureSet contextFeatures,
+ required FeatureSet nonPackageFeatureSet,
+ }) {
if (uri.isScheme('dart')) {
var pathSegments = uri.pathSegments;
if (pathSegments.isNotEmpty) {
@@ -70,18 +67,21 @@
if (experiments != null) {
return featureSetForExperiments(experiments);
}
-
- return _packageDefaultFeatureSet;
+ return contextFeatures;
}
- return _nonPackageDefaultFeatureSet;
+ return nonPackageFeatureSet;
}
/// Return the language version for the package that contains the file.
///
/// Each individual file might use `// @dart` to override this version, to
/// be either lower, or higher than the package language version.
- Version getLanguageVersion(String path, Uri uri) {
+ Version getLanguageVersion(
+ String path,
+ Uri uri, {
+ required Version nonPackageLanguageVersion,
+ }) {
if (uri.isScheme('dart')) {
return _sdkLanguageVersion;
}
@@ -94,7 +94,7 @@
return _sdkLanguageVersion;
}
- return _nonPackageDefaultLanguageVersion;
+ return nonPackageLanguageVersion;
}
/// Return the package corresponding to the [uri] or [path], `null` if none.
@@ -131,9 +131,6 @@
required SourceFactory sourceFactory,
required ResourceProvider resourceProvider,
required Packages packages,
- required FeatureSet packageDefaultFeatureSet,
- required Version nonPackageDefaultLanguageVersion,
- required FeatureSet nonPackageDefaultFeatureSet,
}) {
var sdk = sourceFactory.dartSdk!;
var allowedExperiments = _experimentsForSdk(sdk);
@@ -142,9 +139,6 @@
allowedExperiments: allowedExperiments,
resourceProvider: resourceProvider,
packages: packages,
- packageDefaultFeatureSet: packageDefaultFeatureSet,
- nonPackageDefaultLanguageVersion: nonPackageDefaultLanguageVersion,
- nonPackageDefaultFeatureSet: nonPackageDefaultFeatureSet,
);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 2e33335..4136612 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.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/defined_names.dart';
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
@@ -28,6 +29,7 @@
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/exception/exception.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart' show SourceFactory;
import 'package:analyzer/src/source/source_resource.dart';
@@ -1118,6 +1120,11 @@
/// Information about known file system state.
class FileSystemState {
+ /// In case there is no options file mapped to a file in the [_analysisOptionsMap],
+ /// we default to a shared (empty) analysis options object.
+ static final AnalysisOptionsImpl _defaultAnalysisOptions =
+ AnalysisOptionsImpl();
+
final PerformanceLog _logger;
final ResourceProvider resourceProvider;
final String contextName;
@@ -1176,6 +1183,9 @@
/// macro [FileState]. During the refresh, this will is reset back to `null`.
FileContent? _macroFileContent;
+ /// Used for looking up options to associate with created file states.
+ final AnalysisOptionsMap _analysisOptionsMap;
+
FileSystemState(
this._logger,
this._byteStore,
@@ -1186,14 +1196,15 @@
this._declaredVariables,
this._saltForUnlinked,
this._saltForElements,
- this.featureSetProvider, {
+ this.featureSetProvider,
+ AnalysisOptionsMap analysisOptionsMap, {
required this.fileContentStrategy,
required this.unlinkedUnitStore,
required this.prefetchFiles,
required this.isGenerated,
required this.onNewFile,
required this.testData,
- }) {
+ }) : _analysisOptionsMap = analysisOptionsMap {
_testView = FileSystemStateTestView(this);
}
@@ -1450,10 +1461,19 @@
unlinkedUnitStore.clear();
}
+ AnalysisOptionsImpl _getAnalysisOptions(File file) {
+ var mappedOptions = _analysisOptionsMap.getOptions(file);
+ // TODO(pq): consider making the options map manage default options
+ return (mappedOptions is AnalysisOptionsImpl)
+ ? mappedOptions
+ : _defaultAnalysisOptions;
+ }
+
FeatureSet _getFeatureSet(
String path,
Uri uri,
WorkspacePackage? workspacePackage,
+ AnalysisOptionsImpl analysisOptions,
) {
var workspacePackageExperiments = workspacePackage?.enabledExperiments;
if (workspacePackageExperiments != null) {
@@ -1462,28 +1482,34 @@
);
}
- return featureSetProvider.getFeatureSet(path, uri);
+ return featureSetProvider.getFeatureSet(path, uri,
+ contextFeatures: analysisOptions.contextFeatures,
+ nonPackageFeatureSet: analysisOptions.nonPackageFeatureSet);
}
Version _getLanguageVersion(
String path,
Uri uri,
WorkspacePackage? workspacePackage,
+ AnalysisOptionsImpl analysisOptions,
) {
var workspaceLanguageVersion = workspacePackage?.languageVersion;
if (workspaceLanguageVersion != null) {
return workspaceLanguageVersion;
}
- return featureSetProvider.getLanguageVersion(path, uri);
+ return featureSetProvider.getLanguageVersion(path, uri,
+ nonPackageLanguageVersion: analysisOptions.nonPackageLanguageVersion);
}
FileState _newFile(File resource, String path, Uri uri) {
FileSource uriSource = FileSource(resource, uri);
WorkspacePackage? workspacePackage = _workspace?.findPackageFor(path);
- FeatureSet featureSet = _getFeatureSet(path, uri, workspacePackage);
+ AnalysisOptionsImpl analysisOptions = _getAnalysisOptions(resource);
+ FeatureSet featureSet =
+ _getFeatureSet(path, uri, workspacePackage, analysisOptions);
Version packageLanguageVersion =
- _getLanguageVersion(path, uri, workspacePackage);
+ _getLanguageVersion(path, uri, workspacePackage, analysisOptions);
var file = FileState._(this, path, uri, uriSource, workspacePackage,
featureSet, packageLanguageVersion);
_pathToFile[path] = file;
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 1f74c92..f7a7a3d 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -5,6 +5,7 @@
import 'dart:typed_data';
import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
@@ -13,11 +14,11 @@
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/analysis_options/apply_options.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/cache.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' show ErrorEncoding;
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
@@ -725,16 +726,15 @@
}
var analysisOptions = AnalysisOptionsImpl()
- ..strictInference = fileAnalysisOptions.strictInference;
+ ..strictInference = fileAnalysisOptions.strictInference
+ ..contextFeatures = FeatureSet.latestLanguageVersion()
+ ..nonPackageFeatureSet = FeatureSet.latestLanguageVersion();
if (fsState == null) {
var featureSetProvider = FeatureSetProvider.build(
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: Packages.empty,
- packageDefaultFeatureSet: analysisOptions.contextFeatures,
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: analysisOptions.nonPackageFeatureSet,
);
fsState = FileSystemState(
@@ -748,6 +748,7 @@
Uint32List(0), // _saltForUnlinked
Uint32List(0), // _saltForElements
featureSetProvider,
+ AnalysisOptionsMap.forSharedOptions(analysisOptions),
fileContentStrategy: CiderFileContentStrategy(
resourceProvider: resourceProvider,
getFileDigest: getFileDigest,
diff --git a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
index 8eb7d7a..105fd15 100644
--- a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
@@ -29,6 +29,8 @@
late SourceFactory sourceFactory;
late FeatureSetProvider provider;
+ final latestLanguageVersionFeatures = FeatureSet.latestLanguageVersion();
+
Folder get sdkRoot => newFolder('/sdk');
void setUp() {
@@ -98,13 +100,16 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: packages,
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
void assertHasFeature(String path, bool expected) {
- _assertHasFeatureForPath(path, feature_a, expected);
+ _assertHasFeatureForPath(
+ path,
+ feature_a,
+ expected,
+ contextFeatures: ExperimentStatus(),
+ nonPackageFeatureSet: ExperimentStatus(),
+ );
}
assertHasFeature('/packages/aaa/lib/a.dart', true);
@@ -156,16 +161,19 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: packages,
- packageDefaultFeatureSet: FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.12.0'),
- flags: [feature_a.enableString],
- ),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
void assertHasFeature(String path, bool expected) {
- _assertHasFeatureForPath(path, feature_a, expected);
+ _assertHasFeatureForPath(
+ path,
+ feature_a,
+ expected,
+ contextFeatures: FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: Version.parse('2.12.0'),
+ flags: [feature_a.enableString],
+ ),
+ nonPackageFeatureSet: latestLanguageVersionFeatures,
+ );
}
assertHasFeature('/packages/aaa/a.dart', true);
@@ -215,13 +223,16 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: packages,
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
void assertHasFeature(String path, bool expected) {
- _assertHasFeatureForPath(path, feature_a, expected);
+ _assertHasFeatureForPath(
+ path,
+ feature_a,
+ expected,
+ contextFeatures: ExperimentStatus(),
+ nonPackageFeatureSet: ExperimentStatus(),
+ );
}
assertHasFeature('/packages/aaa/a.dart', false);
@@ -262,9 +273,6 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: packages,
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
void check({
@@ -275,7 +283,8 @@
var uri = Uri.parse(uriStr);
var path = convertPath(posixPath);
expect(
- provider.getLanguageVersion(path, uri),
+ provider.getLanguageVersion(path, uri,
+ nonPackageLanguageVersion: ExperimentStatus.currentVersion),
expected,
);
}
@@ -341,15 +350,20 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: findPackagesFrom(resourceProvider, getFolder('/test')),
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
- var core_featureSet = _getSdkFeatureSet('dart:core');
+ var core_featureSet = _getSdkFeatureSet(
+ 'dart:core',
+ contextFeatures: latestLanguageVersionFeatures,
+ nonPackageFeatureSet: latestLanguageVersionFeatures,
+ );
expect(core_featureSet.isEnabled(feature_a), isTrue);
- var math_featureSet = _getSdkFeatureSet('dart:math');
+ var math_featureSet = _getSdkFeatureSet(
+ 'dart:math',
+ contextFeatures: latestLanguageVersionFeatures,
+ nonPackageFeatureSet: latestLanguageVersionFeatures,
+ );
expect(math_featureSet.isEnabled(feature_a), isTrue);
});
}
@@ -390,15 +404,20 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: findPackagesFrom(resourceProvider, getFolder('/test')),
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
- var core_featureSet = _getSdkFeatureSet('dart:core');
+ var core_featureSet = _getSdkFeatureSet(
+ 'dart:core',
+ contextFeatures: latestLanguageVersionFeatures,
+ nonPackageFeatureSet: latestLanguageVersionFeatures,
+ );
expect(core_featureSet.isEnabled(feature_a), isFalse);
- var math_featureSet = _getSdkFeatureSet('dart:math');
+ var math_featureSet = _getSdkFeatureSet(
+ 'dart:math',
+ contextFeatures: latestLanguageVersionFeatures,
+ nonPackageFeatureSet: latestLanguageVersionFeatures,
+ );
expect(math_featureSet.isEnabled(feature_a), isTrue);
});
}
@@ -408,17 +427,28 @@
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: findPackagesFrom(resourceProvider, getFolder('/test')),
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
- var featureSet = _getSdkFeatureSet('dart:math');
+ var featureSet = _getSdkFeatureSet(
+ 'dart:math',
+ contextFeatures: latestLanguageVersionFeatures,
+ nonPackageFeatureSet: latestLanguageVersionFeatures,
+ );
expect(featureSet.isEnabled(Feature.non_nullable), isTrue);
}
- _assertHasFeatureForPath(String path, Feature feature, bool expected) {
- var featureSet = _getPathFeatureSet(path);
+ _assertHasFeatureForPath(
+ String path,
+ Feature feature,
+ bool expected, {
+ required FeatureSet contextFeatures,
+ required FeatureSet nonPackageFeatureSet,
+ }) {
+ var featureSet = _getPathFeatureSet(
+ path,
+ contextFeatures: contextFeatures,
+ nonPackageFeatureSet: nonPackageFeatureSet,
+ );
expect(featureSet.isEnabled(feature), expected);
}
@@ -444,16 +474,31 @@
sourceFactory = SourceFactoryImpl(resolvers);
}
- FeatureSet _getPathFeatureSet(String path) {
+ FeatureSet _getPathFeatureSet(
+ String path, {
+ required FeatureSet contextFeatures,
+ required FeatureSet nonPackageFeatureSet,
+ }) {
path = convertPath(path);
var uri = sourceFactory.pathToUri(path)!;
- return provider.getFeatureSet(path, uri);
+ return provider.getFeatureSet(
+ path,
+ uri,
+ contextFeatures: contextFeatures,
+ nonPackageFeatureSet: nonPackageFeatureSet,
+ );
}
- FeatureSet _getSdkFeatureSet(String uriStr) {
+ FeatureSet _getSdkFeatureSet(
+ String uriStr, {
+ required FeatureSet contextFeatures,
+ required FeatureSet nonPackageFeatureSet,
+ }) {
var uri = Uri.parse(uriStr);
var path = sourceFactory.forUri2(uri)!.fullName;
- return provider.getFeatureSet(path, uri);
+ return provider.getFeatureSet(path, uri,
+ contextFeatures: contextFeatures,
+ nonPackageFeatureSet: nonPackageFeatureSet);
}
void _newSdkExperimentsFile(String content) {
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 013e935..9c338cb 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -9,14 +9,15 @@
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/experiments.dart';
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
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';
import 'package:analyzer/src/generated/source.dart'
show DartUriResolver, SourceFactory, UriResolver;
import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -5789,13 +5790,13 @@
ResourceUriResolver(resourceProvider)
]);
+ var analysisOptions = AnalysisOptionsImpl()
+ ..contextFeatures = FeatureSet.latestLanguageVersion()
+ ..nonPackageFeatureSet = FeatureSet.latestLanguageVersion();
var featureSetProvider = FeatureSetProvider.build(
sourceFactory: sourceFactory,
resourceProvider: resourceProvider,
packages: Packages.empty,
- packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
- nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
- nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
);
fileSystemState = FileSystemState(
logger,
@@ -5808,6 +5809,7 @@
Uint32List(0),
Uint32List(0),
featureSetProvider,
+ AnalysisOptionsMap.forSharedOptions(analysisOptions),
fileContentStrategy: StoredFileContentStrategy(
FileContentCache.ephemeral(resourceProvider),
),