Skip to content

Analyzer#1345

Merged
rrousselGit merged 15 commits into
masterfrom
analyzer
Apr 23, 2026
Merged

Analyzer#1345
rrousselGit merged 15 commits into
masterfrom
analyzer

Conversation

@rrousselGit
Copy link
Copy Markdown
Owner

@rrousselGit rrousselGit commented Apr 23, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Improved class-name resolution, refined getter validation, and more accurate documentation extraction.
  • Tests

    • Updated test references and formatting; normalized analyzer diagnostic names to lowercase; suppressed a known analyzer false positive.
  • Chores

    • Bumped analyzer support to 12.x, added a dev dependency to address downgrade checks, converted repo to a workspace, adjusted CI matrix, updated .gitignore.
  • Documentation

    • Added an “Unreleased 3.2.6-dev.1” changelog entry.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Derives class names from namePart.typeName.lexeme, tightens getter/constructor checks and class-body handling, updates analyzer constraint to >=12.0.0 <13.0.0 and adds file dev-dependency, switches example package references to freezed_example, adjusts CI matrix channel to master, and adds an analyzer ignore in a test decorator. (44 words)

Changes

Cohort / File(s) Summary
Test import & formatting updates
packages/freezed/example/test/diagnosticable_test.dart, packages/freezed/example/test/json_test.dart, packages/freezed/test/json_test.dart
Switch imports from package:example/... to package:freezed_example/...; minor formatting-only adjustment in packages/freezed/test/json_test.dart.
Model parsing & AST handling
packages/freezed/lib/src/models.dart, packages/freezed/lib/src/ast.dart
Use ClassDeclaration.namePart.typeName.lexeme to derive class names; update constructor/redirected-constructor matching, super/mixin detection, and error messages; change getter validation to require isOriginDeclaration; restrict ClassDeclarationX.constructors/properties to BlockClassBody; change AST documentation extraction to prefer AnnotatedNode.documentationComment.
Analyzer / deps / pubspecs
packages/freezed/pubspec.yaml, packages/freezed/example/pubspec.yaml, pubspec.yaml
Set workspace resolution, add top-level workspace pubspec.yaml, bump analyzer constraint to >=12.0.0 <13.0.0, and add file: >=7.0.0 as a dev_dependency to address downgrade checks.
Tests — diagnostics expectation changes
packages/freezed/test/common_types_test.dart, packages/freezed/test/decorator_test.dart, packages/freezed/test/deep_copy_test.dart
Update expected analyzer diagnostic names from UPPERCASE to lowercase (e.g., UNUSED_RESULTunused_result, ARGUMENT_TYPE_NOT_ASSIGNABLEargument_type_not_assignable, etc.).
CI workflow
.github/workflows/build.yml
Change CI matrix channel to master (comment out stable); gate "Check format" on matrix.channel == 'master'; update test-runner detection to look for name: freezed_example.
Test decorator lint suppression
packages/freezed/test/integration/decorator.dart
Add analyzer ignore for unused_element_parameter on _WeirdDecorator constructor parameters to suppress a known false positive.
Changelog & gitignore
packages/freezed/CHANGELOG.md, .gitignore
Add "Unreleased 3.2.6-dev.1" changelog entry noting analyzer 12 support; add .dart_tool to .gitignore.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Handle analyzer 8 #1300 — Modifies the same analyzer-facing files (packages/freezed/lib/src/models.dart, src/ast.dart) adjusting AST/name handling.
  • Fix diagnostics #1226 — Changes CI workflow/channel logic and test/example detection similar to this PR.
  • Use range for analyzer version #1302 — Updates analyzer-related code and test diagnostics to newer analyzer API naming, overlapping with diagnostic name changes here.

Poem

🐇 I nudged the AST and chased a name,

