associate analysis options with `FileState` instances
Preliminary to https://github.com/dart-lang/sdk/issues/54124.
Next step will be to update all lookups to use this new getter.
Change-Id: Ib4a0234ffc8badf906eee4fbd8c363ef4a25adac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345745
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index 7995df1..e6e52fc 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -204,8 +204,9 @@
map.add(contextRoot.root, options);
} else {
for (var entry in optionsMappings) {
- var options = AnalysisOptionsImpl();
- var optionsYaml = provider.getOptionsFromFile(entry.value);
+ var file = entry.value;
+ var options = AnalysisOptionsImpl(file: file);
+ var optionsYaml = provider.getOptionsFromFile(file);
options.applyOptions(optionsYaml);
updateOptions(options);
map.add(entry.key, options);
@@ -294,9 +295,9 @@
ContextRoot contextRoot,
SourceFactory sourceFactory,
) {
- var options = AnalysisOptionsImpl();
-
var optionsFile = contextRoot.optionsFile;
+ var options = AnalysisOptionsImpl(file: optionsFile);
+
if (optionsFile != null) {
try {
var provider = AnalysisOptionsProvider(sourceFactory);
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 838bb2b..47f7e66 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -375,6 +375,9 @@
class FileState {
final FileSystemState _fsState;
+ /// The [AnalysisOptions] associated with this file.
+ final AnalysisOptionsImpl? analysisOptions;
+
/// The absolute path of the file.
final String path;
@@ -438,6 +441,7 @@
this.workspacePackage,
this._featureSet,
this.packageLanguageVersion,
+ this.analysisOptions,
) : uriProperties = FileUriProperties(uri);
/// The unlinked API signature of the file.
@@ -1497,7 +1501,7 @@
Version packageLanguageVersion =
_getLanguageVersion(path, uri, workspacePackage, analysisOptions);
var file = FileState._(this, path, uri, uriSource, workspacePackage,
- featureSet, packageLanguageVersion);
+ featureSet, packageLanguageVersion, analysisOptions);
_pathToFile[path] = file;
_uriToFile[uri] = file;
knownFilePaths.add(path);
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 89643c1..79cfb36 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -205,6 +205,9 @@
/// A list of exclude patterns used to exclude some sources from analysis.
List<String>? _excludePatterns;
+ /// The associated `analysis_options.yaml` file (or `null` if there is none).
+ File? file;
+
@override
bool lint = false;
@@ -246,7 +249,7 @@
/// Initialize a newly created set of analysis options to have their default
/// values.
- AnalysisOptionsImpl() {
+ AnalysisOptionsImpl({this.file}) {
codeStyleOptions = CodeStyleOptionsImpl(this, useFormatter: false);
}
@@ -262,6 +265,7 @@
warning = options.warning;
lintRules = options.lintRules;
if (options is AnalysisOptionsImpl) {
+ file = options.file;
enableTiming = options.enableTiming;
propagateLinterExceptions = options.propagateLinterExceptions;
strictInference = options.strictInference;
diff --git a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
index f32ba62..11cc270 100644
--- a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/generated/engine.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;
@@ -275,21 +276,24 @@
_assertWorkspaceCollectionText(workspaceRootPath, r'''
contexts
/home/test
- optionsFile: /home/test/analysis_options.yaml
packagesFile: /home/test/.dart_tool/package_config.json
workspace: workspace_0
analyzedFiles
/home/test/lib/a.dart
uri: package:test/a.dart
+ analysisOptions_0
workspacePackage_0_0
/home/test/lib/nested
- optionsFile: /home/test/lib/nested/analysis_options.yaml
packagesFile: /home/test/.dart_tool/package_config.json
workspace: workspace_1
analyzedFiles
/home/test/lib/nested/b.dart
uri: package:test/nested/b.dart
+ analysisOptions_1
workspacePackage_1_0
+analysisOptions
+ analysisOptions_0: /home/test/analysis_options.yaml
+ analysisOptions_1: /home/test/lib/nested/analysis_options.yaml
workspaces
workspace_0: PubWorkspace
root: /home/test
@@ -416,13 +420,15 @@
_assertWorkspaceCollectionText(workspaceRootPath, r'''
contexts
/home/test
- optionsFile: /home/test/analysis_options.yaml
packagesFile: /home/test/.dart_tool/package_config.json
workspace: workspace_0
analyzedFiles
/home/test/lib/a.dart
uri: package:test/a.dart
+ analysisOptions_0
workspacePackage_0_0
+analysisOptions
+ analysisOptions_0: /home/test/analysis_options.yaml
workspaces
workspace_0: PubWorkspace
root: /home/test
@@ -432,6 +438,70 @@
''');
}
+ test_pubWorkspace_singleAnalysisOptions_multipleContexts() async {
+ final workspaceRootPath = '/home';
+ final testPackageRootPath = '$workspaceRootPath/test';
+ final testPackageLibPath = '$testPackageRootPath/lib';
+
+ newAnalysisOptionsYamlFile(testPackageRootPath, '');
+
+ newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+''');
+
+ newSinglePackageConfigJsonFile(
+ packagePath: testPackageRootPath,
+ name: 'test',
+ );
+
+ newFile('$testPackageLibPath/a.dart', '');
+
+ final nestedPackageRootPath = '$testPackageRootPath/nested';
+ newPubspecYamlFile(nestedPackageRootPath, r'''
+name: nested
+''');
+ newSinglePackageConfigJsonFile(
+ packagePath: nestedPackageRootPath,
+ name: 'nested',
+ );
+ newFile('$nestedPackageRootPath/lib/b.dart', '');
+
+ // TODO(pq): there should only be one shared options instance
+ _assertWorkspaceCollectionText(workspaceRootPath, r'''
+contexts
+ /home/test
+ packagesFile: /home/test/.dart_tool/package_config.json
+ workspace: workspace_0
+ analyzedFiles
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ analysisOptions_0
+ workspacePackage_0_0
+ /home/test/nested
+ packagesFile: /home/test/nested/.dart_tool/package_config.json
+ workspace: workspace_1
+ analyzedFiles
+ /home/test/nested/lib/b.dart
+ uri: package:nested/b.dart
+ analysisOptions_1
+ workspacePackage_1_0
+analysisOptions
+ analysisOptions_0: /home/test/analysis_options.yaml
+ analysisOptions_1: /home/test/analysis_options.yaml
+workspaces
+ workspace_0: PubWorkspace
+ root: /home/test
+ pubPackages
+ workspacePackage_0_0: PubWorkspacePackage
+ root: /home/test
+ workspace_1: PubWorkspace
+ root: /home/test/nested
+ pubPackages
+ workspacePackage_1_0: PubWorkspacePackage
+ root: /home/test/nested
+''');
+ }
+
void _assertCollectionText(
AnalysisContextCollectionImpl collection,
String expected,
@@ -480,6 +550,7 @@
final ResourceProvider resourceProvider;
final TreeStringSink sink;
+ final Map<AnalysisOptionsImpl, String> _analysisOptionsFiles = Map.identity();
final Map<Workspace, (int, String)> _workspaces = Map.identity();
final Map<Workspace, Map<WorkspacePackage, String>> _workspacePackages =
Map.identity();
@@ -498,12 +569,25 @@
);
sink.writeElements(
+ 'analysisOptions',
+ contextCollection.contexts
+ .expand((c) => c.allAnalysisOptions
+ .where((o) => o is AnalysisOptionsImpl && o.file != null))
+ .toList(),
+ _writeAnalysisOptions,
+ );
+
+ sink.writeElements(
'workspaces',
_workspaces.keys.toList(),
_writeWorkspace,
);
}
+ String _idOfAnalysisOptions(AnalysisOptionsImpl analysisOptions) {
+ return _indexIdOfAnalysisOptions(analysisOptions);
+ }
+
String _idOfWorkspace(Workspace workspace) {
return _indexIdOfWorkspace(workspace).$2;
}
@@ -520,6 +604,17 @@
}
}
+ String _indexIdOfAnalysisOptions(AnalysisOptionsImpl analysisOptions) {
+ if (_analysisOptionsFiles[analysisOptions] case final existing?) {
+ return existing;
+ }
+
+ final index = _analysisOptionsFiles.length;
+ final id = 'analysisOptions_$index';
+ _analysisOptionsFiles[analysisOptions] = id;
+ return id;
+ }
+
(int, String) _indexIdOfWorkspace(Workspace workspace) {
if (_workspaces[workspace] case final existing?) {
return existing;
@@ -545,7 +640,6 @@
sink.writelnWithIndent(contextRoot.root.posixPath);
sink.withIndent(() {
- _writeNamedFile('optionsFile', contextRoot.optionsFile);
_writeNamedFile('packagesFile', contextRoot.packagesFile);
sink.writelnWithIndent(
'workspace: ${_idOfWorkspace(contextRoot.workspace)}',
@@ -559,12 +653,25 @@
});
}
+ void _writeAnalysisOptions(AnalysisOptions analysisOptions) {
+ final file = (analysisOptions as AnalysisOptionsImpl).file!;
+ _writeNamedFile(_idOfAnalysisOptions(analysisOptions), file);
+ }
+
void _writeDartFile(FileSystemState fsState, File file) {
sink.writelnWithIndent(file.posixPath);
sink.withIndent(() {
final fileState = fsState.getFileForPath(file.path);
sink.writelnWithIndent('uri: ${fileState.uri}');
+ final analysisOptions = fileState.analysisOptions;
+ if (analysisOptions != null) {
+ if (analysisOptions.file != null) {
+ final id = _idOfAnalysisOptions(analysisOptions);
+ sink.writelnWithIndent(id);
+ }
+ }
+
final workspacePackage = fileState.workspacePackage;
if (workspacePackage != null) {
final id = _idOfWorkspacePackage(workspacePackage);