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_element
Warning's severity is set to "ignore", theunused_import
Warning's severity is set to "warning" (the diagnostic type, "Warning," is distinct from the severity, "warning"), and thedead_code
Warning'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 istrue
orfalse
, 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|enable
Here's how it works:
- The
analyzer/diagnostics
section 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_comparison
or 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
.false
means "don't report this."info
,warning
, anderror
mean, "do enable this, and report violations at this severity."
- Alternative possible values:
disable
,enable
,info
,warning
, anderror
.disable
means "don't report this."enable
means "do enable this, and report violations at the default severity."info
,warning
, anderror
mean "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_quotes
I 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/diagnostics
section. It cannot be specified side-by-side withanalyzer/errors
orlinter/rules
, but the values can be merged with included files.- If a file with
analyzer/diagnostics
includes one-or-more files withanalyzer/errors
orlinter/rules
, the options are merged, not at the YAML level, but at the internal-representation level. - If a file with
analyzer/errors
orlinter/rules
includes 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
*.yaml
which has either ananalyzer/errors
section or alinter/rules
section?
- 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"?).