Imports hopped home while tests stayed the same.
Tokens whisper truer from a fresher stream,
Analyzer twelve joins our tidy team.
I twitch my whiskers — CI hums like a dream.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Analyzer' is vague and generic, failing to communicate the specific changes or purpose of the pull request despite substantial modifications across multiple files. Use a more descriptive title that captures the main objective, such as 'Upgrade analyzer dependency to 12.0.0 and refactor class identifier resolution' or 'Update to analyzer 12.0 with workspace configuration.'
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch analyzer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@rrousselGit rrousselGit marked this pull request as ready for review April 23, 2026 07:44
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/freezed/lib/src/models.dart (1)

1076-1084: ⚠️ Potential issue | 🔴 Critical

Inverted synthetic check — throws on plain fields instead of explicit getters.

The condition at line 1079 is inverted. Per the analyzer documentation and the error message intent, this code should reject explicit getters on freezed classes without a private constructor, but currently rejects plain fields instead.

When an explicit getter like int get x => ... is declared, its PropertyAccessorElement is non-synthetic, and getter.nonSynthetic returns the getter itself. When a plain final int x; field is declared, its induced getter is synthetic, and getter.nonSynthetic returns the FieldElement (not the getter).

Case getter.nonSynthetic nonSynthetic != getter
Explicit int get x => … (should throw) getter itself false — no error
Plain final int x; (should pass) FieldElement true — throws error

The condition is inverted relative to the intended behavior. Change the operator from != to ==:

Proposed fix
     if (!shouldUseExtends &&
         field.getter != null &&
         !field.getter!.isAbstract &&
-        field.getter!.nonSynthetic != field.getter) {
+        field.getter!.nonSynthetic == field.getter) {
       throw InvalidGenerationSourceError(
         'Getters require a MyClass._() constructor',
         element: field,
       );
     }

