Skip to content

Commit 3518e02

Browse files
srawlinsCommit Queue
authored andcommitted
analyzer: Make strict modes part of AnalysisOptions API
I think when I was adding these modes, I put them on AnalysisOptionsImpl to keep them secret and flexible. But they're pretty stable now. Also split out the analysis options `include` tests to test merging of individual lists and maps. Change-Id: Ie54a1951dc82900c1fdfc06023cfa7cfb2f410a2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391020 Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 32d3c44 commit 3518e02

File tree

4 files changed

+210
-47
lines changed

4 files changed

+210
-47
lines changed

pkg/analyzer/lib/dart/analysis/analysis_options.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ abstract class AnalysisOptions {
5959
@Deprecated('Use `PubWorkspacePackage.sdkVersionConstraint` instead')
6060
VersionConstraint? get sdkVersionConstraint;
6161

62+
/// Whether implicit casts should be reported as potential problems.
63+
bool get strictCasts;
64+
65+
/// Whether inference failures are allowed, off by default.
66+
bool get strictInference;
67+
68+
/// Whether raw types (types without explicit type arguments, such as `List`)
69+
/// should be reported as potential problems.
70+
///
71+
/// Raw types are a common source of `dynamic` being introduced implicitly.
72+
bool get strictRawTypes;
73+
6274
/// Return `true` if analysis is to generate warning results (e.g. best
6375
/// practices and analysis based on certain annotations).
6476
bool get warning;

pkg/analyzer/lib/source/error_processor.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class ErrorProcessor {
8181
code == error.errorCode.name ||
8282
code == error.errorCode.name.toUpperCase();
8383

84+
@override
85+
String toString() => "ErrorProcessor[code='$code', severity=$severity]";
86+
8487
/// Return an error processor associated in the [analysisOptions] for the
8588
/// given [error], or `null` if none is found.
8689
static ErrorProcessor? getProcessor(

pkg/analyzer/lib/src/generated/engine.dart

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -424,19 +424,13 @@ class AnalysisOptionsImpl implements AnalysisOptions {
424424
/// re-throwing them).
425425
bool propagateLinterExceptions;
426426

427-
/// Whether implicit casts should be reported as potential problems.
427+
@override
428428
final bool strictCasts;
429429

430-
/// A flag indicating whether inference failures are allowed, off by default.
431-
///
432-
/// This option is experimental and subject to change.
430+
@override
433431
final bool strictInference;
434432

435-
/// Whether raw types (types without explicit type arguments, such as `List`)
436-
/// should be reported as potential problems.
437-
///
438-
/// Raw types are a common source of `dynamic` being introduced implicitly.
439-
/// This often leads to cast failures later on in the program.
433+
@override
440434
final bool strictRawTypes;
441435

442436
@override

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

Lines changed: 192 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
1717
main() {
1818
defineReflectiveSuite(() {
1919
defineReflectiveTests(OptionsProviderTest);
20+
21+
// TODO(srawlins): add tests for multiple includes.
22+
// TODO(srawlins): add tests with duplicate legacy plugin names.
23+
// https://github.com/dart-lang/sdk/issues/50980
2024
});
2125
}
2226

@@ -79,62 +83,212 @@ analyzer:
7983
expect(options.enabledLegacyPluginNames, unorderedEquals(['plugin_ddd']));
8084
}
8185

82-
test_mergeIncludedOptions() {
83-
// TODO(srawlins): Split this into smaller tests.
84-
// TODO(srawlins): add tests for multiple includes.
85-
// TODO(srawlins): add tests with duplicate legacy plugin names.
86-
// https://github.com/dart-lang/sdk/issues/50980
86+
test_include_analyzerErrorSeveritiesAreMerged() {
87+
newFile('/other_options.yaml', '''
88+
analyzer:
89+
errors:
90+
toplevelerror: warning
91+
''');
92+
newFile(optionsFilePath, r'''
93+
include: other_options.yaml
94+
analyzer:
95+
errors:
96+
lowlevelerror: warning
97+
''');
98+
99+
var options = _getOptionsObject('/');
100+
101+
expect(
102+
options.errorProcessors,
103+
unorderedMatches([
104+
ErrorProcessorMatcher(
105+
ErrorProcessor('toplevelerror', ErrorSeverity.WARNING)),
106+
ErrorProcessorMatcher(
107+
ErrorProcessor('lowlevelerror', ErrorSeverity.WARNING)),
108+
]),
109+
);
110+
}
111+
112+
test_include_analyzerErrorSeveritiesAreMerged_multipleIncludes() {
113+
newFile('/first_options.yaml', '''
114+
analyzer:
115+
errors:
116+
error_1: error
117+
''');
118+
newFile('/second_options.yaml', '''
119+
include: first_options.yaml
120+
analyzer:
121+
errors:
122+
error_2: warning
123+
''');
124+
newFile(optionsFilePath, r'''
125+
include: second_options.yaml
126+
''');
127+
128+
var options = _getOptionsObject('/');
87129

130+
expect(
131+
options.errorProcessors,
132+
contains(
133+
ErrorProcessorMatcher(ErrorProcessor('error_1', ErrorSeverity.ERROR)),
134+
),
135+
);
136+
}
137+
138+
test_include_analyzerErrorSeveritiesAreMerged_outermostWins() {
139+
newFile('/other_options.yaml', '''
140+
analyzer:
141+
errors:
142+
error_1: warning
143+
error_2: warning
144+
''');
145+
newFile(optionsFilePath, r'''
146+
include: other_options.yaml
147+
analyzer:
148+
errors:
149+
error_1: ignore
150+
''');
151+
152+
var options = _getOptionsObject('/');
153+
154+
expect(
155+
options.errorProcessors,
156+
unorderedMatches([
157+
// We want to explicitly state the expected severity.
158+
// ignore: avoid_redundant_argument_values
159+
ErrorProcessorMatcher(ErrorProcessor('error_1', null)),
160+
ErrorProcessorMatcher(ErrorProcessor('error_2', ErrorSeverity.WARNING)),
161+
]),
162+
);
163+
}
164+
165+
test_include_analyzerExcludeListsAreMerged() {
88166
newFile('/other_options.yaml', '''
89167
analyzer:
90168
exclude:
91169
- toplevelexclude.dart
92-
plugins:
93-
toplevelplugin:
94-
enabled: true
95-
errors:
96-
toplevelerror: warning
97-
linter:
98-
rules:
99-
- toplevellint
100170
''');
101-
String code = r'''
171+
newFile(optionsFilePath, r'''
102172
include: other_options.yaml
103173
analyzer:
104174
exclude:
105175
- lowlevelexclude.dart
106-
errors:
107-
lowlevelerror: warning
176+
''');
177+
178+
var options = _getOptionsObject('/');
179+
180+
expect(
181+
options.excludePatterns,
182+
unorderedEquals(['toplevelexclude.dart', 'lowlevelexclude.dart']),
183+
);
184+
}
185+
186+
test_include_analyzerLanguageModesAreMerged() {
187+
newFile('/other_options.yaml', '''
188+
analyzer:
189+
language:
190+
strict-casts: true
191+
''');
192+
newFile(optionsFilePath, r'''
193+
include: other_options.yaml
194+
analyzer:
195+
language:
196+
strict-inference: true
197+
''');
198+
199+
var options = _getOptionsObject('/');
200+
201+
expect(options.strictCasts, true);
202+
expect(options.strictInference, true);
203+
expect(options.strictRawTypes, false);
204+
}
205+
206+
test_include_linterRulesAreMerged() {
207+
newFile('/other_options.yaml', '''
108208
linter:
109209
rules:
110-
- lowlevellint
111-
''';
112-
newFile(optionsFilePath, code);
113-
114-
var lowlevellint = TestRule.withName('lowlevellint');
115-
var toplevellint = TestRule.withName('toplevellint');
116-
Registry.ruleRegistry.register(lowlevellint);
117-
Registry.ruleRegistry.register(toplevellint);
210+
- top_level_lint
211+
''');
212+
newFile(optionsFilePath, r'''
213+
include: other_options.yaml
214+
linter:
215+
rules:
216+
- low_level_lint
217+
''');
218+
219+
var lowLevelLint = TestRule.withName('low_level_lint');
220+
var topLevelLint = TestRule.withName('top_level_lint');
221+
Registry.ruleRegistry.register(lowLevelLint);
222+
Registry.ruleRegistry.register(topLevelLint);
223+
var options = _getOptionsObject('/');
224+
225+
expect(options.lintRules, unorderedEquals([topLevelLint, lowLevelLint]));
226+
}
227+
228+
test_include_linterRulesAreMerged_differentFormats() {
229+
newFile('/other_options.yaml', '''
230+
linter:
231+
rules:
232+
top_level_lint: true
233+
''');
234+
newFile(optionsFilePath, r'''
235+
include: other_options.yaml
236+
linter:
237+
rules:
238+
- low_level_lint
239+
''');
240+
241+
var lowLevelLint = TestRule.withName('low_level_lint');
242+
var topLevelLint = TestRule.withName('top_level_lint');
243+
Registry.ruleRegistry.register(lowLevelLint);
244+
Registry.ruleRegistry.register(topLevelLint);
245+
var options = _getOptionsObject('/');
246+
247+
expect(options.lintRules, unorderedEquals([topLevelLint, lowLevelLint]));
248+
}
249+
250+
test_include_linterRulesAreMerged_outermostWins() {
251+
newFile('/other_options.yaml', '''
252+
linter:
253+
rules:
254+
- top_level_lint
255+
''');
256+
newFile(optionsFilePath, r'''
257+
include: other_options.yaml
258+
linter:
259+
rules:
260+
top_level_lint: false
261+
''');
262+
263+
var topLevelLint = TestRule.withName('top_level_lint');
264+
Registry.ruleRegistry.register(topLevelLint);
265+
var options = _getOptionsObject('/');
266+
267+
expect(options.lintRules, isNot(contains(topLevelLint)));
268+
}
269+
270+
test_include_pluginCanBeIncluded() {
271+
newFile('/other_options.yaml', '''
272+
analyzer:
273+
plugins:
274+
toplevelplugin:
275+
enabled: true
276+
''');
277+
newFile(optionsFilePath, r'''
278+
include: other_options.yaml
279+
''');
280+
118281
var options = _getOptionsObject('/');
119282

120-
expect(options.lintRules, unorderedEquals([toplevellint, lowlevellint]));
121-
expect(
122-
options.enabledLegacyPluginNames, unorderedEquals(['toplevelplugin']));
123-
expect(options.excludePatterns,
124-
unorderedEquals(['toplevelexclude.dart', 'lowlevelexclude.dart']));
125283
expect(
126-
options.errorProcessors,
127-
unorderedMatches([
128-
ErrorProcessorMatcher(
129-
ErrorProcessor('toplevelerror', ErrorSeverity.WARNING)),
130-
ErrorProcessorMatcher(
131-
ErrorProcessor('lowlevelerror', ErrorSeverity.WARNING))
132-
]));
284+
options.enabledLegacyPluginNames,
285+
unorderedEquals(['toplevelplugin']),
286+
);
133287
}
134288

135-
AnalysisOptions _getOptionsObject(String posixPath) =>
289+
AnalysisOptions _getOptionsObject(String filePath) =>
136290
AnalysisOptionsImpl.fromYaml(
137-
optionsMap: provider.getOptions(getFolder(posixPath)));
291+
optionsMap: provider.getOptions(getFolder(filePath)));
138292
}
139293

140294
class TestRule extends LintRule {

0 commit comments

Comments
 (0)