-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
New YAML configuration for diagnostics analysis options
Addresses #58693
Problem: confusing way to specify diagnostics options
Let's look at an example:
analyzer:
errors:
unused_element: ignore
unused_import: warning
dead_code: error
language:
- strict-casts
linter:
rules:
double_quotes: false
single_quotes: true Section by section:
analyzer/errors: In this section, we can set the severity of individual diagnostic codes. In the example, theunused_elementWarning's severity is set to "ignore", theunused_importWarning's severity is set to "warning" (the diagnostic type, "Warning," is distinct from the severity, "warning"), and thedead_codeWarning's severity is set to "error."analyzer/language: In this section, we can enable three different "strict analysis modes":strict-casts,strict-inference, andstrict-raw-types.linter/rules: In this section, we can specify a list of lint rules to enable (distinct from the names of the diagnostics they produce), or a map, where each key is a lint rule name, and each value istrueorfalse, enabling or disabling the lint rule.
There can be confusion around these three sections, as they seem to each serve approximately the same function: enabling and disabling diagnostics that are produced by the analyzer.
Proposal: a single section
I believe we can combine these three sections into a single one, placed at analyzer/diagnostics (or alternatively just a top-level diagnostics section). The above example would be written as:
analyzer:
diagnostics:
unused_element: false|disable
unused_import: warning
dead_code: error
strict-casts: warning|enable
double_quotes: false|disable
single_quotes: warning|enableHere's how it works:
- The
analyzer/diagnosticssection must be a YAML map. - Each key is just a diagnostic name. In the case of Warning diagnostics, this can be a "shared name" (e.g.
unnecessary_null_comparisonor a "unique name" (e.g.unnecessary_null_comparison_always_null_false). In the case of Lint diagnostics, this can be a lint rule name, which acts as a shared name (e.g.invalid_runtime_check_with_js_interop_types), or can be a unique diagnostic name (e.g.invalid_runtime_check_with_js_interop_types_dart_as_js). The three "strict modes" will have to be changed to report diagnostics that have a shared name likestrict_casts(or they could be refactored in a bigger way to just be like lint rules...). - There are four possible values:
false,info,warning, anderror.falsemeans "don't report this."info,warning, anderrormean, "do enable this, and report violations at this severity."
- Alternative possible values:
disable,enable,info,warning, anderror.disablemeans "don't report this."enablemeans "do enable this, and report violations at the default severity."info,warning, anderrormean "do enable this, and report violations at this severity."
Alternatives
Using a YAML list
The analyzer/diagnostics section could be a list. This would allow specifying lint rules without a true/false/warning/whatever value:
analyzer:
diagnostics:
- unused_element: false
- unused_import: warning
- dead_code: error
- strict-casts
- double_quotes: false
- single_quotesI think this probably makes the syntax more confusing, and not much more terse. One benefit is that developers don't have to "choose" what severity lint rules are reported at (e.g. "warning").
Save the strict modes for later
It can be an incremental migration. Refactoring the strict modes may be a bigger effort. We could leave them in place, for a first phase of migrating to analyzer/diagnostics. The two sections which are most important to combine are analyzer/errors and linter/rules.
Migration
The migration would be incremental.
-
In one release, Dart 3.N, we introduce the
analyzer/diagnosticssection. It cannot be specified side-by-side withanalyzer/errorsorlinter/rules, but the values can be merged with included files.- If a file with
analyzer/diagnosticsincludes one-or-more files withanalyzer/errorsorlinter/rules, the options are merged, not at the YAML level, but at the internal-representation level. - If a file with
analyzer/errorsorlinter/rulesincludes one-or-more files withanalyzer/diagnostics, the options are merged, not at the YAML level, but at the internal-representation level. - In this release, we also offer an assist to migrate the contents of an analysis options file from the old format to the new. (I guess we'd offer it for any file named
*.yamlwhich has either ananalyzer/errorssection or alinter/rulessection?
- If a file with
-
In the next release, Dart 3.N+1, we deprecate the old options. There is no change in the behavior of what options are parsed; only new warnings are reported in analysis options files.
We delay deprecating them for CI purposes. (Maybe this can be done between dev releases or flutter rolls... but tricky with the customer tests.)
-
In the next release, Dart 3.N+2, we stop respecting the old sections (and report the old sections as "unknown"?).