This regression breaks existing tests: the @ShouldThrow('Getters require a MyClass._() constructor') cases in test/source_gen_src.dart for explicit getters (int get regularProperty => 42;) will fail to throw as expected.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/freezed/lib/src/models.dart` around lines 1076 - 1084, The condition
that rejects explicit getters is inverted: in the block checking
shouldUseExtends and field.getter you should compare getter.nonSynthetic to the
getter with == instead of != so explicit (non-synthetic) getters trigger the
InvalidGenerationSourceError('Getters require a MyClass._() constructor',
element: field) while synthetic field-induced accessors do not; update the
expression involving field.getter!.nonSynthetic and field.getter in the if
inside the shouldUseExtends branch accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/freezed/lib/src/models.dart`:
- Around line 1334-1355: The getters constructors and properties currently
switch on body and silently return const [] for unhandled shapes; add a
defensive assertion in the default branch that fails fast with a clear message
when body is an EmptyClassBody (or any unrecognized ClassBody) so callers know
the class shape is unsupported (referencing the getters constructors and
properties and the body switch on BlockClassBody); implement the assertion to
include the actual runtime type (e.g., "Unsupported ClassBody: $runtimeType
(EmptyClassBody not handled) — `@freezed` classes with semicolon are not
supported") so the error is thrown at the point of observation rather than later
in Class construction.

---

Outside diff comments:
In `@packages/freezed/lib/src/models.dart`:
- Around line 1076-1084: The condition that rejects explicit getters is
inverted: in the block checking shouldUseExtends and field.getter you should
compare getter.nonSynthetic to the getter with == instead of != so explicit
(non-synthetic) getters trigger the InvalidGenerationSourceError('Getters
require a MyClass._() constructor', element: field) while synthetic
field-induced accessors do not; update the expression involving
field.getter!.nonSynthetic and field.getter in the if inside the
shouldUseExtends branch accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6b22ab6b-2742-4af7-ba61-90876067dcb2

📥 Commits

Reviewing files that changed from the base of the PR and between b7ac4d7 and c3b6a54.

📒 Files selected for processing (5)
  • packages/freezed/example/test/diagnosticable_test.dart
  • packages/freezed/example/test/json_test.dart
  • packages/freezed/lib/src/models.dart
  • packages/freezed/pubspec.yaml
  • packages/freezed/test/integration/decorator.dart

Comment thread packages/freezed/lib/src/models.dart
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build.yml:
- Around line 25-26: The "Check format" step is guarded by if: matrix.channel ==
'stable' but you removed the 'stable' matrix lane (only 'master' remains), so
the formatting check never runs; update the CI so formatting is still enforced
by either restoring a 'stable' matrix entry or changing the step's condition to
target 'master' (e.g., replace the guard on the "Check format" step that
references matrix.channel == 'stable' with matrix.channel == 'master' or remove
the guard to run on all channels), ensuring you modify the matrix.channel
condition and the "Check format" step reference accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 134773b7-9835-4b21-9120-8b0fd9328049

📥 Commits

Reviewing files that changed from the base of the PR and between c3b6a54 and cef3e30.

📒 Files selected for processing (4)
  • .github/workflows/build.yml
  • packages/freezed/CHANGELOG.md
  • packages/freezed/example/pubspec.yaml
  • packages/freezed/pubspec.yaml
✅ Files skipped from review due to trivial changes (2)
  • packages/freezed/CHANGELOG.md
  • packages/freezed/example/pubspec.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/freezed/pubspec.yaml

Comment thread .github/workflows/build.yml
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/build.yml (1)

24-34: Dead matrix config referencing removed stable channel.

With stable commented out of channel, the exclude entries on lines 31–34 (and the cache expression on line 42) can never match. Consider cleaning these up to avoid confusion, or restore a stable lane if it's intended to come back.

🧹 Proposed cleanup
         channel:
           # - stable
           - master
         dependencies:
           - get
           - downgrade
-        exclude:
-          - channel: stable
-            dependencies: downgrade
-          - package: packages/freezed_lint
-            channel: stable
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build.yml around lines 24 - 34, The workflow matrix
contains a dead configuration: the channel list no longer includes "stable" but
the exclude rules (the exclude block referencing channel: stable and the
package: packages/freezed_lint / channel: stable rule) and the cache expression
still refer to "stable", so they will never match; either restore "stable" in
the channel matrix or remove/simplify the exclude entries and any cache
expressions that reference "stable" (look for the "channel:" list, the
"exclude:" block, and the cache expression that mentions stable) so the matrix
is consistent and there are no unreachable rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/build.yml:
- Around line 24-34: The workflow matrix contains a dead configuration: the
channel list no longer includes "stable" but the exclude rules (the exclude
block referencing channel: stable and the package: packages/freezed_lint /
channel: stable rule) and the cache expression still refer to "stable", so they
will never match; either restore "stable" in the channel matrix or
remove/simplify the exclude entries and any cache expressions that reference
"stable" (look for the "channel:" list, the "exclude:" block, and the cache
expression that mentions stable) so the matrix is consistent and there are no
unreachable rules.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 54a0b878-e1f0-4801-b93c-93cb6ff2b511

📥 Commits

Reviewing files that changed from the base of the PR and between 9a27854 and 5c73fd6.

📒 Files selected for processing (2)
  • .github/workflows/build.yml
  • packages/freezed/test/json_test.dart
✅ Files skipped from review due to trivial changes (1)
  • packages/freezed/test/json_test.dart

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/freezed/lib/src/models.dart (1)

1334-1355: ⚠️ Potential issue | 🟡 Minor

Avoid silently accepting unsupported class-body shapes.

EmptyClassBody/future ClassBody variants currently produce empty constructors/properties, which can defer the failure to a less clear assertion or generation path. Prefer failing here with an actionable InvalidGenerationSourceError.

Suggested defensive handling
   Iterable<ConstructorDeclaration> get constructors {
     final that = body;
     switch (that) {
       case BlockClassBody():
         return that.members.whereType<ConstructorDeclaration>();
       default:
-        return const [];
+        throw InvalidGenerationSourceError(
+          'Classes using `@freezed` must use a block class body. '
+          'Unsupported class body: ${that.runtimeType}.',
+          element: declaredFragment?.element,
+          node: this,
+        );
     }
   }
 
   Iterable<(FieldDeclaration, VariableDeclaration)> get properties {
     final that = body;
     switch (that) {
       case BlockClassBody():
         return that.members
             .whereType<FieldDeclaration>()
             .where((e) => !e.isStatic)
             .expand((e) => e.fields.variables.map((f) => (e, f)));
       default:
-        return const [];
+        throw InvalidGenerationSourceError(
+          'Classes using `@freezed` must use a block class body. '
+          'Unsupported class body: ${that.runtimeType}.',
+          element: declaredFragment?.element,
+          node: this,
+        );
     }
   }

Verification query:

What are the concrete subclasses of ClassBody returned by ClassDeclaration.body in package:analyzer 12.x, including semicolon class declarations?

Optional repository check:

#!/bin/bash
set -euo pipefail

# Confirm analyzer constraints and inspect current class-body handling/tests.
fd pubspec.yaml | xargs rg -n -C2 "analyzer:"
rg -n -C3 "BlockClassBody|EmptyClassBody|ClassBody|Iterable<ConstructorDeclaration> get constructors|Iterable<\\(FieldDeclaration" --type dart
rg -n -C2 -i "EmptyClassBody|semicolon|empty class|class\\s+[A-Za-z_][A-Za-z0-9_]*[^{};]*;" --type dart
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/freezed/lib/src/models.dart` around lines 1334 - 1355, The getters
constructors and properties currently swallow non-BlockClassBody shapes by
returning empty lists; change them to detect unsupported ClassBody variants
(e.g., EmptyClassBody / semicolon class bodies) and throw an
InvalidGenerationSourceError with an actionable message (mentioning the owning
ClassDeclaration name and the unexpected body kind) instead of returning const
[]; update both Iterable<ConstructorDeclaration> get constructors and
Iterable<(FieldDeclaration, VariableDeclaration)> get properties to perform this
check on body and throw InvalidGenerationSourceError for any non-BlockClassBody
to surface clear failures during generation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/freezed/lib/src/models.dart`:
- Around line 1334-1355: The getters constructors and properties currently
swallow non-BlockClassBody shapes by returning empty lists; change them to
detect unsupported ClassBody variants (e.g., EmptyClassBody / semicolon class
bodies) and throw an InvalidGenerationSourceError with an actionable message
(mentioning the owning ClassDeclaration name and the unexpected body kind)
instead of returning const []; update both Iterable<ConstructorDeclaration> get
constructors and Iterable<(FieldDeclaration, VariableDeclaration)> get
properties to perform this check on body and throw InvalidGenerationSourceError
for any non-BlockClassBody to surface clear failures during generation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a89ef4bb-e5c1-4948-b19b-752d1ff54dcd

📥 Commits

Reviewing files that changed from the base of the PR and between 5c73fd6 and 912fa43.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • .gitignore
  • packages/freezed/example/pubspec.yaml
  • packages/freezed/lib/src/ast.dart
  • packages/freezed/lib/src/models.dart
  • packages/freezed/pubspec.yaml
  • packages/freezed/test/common_types_test.dart
  • packages/freezed/test/decorator_test.dart
  • packages/freezed/test/deep_copy_test.dart
  • pubspec.yaml
✅ Files skipped from review due to trivial changes (3)
  • packages/freezed/test/deep_copy_test.dart
  • .gitignore
  • pubspec.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/freezed/example/pubspec.yaml
  • packages/freezed/pubspec.yaml

@rrousselGit rrousselGit merged commit c9545cb into master Apr 23, 2026
7 checks passed
@rrousselGit rrousselGit deleted the analyzer branch April 23, 2026 09:58
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.

1 participant