Skip to content

Commit 39c1850

Browse files
srawlinsCommit Queue
authored andcommitted
DAS plugins: warn when plugins found in inner options file
Work towards #61481 Change-Id: I16d5333de6b5b195f629ec51ee582d793431f139 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/450220 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 52e2c13 commit 39c1850

File tree

7 files changed

+141
-9
lines changed

7 files changed

+141
-9
lines changed

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ AnalysisOptionsWarningCode.MULTIPLE_PLUGINS:
115115
notes: |-
116116
The fix is to remove the plugin name. Might not be worth the cost if we
117117
can address the question of if/how we're supporting plugins.
118+
AnalysisOptionsWarningCode.PLUGINS_IN_INNER_OPTIONS:
119+
status: needsFix
120+
notes: |-
121+
The fix is to delete the 'plugins' section.
118122
AnalysisOptionsWarningCode.RECURSIVE_INCLUDE_FILE:
119123
status: noFix
120124
notes: |-

pkg/analysis_server_plugin/doc/using_plugins.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
# Using plugins
22

3-
This document describes how to enable an analyzer plugin. An analyzer plugin
4-
can be enabled for a given package, so that the plugin can report diagnostics
5-
(lints and warnings) and offer quick fixes. Plugins are enabled via the
6-
`analysis_options.yaml` file under the top-level `plugins` section:
3+
This document describes how to enable analyzer plugins. Analyzer plugins can
4+
report diagnostics (lints and warnings) in an IDE and also at the command line
5+
(with `dart analyze` or `flutter analyze`). Analyzer plugins can also offer
6+
quick fixes and assists in an IDE. A set of analyzer plugins can be enabled for
7+
a given package or [workspace][] via the `analysis_options.yaml` file, at the
8+
root of the package or workspace source tree. Analyzer plugins cannot be
9+
enabled, disabled, or otherwise specified or configured in a nested analysis
10+
options file
11+
12+
Analyzer plugins are specified in the top-level `plugins` section:
713

814
```yaml
915
plugins:
1016
my_plugin: ^1.0.0
1117
```
1218
19+
[workspace]: https://dart.dev/tools/pub/workspaces
20+
1321
Note: This is similar to how analyzer plugins are enabled in the [legacy][]
1422
analyzer plugin system. However, in the legacy system, this `plugins` section
1523
is listed under the top-level `analyzer` section. In the new analyzer plugin
@@ -72,4 +80,4 @@ use a comment like the following:
7280
// ignore: some_plugin/some_code
7381
7482
// ignore_for_file: some_plugin/some_code
75-
```
83+
```

pkg/analyzer/lib/src/analysis_options/error/option_codes.g.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,24 @@ class AnalysisOptionsWarningCode extends DiagnosticCodeWithExpectedTypes {
375375
expectedTypes: [ExpectedType.string],
376376
);
377377

378+
/// An error code indicating plugins have been specified in an "inner"
379+
/// analysis options file.
380+
///
381+
/// Parameters:
382+
/// String contextRoot: the root of the analysis context
383+
static const AnalysisOptionsWarningTemplate<
384+
LocatableDiagnostic Function({required String contextRoot})
385+
>
386+
pluginsInInnerOptions = AnalysisOptionsWarningTemplate(
387+
'PLUGINS_IN_INNER_OPTIONS',
388+
"Plugins can only be specified in the root of a pub workspace or the root "
389+
"of a package that isn't in a workspace.",
390+
correctionMessage:
391+
"Try specifying plugins in an analysis options file at '{0}'.",
392+
withArguments: _withArgumentsPluginsInInnerOptions,
393+
expectedTypes: [ExpectedType.string],
394+
);
395+
378396
/// An error code indicating a specified include file includes itself recursively.
379397
///
380398
/// Parameters:
@@ -671,6 +689,12 @@ class AnalysisOptionsWarningCode extends DiagnosticCodeWithExpectedTypes {
671689
return LocatableDiagnosticImpl(multiplePlugins, [p0]);
672690
}
673691

692+
static LocatableDiagnostic _withArgumentsPluginsInInnerOptions({
693+
required String contextRoot,
694+
}) {
695+
return LocatableDiagnosticImpl(pluginsInInnerOptions, [contextRoot]);
696+
}
697+
674698
static LocatableDiagnostic _withArgumentsRecursiveIncludeFile({
675699
required Object p0,
676700
required Object p1,

pkg/analyzer/lib/src/analysis_options/options_file_validator.dart

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ List<Diagnostic> analyzeAnalysisOptions(
7777
}
7878

7979
// Validates the specified options and any included option files.
80-
void validate(Source source, YamlMap options) {
80+
void validate(Source source, YamlMap options, {required String contextRoot}) {
8181
var isSourcePrimary = initialIncludeSpan == null;
8282
var validationErrors = OptionsFileValidator(
8383
source,
8484
sdkVersionConstraint: sdkVersionConstraint,
85+
contextRoot: contextRoot,
8586
isPrimarySource: isSourcePrimary,
8687
optionsProvider: optionsProvider,
8788
sourceFactory: sourceFactory,
@@ -168,7 +169,7 @@ List<Diagnostic> analyzeAnalysisOptions(
168169
var includedOptions = optionsProvider.getOptionsFromString(
169170
includedSource.contents.data,
170171
);
171-
validate(includedSource, includedOptions);
172+
validate(includedSource, includedOptions, contextRoot: contextRoot);
172173
firstPluginName ??= _firstPluginName(includedOptions);
173174
// Validate the 'plugins' option in [options], taking into account any
174175
// plugins enabled by [includedOptions].
@@ -222,7 +223,7 @@ List<Diagnostic> analyzeAnalysisOptions(
222223
content,
223224
sourceUrl: source.uri,
224225
);
225-
validate(source, options);
226+
validate(source, options, contextRoot: contextRoot);
226227
} on OptionsFormatException catch (e) {
227228
SourceSpan span = e.span!;
228229
errors.add(
@@ -297,6 +298,7 @@ class OptionsFileValidator {
297298
OptionsFileValidator(
298299
this._source, {
299300
VersionConstraint? sdkVersionConstraint,
301+
required String contextRoot,
300302
required bool isPrimarySource,
301303
required AnalysisOptionsProvider optionsProvider,
302304
required ResourceProvider resourceProvider,
@@ -313,7 +315,12 @@ class OptionsFileValidator {
313315
sdkVersionConstraint: sdkVersionConstraint,
314316
isPrimarySource: isPrimarySource,
315317
),
316-
_PluginsOptionsValidator(),
318+
_PluginsOptionsValidator(
319+
contextRoot: contextRoot,
320+
filePath: _source.fullName,
321+
isPrimarySource: isPrimarySource,
322+
resourceProvider: resourceProvider,
323+
),
317324
];
318325

319326
List<Diagnostic> validate(YamlMap options) {
@@ -945,11 +952,38 @@ class _PluginsOptionsValidator extends OptionsValidator {
945952
AnalysisOptionsFile.pluginsOptions,
946953
);
947954

955+
final String _contextRoot;
956+
957+
final String _filePath;
958+
959+
final bool _isPrimarySource;
960+
961+
final ResourceProvider _resourceProvider;
962+
963+
_PluginsOptionsValidator({
964+
required String contextRoot,
965+
required String filePath,
966+
required bool isPrimarySource,
967+
required ResourceProvider resourceProvider,
968+
}) : _contextRoot = contextRoot,
969+
_filePath = filePath,
970+
_isPrimarySource = isPrimarySource,
971+
_resourceProvider = resourceProvider;
972+
948973
@override
949974
void validate(DiagnosticReporter reporter, YamlMap options) {
950975
var plugins = options.valueAt(AnalysisOptionsFile.plugins);
951976
switch (plugins) {
952977
case YamlMap():
978+
var sourceDir = _resourceProvider.pathContext.dirname(_filePath);
979+
var isAtContextRoot = sourceDir == _contextRoot;
980+
if (!isAtContextRoot && _isPrimarySource) {
981+
reporter.atSourceSpan(
982+
plugins.span,
983+
AnalysisOptionsWarningCode.pluginsInInnerOptions,
984+
arguments: [_contextRoot],
985+
);
986+
}
953987
plugins.nodes.forEach((pluginName, pluginValue) {
954988
if (pluginName is! String) {
955989
return;

pkg/analyzer/lib/src/diagnostic/diagnostic_code_values.g.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const List<DiagnosticCode> diagnosticCodeValues = [
4040
AnalysisOptionsWarningCode.invalidOption,
4141
AnalysisOptionsWarningCode.invalidSectionFormat,
4242
AnalysisOptionsWarningCode.multiplePlugins,
43+
AnalysisOptionsWarningCode.pluginsInInnerOptions,
4344
AnalysisOptionsWarningCode.recursiveIncludeFile,
4445
AnalysisOptionsWarningCode.removedLint,
4546
AnalysisOptionsWarningCode.replacedLint,

pkg/analyzer/messages.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ AnalysisOptionsWarningCode:
201201
hasPublishedDocs: false
202202
comment: |-
203203
An error code indicating multiple plugins have been specified as enabled.
204+
PLUGINS_IN_INNER_OPTIONS:
205+
parameters:
206+
String contextRoot: the root of the analysis context
207+
problemMessage: "Plugins can only be specified in the root of a pub workspace or the root of a package that isn't in a workspace."
208+
correctionMessage: "Try specifying plugins in an analysis options file at '#contextRoot'."
209+
hasPublishedDocs: false
210+
comment: |-
211+
An error code indicating plugins have been specified in an "inner"
212+
analysis options file.
204213
RECURSIVE_INCLUDE_FILE:
205214
parameters:
206215
Object p0: the URI of the file to be included

pkg/analyzer/test/src/options/options_file_validator_test.dart

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class OptionsFileValidatorTest
7878
late final OptionsFileValidator validator = OptionsFileValidator(
7979
TestSource(),
8080
isPrimarySource: true,
81+
contextRoot: '/',
8182
optionsProvider: optionsProvider,
8283
resourceProvider: resourceProvider,
8384
sourceFactory: SourceFactory([ResourceUriResolver(resourceProvider)]),
@@ -839,6 +840,57 @@ analyzer:
839840
);
840841
}
841842

843+
test_pluginsInInnerOptions() {
844+
var code = '''
845+
plugins:
846+
one: ^1.0.0
847+
''';
848+
var filePath = '/inner/analysis_options.yaml';
849+
newFile(filePath, code);
850+
newFile('/pubspec.yaml', '''
851+
name: test
852+
version: 0.0.1
853+
''');
854+
var diagnostics = analyzeAnalysisOptions(
855+
sourceFactory.forUri2(toUri(filePath))!,
856+
code,
857+
sourceFactory,
858+
'/',
859+
null /*sdkVersionConstraint*/,
860+
resourceProvider,
861+
);
862+
863+
assertErrorsInList(diagnostics, [
864+
error(AnalysisOptionsWarningCode.pluginsInInnerOptions, 11, 12),
865+
]);
866+
}
867+
868+
test_pluginsInInnerOptions_included() {
869+
newFile(optionsFilePath, '''
870+
plugins:
871+
one: ^1.0.0
872+
''');
873+
var code = '''
874+
include: ../analysis_options.yaml
875+
''';
876+
var filePath = '/inner/analysis_options.yaml';
877+
newFile(filePath, code);
878+
newFile('/pubspec.yaml', '''
879+
name: test
880+
version: 0.0.1
881+
''');
882+
var diagnostics = analyzeAnalysisOptions(
883+
sourceFactory.forUri2(toUri(filePath))!,
884+
code,
885+
sourceFactory,
886+
'/',
887+
null /*sdkVersionConstraint*/,
888+
resourceProvider,
889+
);
890+
891+
assertErrorsInList(diagnostics, []);
892+
}
893+
842894
List<Diagnostic> validate(String code, List<DiagnosticCode> expected) {
843895
newFile(optionsFilePath, code);
844896
var diagnostics = analyzeAnalysisOptions(

0 commit comments

Comments
 (0)