Skip to content

Review fixes for the new rules: false positives, Dart 3.10 gating, and 4.2.0 version sync - #261

Merged
juan-campuzano merged 6 commits into
bancolombia:add-new-rulesfrom
Akhrameev:fix/prefer-dot-shorthands-inferred-generic
Aug 10, 2026
Merged

Review fixes for the new rules: false positives, Dart 3.10 gating, and 4.2.0 version sync#261
juan-campuzano merged 6 commits into
bancolombia:add-new-rulesfrom
Akhrameev:fix/prefer-dot-shorthands-inferred-generic

Conversation

@Akhrameev

Copy link
Copy Markdown
Contributor

Wow!

Hey @juan-campuzano, really nice set of rules in draft!

While reviewing, I hit a few edge cases.
I found 4 issues; here is their resolution.

prefer-dot-shorthands

  • Broken auto-fix on inferred generics. For ValueNotifier(LogLevel.info) the
    substituted parameter type (T = LogLevel) matched the context check, but the
    suggested .info removes the very argument T is inferred from, so the fixed code
    fails with DOT_SHORTHAND_MISSING_CONTEXT. The rule now skips parameters declared
    as type parameters (checked via baseElement, available on analyzer 10-14).
  • No language-version gate. The rule suggested Dart 3.10 syntax on any file, but
    a project with e.g. sdk: ^3.5.0 resolves below 3.10 and the fix would not
    compile. check now bails out unless the unit's featureSet enables
    Feature.dot_shorthands; a // @dart=3.9 fixture proves it stays silent.
  • Addition testing will catch any future rule change whose auto-fix produces invalid code.

avoid-non-exhaustive-switch-on-sealed-classes

  • Guarded wildcards were flagged. case _ when condition: does not satisfy
    exhaustiveness, so the compiler still enforces the remaining subtypes and the
    rule's rationale does not apply. Both switch-statement and switch-expression
    branches now require the guarded pattern to have no when clause.

avoid-non-configurable-callbacks-in-init-state

  • Non-callback configs were flagged. "Callback object" detection accepted any
    named argument, so widget.controller.configure(Options(timeout: 5)) was
    reported. It now requires at least one named argument with a function type.
  • Tear-off callbacks were judged blindly. onError: _handleError was reported
    even when _handleError reads widget fields inside its body. The rule now follows
    references to methods of the same State class (transitively) and scans their
    bodies; callbacks resolving outside the class are conservatively not reported.
    A hardcoded tear-off (body touching no widget field) is still caught.

Coverage and hygiene

  • Unit tests for the new ast_compat.correspondingParameterOf (positional, named,
    constructor-named, non-argument), matching how isAbstractMethod was covered.
  • Rule tests upgraded to RuleTestHelper.verifyIssues with exact lines and
    replacements; fixtures added for the rules' skip branches (const constructor
    calls, explicit type arguments, supertype-typed parameters, multiple violations
    in one initState).
  • Both new dart rules added to the dart_all preset (prefer-dot-shorthands is
    safe there now that it no-ops below Dart 3.10).
  • 4.2.0 version sync: tools/analyzer_plugin/pubspec.yaml, README compatibility
    table row, and a CHANGELOG note about the 3.10 gate.

Verification

make test-analyzer-compat-full passes on all rows (analyzer 10.0.1, 11.0.0,
12.1.0, 13.0.0, 13.3.0, 14.0.0, 14.1.0).

…rameters

When a parameter is declared as a type parameter (e.g. `T value` in
`ValueNotifier<T>`), its substituted context type may be inferred from
the argument itself; rewriting the argument to a dot shorthand removes
the inference source and the fixed code no longer compiles
(DOT_SHORTHAND_MISSING_CONTEXT). Guard on the parameter declaration's
type via `baseElement` (available across analyzer 10-14).

Also tighten the rule test: assert exact issue lines and replacements
via RuleTestHelper.verifyIssues, and add a step that applies every
suggested replacement to the fixture and runs `dart analyze` on the
result (opted in to Dart 3.10 via `// @Dart=3.10`) to prove the fixes
compile
…ldcards

A guarded wildcard (`case _ when condition:`) doesn't satisfy
exhaustiveness, so the compiler still enforces coverage of the
remaining subtypes; it isn't a fallback that hides missing cases and
the rule's rationale doesn't apply to it. Require the guarded pattern
to have no `when` clause in both switch statements and switch
expressions.

Also tighten the rule test to assert exact issue lines via
RuleTestHelper.verifyIssues and add guarded-wildcard fixtures for both
switch forms
…verage

The rule suggested Dart 3.10 syntax regardless of the analyzed file's
language version, so on pre-3.10 code the warning was unactionable and
the auto-fix produced code that does not compile. Bail out unless the
unit's featureSet enables dot_shorthands (present across analyzer
10-14). The main fixture opts in via `// @Dart=3.10`; a new pre-3.10
fixture proves the rule stays silent below that.

Also add avoid-non-exhaustive-switch-on-sealed-classes and
prefer-dot-shorthands to the dart_all preset, and extend coverage:
- unit tests for ast_compat.correspondingParameterOf (positional,
  named, constructor-named, non-argument)
- dot-shorthands fixtures for const constructor calls, explicit type
  arguments, and supertype-typed parameters
- init-state rule: exact-line assertions via verifyIssues plus a
  two-violations-in-one-initState fixture
- fix a misplaced deprecated_member_use ignore in ast_compat_test

Verified with make test-analyzer-compat-full across analyzer 10.0.1
through 14.1.0
…-typed callbacks

The "callback object" check accepted any named argument, so a plain
value configuration like `widget.controller.configure(Options(timeout:
5))` was reported as a hardcoded callback configuration. Require at
least one named argument whose static type is a function type.

Known limitation (documented in the visitor): a tear-off callback that
reads widget fields inside its body is still reported, since only the
creation expression itself is inspected for `widget` references
Bump tools/analyzer_plugin/pubspec.yaml to 4.2.0, add the 4.2.0 row to
the README compatibility table, and note in the changelog that
prefer-dot-shorthands only fires on language version 3.10+
… callback bodies

A tear-off callback (e.g. `onError: _handleError`) was judged only by
the configuration expression itself, so a handler that reads widget
fields inside its body was still reported as hardcoded. Follow
references to methods of the same State class (tear-offs and calls
inside callback literals, transitively) and scan their bodies for
`widget` references. Function-typed arguments that resolve outside the
class cannot be inspected within a single resolved unit and are
conservatively treated as referencing the widget.

Fixtures: tear-off reading a widget field, transitive tear-off, and
external tear-off (all not flagged); hardcoded tear-off (flagged).
@juan-campuzano

Copy link
Copy Markdown
Contributor

@Akhrameev thanks!

@juan-campuzano
juan-campuzano merged commit 45a8f15 into bancolombia:add-new-rules Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants