Skip to content

New YAML configuration for diagnostics analysis optionsΒ #57034

Open
@srawlins

Description

@srawlins

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, the unused_element Warning's severity is set to "ignore", the unused_import Warning's severity is set to "warning" (the diagnostic type, "Warning," is distinct from the severity, "warning"), and the dead_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, and strict-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 is true or false, 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 like strict_casts (or they could be refactored in a bigger way to just be like lint rules...).
  • There are four possible values: false, info, warning, and error.
    • false means "don't report this."
    • info, warning, and error mean, "do enable this, and report violations at this severity."
  • Alternative possible values: disable, enable, info, warning, and error.
    • disable means "don't report this."
    • enable means "do enable this, and report violations at the default severity."
    • info, warning, and error 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.

  1. In one release, Dart 3.N, we introduce the analyzer/diagnostics section. It cannot be specified side-by-side with analyzer/errors or linter/rules, but the values can be merged with included files.

    • If a file with analyzer/diagnostics includes one-or-more files with analyzer/errors or linter/rules, the options are merged, not at the YAML level, but at the internal-representation level.
    • If a file with analyzer/errors or linter/rules includes one-or-more files with analyzer/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 an analyzer/errors section or a linter/rules section?
  2. 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.)

  3. In the next release, Dart 3.N+2, we stop respecting the old sections (and report the old sections as "unknown"?).

CC @dart-lang/analyzer-team @DanTup @parlough

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestanalyzer-analysis-optionsarea-dart-modelFor issues related to conformance to the language spec in the parser, compilers or the CLI analyzer.type-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions