Skip to content

Use range for analyzer version#1302

Merged
rrousselGit merged 4 commits intomasterfrom
revert-analyzer8
Sep 10, 2025
Merged

Use range for analyzer version#1302
rrousselGit merged 4 commits intomasterfrom
revert-analyzer8

Conversation

@rrousselGit
Copy link
Owner

@rrousselGit rrousselGit commented Sep 10, 2025

Summary by CodeRabbit

  • Chores

    • Broaden dependency constraints (analyzer, build, source_gen) and add a new dependency to improve compatibility with analyzer 7.5.9–<9.0.0.
    • Update lint package constraints and temporarily ignore a deprecation in analysis settings.
  • Refactor

    • Migrate internals to newer analyzer APIs for improved forward compatibility. No functional changes expected for end users.
  • Tests

    • Update test suite to align with the analyzer’s new error reporting API, maintaining existing coverage and behavior.

@coderabbitai
Copy link

coderabbitai bot commented Sep 10, 2025

Walkthrough

Migrates the codebase to Dart analyzer v2 APIs: switches to element2/element3, name3, methods2/getters2, updates error reporting from diagnostics to errors, and adjusts tests and lints accordingly. Pubspecs broaden analyzer ranges (>=7.5.9 <9.0.0) and add pub_semver. analysis_options adds an ignore for deprecated_member_use.

Changes

Cohort / File(s) Summary
Analyzer config
analysis_options.yaml
Adds analyzer.errors ignore for deprecated_member_use with a note about requiring analyzer >=8 later; retains invalid_annotation_target ignore.
Core AST and models migration
packages/freezed/lib/src/ast.dart, packages/freezed/lib/src/models.dart
Replace analyzer element APIs with element2/element3; rename accesses to name3, methods2, getters2, fields2; update extensions to target …Element2; adjust constructor/class/library getters and helper signatures.
Parser/generator
packages/freezed/lib/src/parse_generator.dart
Update imports to element2; change generateForAnnotatedElement to accept Element2; match AST by name3.
Templates
packages/freezed/lib/src/templates/*
Switch to element2 API across concrete_template.dart, parameter_template.dart, properties.dart, prototypes.dart; update signatures (e.g., TypeParameterElement2, ConstructorElement2); use metadata2.annotations, name3, getField2.
Tools: imports/recursive/type
packages/freezed/lib/src/tools/imports.dart, .../recursive_import_locator.dart, .../type.dart
Migrate traversal/rendering to LibraryElement2/Element2; update exportedLibraries2/importedLibrary2/library2, element/name3 access; public method/extension signatures updated accordingly.
Pubspecs
packages/freezed/pubspec.yaml, packages/freezed_lint/pubspec.yaml
Broaden analyzer to ">=7.5.9 <9.0.0"; relax build/source_gen ranges; add pub_semver; adjust custom_lint(_builder) to ^0.8.0.
Tests migration
packages/freezed/test/*
Update analyzer result usage: diagnostics → errors; rename properties to name3; switch element types/collections to …2 variants (fields2, constructors2, getter2).
Lint rules
packages/freezed_lint/lib/src/missing_mixin.dart, .../missing_private_empty_ctor.dart, .../tools/element_extensions.dart
Swap DiagnosticReporter/Diagnostic for ErrorReporter/AnalysisError; update severity enums; migrate ClassElement → ClassElement2 and constructors → constructors2; rename name → name3, name2.lexeme where applicable.

Sequence Diagram(s)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Migrate to analyzer element2 model #1276 — Similar analyzer element2 migration across the same Freezed files; closely mirrors these API changes.
  • Update analyzer 8 #1301 — Adjusts analyzer integrations in lint sources (missing_mixin, element_extensions), overlapping with this PR’s lint updates.
  • Ci #1128 — Touches ConstructorX getters in ast.dart, which are also modified here for analyzer v2 APIs.

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title “Use range for analyzer version” only refers to the dependency constraint change, but the pull request’s primary work is a comprehensive migration of the codebase to the Analyzer v2 API (element2/element3, name3, methods2, etc.) alongside updating analyzer version constraints; the title fails to capture the main scope of the changes. Rename the pull request to reflect the core update, for example “Migrate codebase to Analyzer v2 API and update analyzer dependency range,” so it clearly summarizes both the API migration and the version constraint change.
✅ Passed checks (2 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 changes. Docstring coverage check skipped.

Poem

A rabbit taps keys with a rhythmic cheer,
name3 hops in, and element2 draws near.
Diagnostics burrowed; errors now bloom,
Fields2 and getters2 tidy the room.
Pubspec trails widen, constraints align—
I thump my paws: “The build is fine!” 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch revert-analyzer8

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 merged commit 89d763e into master Sep 10, 2025
3 of 4 checks passed
@rrousselGit rrousselGit deleted the revert-analyzer8 branch September 10, 2025 15:48
Copy link

@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: 7

Caution

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

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

72-79: Fix no-op cast; strongly type the resolved unit.

unit as ResolvedUnitResult; is a no-op and doesn’t change the type of unit. Use a typed variable to avoid dynamic.

-    final unit = await element.session!.getResolvedUnit(
-      element.firstFragment.libraryFragment!.source.fullName,
-    );
-    unit as ResolvedUnitResult;
-    final Object? ast = unit.unit.declarations.firstWhereOrNull(
+    final resolvedUnit = await element.session!.getResolvedUnit(
+      element.firstFragment.libraryFragment!.source.fullName,
+    ) as ResolvedUnitResult;
+    final Object? ast = resolvedUnit.unit.declarations.firstWhereOrNull(
       (declaration) =>
-          declaration.declaredFragment?.element.name3 == element.name3!,
+          declaration.declaredFragment?.element.name3 == element.name3!,
     );
packages/freezed_lint/lib/src/missing_private_empty_ctor.dart (1)

10-17: User-facing message spacing typo.
There’s a missing space: “accessors,requires”. Add a trailing space to the previous string.

-        'Freezed classes containing methods, fields or accessors,'
+        'Freezed classes containing methods, fields or accessors, '
🧹 Nitpick comments (18)
packages/freezed_lint/lib/src/missing_mixin.dart (3)

50-51: Unused others parameter—prefix with underscore to silence lints.

Minor polish to avoid an unused parameter warning.

-    AnalysisError analysisError,
-    List<AnalysisError> others,
+    AnalysisError analysisError,
+    List<AnalysisError> _,

63-68: Insertion offset is brittle when there’s no space before {.

Using node.leftBracket.offset - 1 assumes a space before the brace. If code is class A{, the insertion occurs before the last identifier, producing invalid code. Insert at leftBracket.offset instead and include a leading space when needed.

-          final offset = node.leftBracket.offset - 1;
+          final offset = node.leftBracket.offset;
           if (node.withClause != null) {
-            builder.addSimpleInsertion(offset, ', _\$$name');
+            builder.addSimpleInsertion(offset, ', _\$$name');
           } else {
-            builder.addSimpleInsertion(offset, ' with _\$$name');
+            builder.addSimpleInsertion(offset, ' with _\$$name');
           }

56-56: Use a stable name in the fix message.

node.name is a SimpleIdentifier; relying on its toString() is fine but using element.displayName (already computed below) avoids surprises.

-        message: 'Add mixin _\$${node.name}',
+        message: 'Add mixin _\$$name',
packages/freezed/lib/src/templates/concrete_template.dart (1)

525-542: metadata2 is deprecated in analyzer ≥8; keep plan to migrate to metadata when bumping.

Using metadata2.annotations is valid across 7.5.9–8.x, but it’s deprecated in newer analyzer versions. Your analysis_options ignore makes this workable for now; when you raise the lower bound to ≥8, flip back to metadata.annotations and drop the ignore. (pub.dev)

Optionally centralize this behind a helper to ease the eventual switch:

// e.g. lib/src/tools/analyzer_compat.dart
import 'package:analyzer/dart/element/element2.dart';

extension AnnotationsCompat on Annotatable {
  // TODO: when requiring analyzer >=8, switch to `metadata.annotations`.
  Iterable<ElementAnnotation> get annotationsCompat => metadata2.annotations;
}

Then iterate for (final meta in parameter.annotationsCompat) { ... }.

analysis_options.yaml (1)

10-11: Scope the deprecation ignore if possible.

Rather than a global deprecated_member_use: ignore, consider targeted // ignore: deprecated_member_use at the few call-sites (e.g., metadata2) so unrelated deprecations remain visible.

packages/freezed/test/common.dart (1)

2-4: Drop now-unused diagnostic import.

package:analyzer/diagnostic/diagnostic.dart seems unused after migrating to AnalysisError/Severity.

-import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
packages/freezed_lint/pubspec.yaml (1)

12-12: Analyzer range broadened — sanity-check API availability at the floor.

Your code uses v2 APIs (element2, name3, ErrorsResult.errors). Please confirm these are present in analyzer 7.5.9 specifically; otherwise raise the floor.

Suggested CI hardening:

  • Job A: resolve to minimum versions (e.g., dart pub downgrade analyzer:7.5.9) and run tests.
  • Job B: resolve to latest allowed (dart pub upgrade) and run tests.

I can draft the workflow snippet on request.

packages/freezed/lib/src/parse_generator.dart (1)

66-71: Avoid shadowing the annotation parameter.

The local annotation hides the method parameter and hurts readability.

-    final annotation = typeChecker.firstAnnotationOf(
+    final ann = typeChecker.firstAnnotationOf(
       element,
       throwOnUnresolved: false,
     );
-    if (annotation == null) return;
+    if (ann == null) return;
...
-    final datas = <AnnotationMeta>[(declaration: ast, annotation: annotation)];
+    final datas = <AnnotationMeta>[(declaration: ast, annotation: ann)];
packages/freezed/test/typedef_parameter_test.dart (1)

42-44: Use semantic default-constructor check with isDefaultConstructor
Replace

var constructor = freezedClass.constructors2.firstWhere(
  (e) => e.name3 == 'new',
);

with

import 'package:freezed/src/templates/prototypes.dart';

var constructor = freezedClass.constructors2.firstWhere(isDefaultConstructor);

This uses the existing helper function instead of brittle string-matching.

packages/freezed/lib/src/tools/type.dart (1)

65-69: Prefer display strings for typedef type arguments.
Using join on DartType relies on toString(). Use getDisplayString() for consistency.

-    displayType = type.alias!.element2.name3!;
-    if (type.alias!.typeArguments.isNotEmpty) {
-      displayType += '<${type.alias!.typeArguments.join(', ')}>';
-    }
+    displayType = type.alias!.element2.name3!;
+    if (type.alias!.typeArguments.isNotEmpty) {
+      final args = type.alias!.typeArguments
+          .map((t) => t.getDisplayString())
+          .join(', ');
+      displayType += '<$args>';
+    }
packages/freezed_lint/lib/src/missing_private_empty_ctor.dart (1)

1-3: Keep analyzer range alignment in freezed_lint.
Given past blockers with custom_lint upgrades, double-check freezed_lint’s pubspec analyzer range matches the repo-wide <9.0.0 constraint and that transitive analyzer_plugin/source_gen versions remain compatible.

packages/freezed/lib/src/tools/recursive_import_locator.dart (1)

93-95: Nit: rename misleading parameter.

fromImport() takes a LibraryImport but the param is named export.

Apply this diff:

-  static _LibraryDirectives? fromImport(LibraryImport export) {
-    final library = export.importedLibrary2;
+  static _LibraryDirectives? fromImport(LibraryImport import) {
+    final library = import.importedLibrary2;
packages/freezed/lib/src/tools/imports.dart (3)

9-12: Tiny clarity/robustness nits: seed visited with this + rename loop var.

  • Seeding avoids re-visiting this on cyclic exports (you already handle cycles; this just reduces redundant visitor calls).
  • Rename import to exported for accuracy.
   final visitedLibraries = <LibraryElement2>{};
+  // Avoid re-visiting `this` via cycles.
+  visitedLibraries.add(this);
   LibraryElement2? visitLibrary(LibraryElement2 library) {
@@
-    for (final import in exportedLibraries2) {
-      final result = visitLibrary(import);
+    for (final exported in exportedLibraries2) {
+      final result = visitLibrary(exported);
       if (result != null) return result;
     }

Also applies to: 23-23


15-18: Optional: consider BFS to prevent deep recursion.

A queue-based traversal avoids stack overflows on very deep export graphs. Current DFS is fine for typical SDK/plugin sizes.


3-3: Rename extension LibraryHasImport to LibraryExportTraversal
No other occurrences of LibraryHasImport were found outside its own declaration; it’s safe to apply the diff.

packages/freezed/test/decorator_test.dart (2)

36-37: Prefer element.name3 directly; library2 is redundant here.

element is already a library; accessing library2 adds noise.

-          (element) => element.library2.name3 == 'decorator',
+          (element) => element.name3 == 'decorator',

99-118: Stabilize expectations: ignore ordering of errors.

Analyzer error ordering can fluctuate. Use unorderedEquals while preserving the two accepted variants.

-    expect(
-      errorResult.errors.map((e) => e.errorCode.name),
-      anyOf([
-        [
+    final names = errorResult.errors.map((e) => e.errorCode.name).toList();
+    expect(
+      names,
+      anyOf([
+        unorderedEquals([
           'UNUSED_RESULT',
           'UNUSED_RESULT',
           'DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE',
           'DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE',
           'DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE',
           'DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE',
-        ],
-        [
+        ]),
+        unorderedEquals([
           'UNUSED_RESULT',
           'UNUSED_RESULT',
           'DEPRECATED_MEMBER_USE',
           'DEPRECATED_MEMBER_USE',
           'DEPRECATED_MEMBER_USE',
           'DEPRECATED_MEMBER_USE',
-        ],
+        ]),
       ]),
     );
packages/freezed/test/multiple_constructors_test.dart (1)

47-49: Reduce repetition for getField2(...).type.getDisplayString().

Minor: a local helper/extension would DRY these assertions and ease future API shifts.

Example:

extension on ClassElement2 {
  String fieldTypeDisplay(String name) =>
      getField2(name)!.type.getDisplayString();
}

Also applies to: 577-579, 586-588, 593-595, 603-605, 612-614, 619-621, 630-632, 634-636, 638-640, 642-644

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b02955c and 706678a.

📒 Files selected for processing (30)
  • analysis_options.yaml (1 hunks)
  • packages/freezed/lib/src/ast.dart (3 hunks)
  • packages/freezed/lib/src/models.dart (26 hunks)
  • packages/freezed/lib/src/parse_generator.dart (3 hunks)
  • packages/freezed/lib/src/templates/concrete_template.dart (2 hunks)
  • packages/freezed/lib/src/templates/parameter_template.dart (4 hunks)
  • packages/freezed/lib/src/templates/properties.dart (3 hunks)
  • packages/freezed/lib/src/templates/prototypes.dart (2 hunks)
  • packages/freezed/lib/src/tools/imports.dart (1 hunks)
  • packages/freezed/lib/src/tools/recursive_import_locator.dart (7 hunks)
  • packages/freezed/lib/src/tools/type.dart (4 hunks)
  • packages/freezed/pubspec.yaml (1 hunks)
  • packages/freezed/test/bidirectional_test.dart (1 hunks)
  • packages/freezed/test/common.dart (3 hunks)
  • packages/freezed/test/common_types_test.dart (1 hunks)
  • packages/freezed/test/decorator_test.dart (3 hunks)
  • packages/freezed/test/deep_copy_test.dart (3 hunks)
  • packages/freezed/test/generic_test.dart (1 hunks)
  • packages/freezed/test/generics_refs_test.dart (1 hunks)
  • packages/freezed/test/json_test.dart (1 hunks)
  • packages/freezed/test/map_test.dart (2 hunks)
  • packages/freezed/test/multiple_constructors_test.dart (10 hunks)
  • packages/freezed/test/optional_maybe_test.dart (1 hunks)
  • packages/freezed/test/single_class_constructor_test.dart (5 hunks)
  • packages/freezed/test/typedef_parameter_test.dart (2 hunks)
  • packages/freezed/test/when_test.dart (1 hunks)
  • packages/freezed_lint/lib/src/missing_mixin.dart (4 hunks)
  • packages/freezed_lint/lib/src/missing_private_empty_ctor.dart (4 hunks)
  • packages/freezed_lint/lib/src/tools/element_extensions.dart (1 hunks)
  • packages/freezed_lint/pubspec.yaml (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: lishaduck
PR: rrousselGit/freezed#1147
File: packages/freezed_lint/pubspec.yaml:12-12
Timestamp: 2025-01-07T20:51:22.701Z
Learning: The analyzer version update to >=7.0.0 in freezed_lint package is blocked by invertase/dart_custom_lint#300, preventing alignment with freezed package's analyzer requirements.
Learnt from: lishaduck
PR: rrousselGit/freezed#1147
File: packages/freezed_lint/pubspec.yaml:12-12
Timestamp: 2025-01-07T20:51:22.701Z
Learning: The analyzer version upgrade in freezed_lint is blocked by invertase/dart_custom_lint#300 which handles the broader upgrade of analyzer, analyzer_plugin, and source_gen dependencies in custom_lint.
📚 Learning: 2025-01-07T20:51:22.701Z
Learnt from: lishaduck
PR: rrousselGit/freezed#1147
File: packages/freezed_lint/pubspec.yaml:12-12
Timestamp: 2025-01-07T20:51:22.701Z
Learning: The analyzer version upgrade in freezed_lint is blocked by invertase/dart_custom_lint#300 which handles the broader upgrade of analyzer, analyzer_plugin, and source_gen dependencies in custom_lint.

Applied to files:

  • packages/freezed_lint/lib/src/tools/element_extensions.dart
  • packages/freezed_lint/pubspec.yaml
  • packages/freezed/lib/src/templates/concrete_template.dart
  • packages/freezed/pubspec.yaml
  • packages/freezed/lib/src/templates/properties.dart
  • packages/freezed/lib/src/templates/prototypes.dart
  • packages/freezed_lint/lib/src/missing_private_empty_ctor.dart
  • packages/freezed_lint/lib/src/missing_mixin.dart
  • packages/freezed/lib/src/models.dart
  • packages/freezed/lib/src/ast.dart
📚 Learning: 2025-01-07T20:51:22.701Z
Learnt from: lishaduck
PR: rrousselGit/freezed#1147
File: packages/freezed_lint/pubspec.yaml:12-12
Timestamp: 2025-01-07T20:51:22.701Z
Learning: The analyzer version update to >=7.0.0 in freezed_lint package is blocked by invertase/dart_custom_lint#300, preventing alignment with freezed package's analyzer requirements.

Applied to files:

  • packages/freezed_lint/lib/src/tools/element_extensions.dart
  • packages/freezed_lint/pubspec.yaml
  • packages/freezed/lib/src/templates/concrete_template.dart
  • packages/freezed/pubspec.yaml
  • packages/freezed/lib/src/templates/properties.dart
  • packages/freezed_lint/lib/src/missing_private_empty_ctor.dart
  • packages/freezed_lint/lib/src/missing_mixin.dart
  • packages/freezed/lib/src/templates/parameter_template.dart
  • packages/freezed/lib/src/models.dart
  • packages/freezed/lib/src/ast.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: freezed (packages/freezed, stable, get)
🔇 Additional comments (72)
packages/freezed_lint/lib/src/missing_mixin.dart (3)

1-2: Good import split; avoids LintCode clash.

Importing AnalysisError while hiding analyzer’s LintCode is correct so LintCode resolves to custom_lint’s type.


27-27: Using element.name3 is consistent with analyzer v2 elements.

This avoids deprecated accessors and aligns with declaredFragment?.element. Looks good.


17-17: pubspec.yaml’s analyzer: ">=7.5.9 <9.0.0" and custom_lint_builder: ^0.8.0 cover the run(CustomLintResolver, ErrorReporter, CustomLintContext) signature introduced in v0.8.0. (pub.dev)

packages/freezed/lib/src/templates/concrete_template.dart (1)

2-2: Element v2 import: LGTM.

Switching to element2.dart aligns with the v2 element API used across the repo. (pub.dev)

packages/freezed/test/generics_refs_test.dart (1)

24-24: Assert on ErrorsResult.errors: LGTM.

Matches the current analyzer API; errors is the right property. (pub.dev)

packages/freezed/test/optional_maybe_test.dart (1)

24-24: Assert on ErrorsResult.errors: LGTM.

Consistent with the updated analyzer API. (pub.dev)

packages/freezed/test/map_test.dart (1)

306-306: Use errorResult.errors in expectations: LGTM.

Both assertions correctly target the new property. (pub.dev)

Also applies to: 427-427

packages/freezed/test/bidirectional_test.dart (1)

23-23: Assert on ErrorsResult.errors: LGTM.

Aligned with the analyzer API. (pub.dev)

packages/freezed/pubspec.yaml (1)

13-14: Version ranges align across freezed and freezed_lint; no conflicting constraints found.

packages/freezed/test/generic_test.dart (1)

55-55: Assert on ErrorsResult.errors: LGTM.

Correctly updated to the new property. (pub.dev)

packages/freezed/lib/src/templates/prototypes.dart (1)

1-1: Import to element2 looks fine.

No further action.

packages/freezed/test/common.dart (2)

26-28: Correct migration to ErrorsResult.errors + Severity filter.

Looks good.


37-37: Public field type update is consistent.

List<AnalysisError> aligns with the new API.

packages/freezed/test/json_test.dart (1)

755-755: Updated assertion to errors — OK.

packages/freezed/test/when_test.dart (1)

305-305: Updated to errors — OK.

packages/freezed/test/common_types_test.dart (1)

28-28: Updated to errors — OK.

packages/freezed_lint/lib/src/tools/element_extensions.dart (2)

1-1: element2 import is consistent with the migration.


8-11: Ensure min analyzer in range exposes constructors2.

Given the widened constraint (>=7.5.9 <9.0.0), verify ClassElement2.constructors2 exists across the range. Consider adding CI that resolves deps at both the minimum and latest to guard this.

I can propose a CI matrix step to test min/max dependency resolutions if helpful.

packages/freezed/test/deep_copy_test.dart (3)

34-34: errors isEmpty assertion — OK.


52-52: errors isEmpty assertion — OK.


737-741: Mapping to errorCode.name — OK; confirm code stability across range.

UNUSED_RESULT name should remain consistent across analyzer versions in your range.

If needed, I can add a test guard that accepts both historic and new spellings.

packages/freezed_lint/pubspec.yaml (2)

14-14: custom_lint_builder ^0.8.0 compatibility.

Double-check custom_lint_builder and analyzer_plugin compatibility with analyzer up to <9.0.0 to avoid resolution conflicts.


18-18: custom_lint ^0.8.0 downgrade — verify still supports analyzer >=7.5.9.

If not, consider pinning with an upper bound or bumping to a compatible minor.

packages/freezed/lib/src/parse_generator.dart (1)

6-6: Import migration looks correct.

Switch to element2.dart aligns with the analyzer v2 API.

packages/freezed/test/typedef_parameter_test.dart (2)

24-24: LGTM: updated to ErrorsResult.errors.

Matches the analyzer API change from diagnostics to errors.


48-66: LGTM: element2/name3 alias assertions.

The updated alias accessors and name3 expectations look consistent with the v2 API.

packages/freezed/lib/src/templates/parameter_template.dart (3)

14-18: LGTM: migrate generics definition to TypeParameterElement2 + displayString2().


39-42: LGTM: migrate generics parameter list to TypeParameterElement2 + name3.


72-80: parseDecorators usage is correct: it expects a List and metadata2.annotations already provides that.

packages/freezed/lib/src/templates/properties.dart (4)

2-2: Import migration to element2 looks correct.


54-64: Guard against potential null name3 during recovery.
In rare parser-recovery/synthetic cases, element.name3 could be null. Consider a safe fallback to avoid a crash.

Would you prefer a defensive fallback like parameter.name if available, or keep the hard fail?


61-61: metadata2 migration LGTM.
Usage of metadata2.annotations aligns with v2 API.


117-118: Ignore internal template change (no public API impact)
This update to TypeParameterElement2? parameterElement lives in the code‐generator’s internal template and isn’t exposed to users—no external or exported call-sites are affected.

Likely an incorrect or invalid review comment.

packages/freezed/lib/src/tools/type.dart (4)

27-37: Element lookup migration is correct.
InterfaceType.element3 and FunctionType.alias?.element2 are the right replacements.


87-91: Dynamic type retrieval via element3.library2 is fine.
Assuming type.element3 is available for interface types, this keeps behavior parity.


94-95: Prefix owner rendering migration LGTM.
owner.name3 is the correct accessor.


42-42: The diff in callers all use the updated LibraryElement2‐based API (e.g. passing .library2), and tools/type.dart isn’t publicly re-exported from lib/—it lives under lib/src. No public API broke.

packages/freezed_lint/lib/src/missing_private_empty_ctor.dart (5)

16-17: Severity migration LGTM.
ErrorSeverity.ERROR matches analyzer v2.


32-38: members2/accessors2 migration LGTM.
Correct non-static filtering retained.


41-43: Constructor check is precise.
constructors2 with isPrivate, empty params, and name3 == '_' matches Class._();.


61-63: Fix API migration for fixes LGTM.
Using AnalysisError and List<AnalysisError> aligns with v2.


22-24: Confirmed ErrorReporter support—import atElement2.
Your pubspec.yaml already pins custom_lint_builder: ^0.8.0, which provides the ErrorReporter reporter API; ensure the atElement2 extension is imported so reporter.atElement2(...) resolves.

packages/freezed/test/single_class_constructor_test.dart (2)

3-3: Analyzer v2 migration in tests looks good.

Importing element2 and updating analyze() to return LibraryElement2 aligns with the new API.

Also applies to: 28-40


382-383: Correct switch to ErrorsResult.errors.

Using errors instead of diagnostics matches analyzer >=7.x changes.

packages/freezed/lib/src/tools/imports.dart (1)

31-34: LGTM: helper reads clearly.

Simple wrapper around the finder; no behavior change.

packages/freezed/test/decorator_test.dart (3)

20-20: LGTM: migrated to ErrorsResult.errors.


46-61: LGTM: v2 API updates (fields2, name3, metadata2, getter2).

Assertions read cleanly and match the new analyzer surface.


57-61: LGTM: metadata assertions reflect new annotation API.

packages/freezed/test/multiple_constructors_test.dart (7)

5-5: LGTM: switch to element2.dart.


26-28: LGTM: helper uses ClassElement2 + name3.

Reads well and centralizes lookups.


40-41: LGTM: getField2(...).type interface-type assertion is correct.


66-71: LGTM: migrated accessors (getters, PropertyAccessorElement2, name3).

Also applies to: 74-81


85-99: LGTM: fields2/name3 doc assertions look consistent with v2.

Also applies to: 102-117


184-185: LGTM: ErrorsResult.errors check.


1-1: Cross-package analyzer range sanity check complete.

  • Both packages/freezed and packages/freezed_lint now require analyzer: ">=7.5.9 <9.0.0".
  • packages/freezed_lint pins custom_lint: ^0.8.0; confirm that this version supports the analyzer range and that CI resolves a consistent pub-get across all packages.
packages/freezed/lib/src/models.dart (17)

7-7: LGTM!

The import change from element.dart to element2.dart correctly aligns with the Dart analyzer v2 migration.


30-30: LGTM!

The extension targets are correctly updated to use Element2 and ConstructorElement2 types from the analyzer v2 API.

Also applies to: 39-39


41-41: LGTM!

The migration from name to name3 is correct. The name3 property is the v2 API equivalent for accessing element names.

Also applies to: 54-54


100-101: LGTM!

The updates correctly migrate to v2 API:

  • element3 for accessing interface type elements
  • ClassElement2 for class element types
  • name3 for accessing element names

Also applies to: 119-119, 122-122


272-272: LGTM!

The change from name to name2 for the NamedType is correct, aligning with the analyzer v2 API for AST node names.


286-286: LGTM!

The use of name3 for accessing element names is correctly applied to parameter elements.


321-321: LGTM!

The migration to element2 for accessing annotation elements and library2 for library references follows the v2 API convention.


427-427: LGTM!

The changes correctly update method signatures and implementations:

  • ConstructorElement2 parameter types in static helpers
  • library2 for library element access
  • metadata2.annotations for accessing metadata in v2 API

Also applies to: 439-439, 454-454, 456-456, 466-466


525-525: LGTM!

The change from name to name2 for NamedType is consistent with the analyzer v2 API for AST nodes.


555-555: LGTM!

The library getter signature correctly returns LibraryElement2 as part of the v2 API migration.


573-573: LGTM!

The migrations correctly use v2 API equivalents:

  • fields2 for accessing class fields
  • name3 for field names
  • typeParameters2 for type parameters

Also applies to: 679-680, 683-683, 686-686


748-748: LGTM!

The change from name to name2 for accessing AST node names is correct.


836-836: LGTM!

The use of metadata2.annotations for accessing metadata correctly follows the v2 API pattern.


865-865: LGTM!

All library and type system references are correctly updated to use library2 from the v2 API.

Also applies to: 867-867, 921-921, 967-967


1064-1064: LGTM!

The field access methods are correctly migrated:

  • FieldElement2 type
  • setter2 and getter2 properties for accessors
  • Consistent use of v2 API naming conventions

Also applies to: 1069-1080


1132-1132: LGTM!

The library imports checking correctly uses library2 for accessing library elements.

Also applies to: 1135-1135


1360-1364: LGTM!

The extension on LibraryElement2 correctly uses:

  • name3 for element names
  • library2 for library references
  • Proper null-safe navigation with the v2 API

Also applies to: 1370-1371

Comment on lines 34 to 36
final mixins = withClause.mixinTypes;
if (mixins.any((m) => name == m.name.lexeme)) return;
if (mixins.any((m) => name == m.name2.lexeme)) return;
reporter.atElement2(element, _code, arguments: [name]);
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Potential API mismatch: m.name2.lexeme may not exist depending on analyzer; prefer name2.name.

On recent analyzer versions, NamedType.name2 is an Identifier whose stable string is name, not lexeme. Using lexeme can fail or be less future-proof. Consider switching to name2.name.

Apply:

-      if (mixins.any((m) => name == m.name2.lexeme)) return;
+      if (mixins.any((m) => name == m.name2.name)) return;

To confirm usage across the repo:


🏁 Script executed:

#!/bin/bash
rg -nP --type=dart -C1 '\.name2\.(lexeme|name)\b'

Length of output: 753


Replace .name2.lexeme with .name2.name across all occurrences

  • packages/freezed_lint/lib/src/missing_mixin.dart:35
  • packages/freezed/lib/src/models.dart:272, 748

Apply these diffs:

--- a/packages/freezed_lint/lib/src/missing_mixin.dart
+++ b/packages/freezed_lint/lib/src/missing_mixin.dart
@@ -34,7 +34,7 @@
       final mixins = withClause.mixinTypes;
-      if (mixins.any((m) => name == m.name2.lexeme)) return;
+      if (mixins.any((m) => name == m.name2.name)) return;
       reporter.atElement2(element, _code, arguments: [name]);
--- a/packages/freezed/lib/src/models.dart
+++ b/packages/freezed/lib/src/models.dart
@@ -270,7 +270,7 @@
       final redirectedName =
-          constructor.redirectedConstructor?.type.name2.lexeme;
+          constructor.redirectedConstructor?.type.name2.name;
--- a/packages/freezed/lib/src/models.dart
+++ b/packages/freezed/lib/src/models.dart
@@ -745,7 +745,7 @@
         ...?clazz._node.withClause?.mixinTypes,
-      ].map((e) => e.name2.lexeme);
+      ].map((e) => e.name2.name);

Verify no remaining instances:

rg -nP --type=dart '\.name2\.lexeme'
🤖 Prompt for AI Agents
In packages/freezed_lint/lib/src/missing_mixin.dart around lines 34–36 (and
similarly in packages/freezed/lib/src/models.dart at lines ~272 and ~748),
change usages of `.name2.lexeme` to `.name2.name` so the code accesses the
token's name property instead of lexeme; update each occurrence to use
`.name2.name`, run the provided search command (rg -nP --type=dart
'\.name2\.lexeme') to ensure no remaining instances, and run tests/linting to
confirm nothing else breaks.

Comment on lines +73 to 76
final className = classElement.enclosingElement2.name3;

return name == null ? '$className$generics' : '$className$generics.$name';
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Bug: Using library name instead of class name in fullName.

className should come from the class element, not its enclosing library.

Apply this diff:

-    final className = classElement.enclosingElement2.name3;
+    final className = classElement.name3!;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
final className = classElement.enclosingElement2.name3;
return name == null ? '$className$generics' : '$className$generics.$name';
}
final className = classElement.name3!;
return name == null ? '$className$generics' : '$className$generics.$name';
🤖 Prompt for AI Agents
In packages/freezed/lib/src/ast.dart around lines 73 to 76, fullName is
incorrectly using the enclosing element's name (library) as className; replace
the use of classElement.enclosingElement2.name3 with the class element's own
name (classElement.name) so fullName uses the actual class name when composing
'$className$generics' or '$className$generics.$name'.

Comment on lines 76 to 79
final Object? ast = unit.unit.declarations.firstWhereOrNull(
(declaration) =>
declaration.declaredFragment?.element.name == element.name!,
declaration.declaredFragment?.element.name3 == element.name3!,
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Match elements by identity, not by (possibly-null) name.

Comparing name3 risks a null bang on unnamed elements. Use element identity for robustness.

-    final Object? ast = resolvedUnit.unit.declarations.firstWhereOrNull(
-      (declaration) =>
-          declaration.declaredFragment?.element.name3 == element.name3!,
-    );
+    final Object? ast = resolvedUnit.unit.declarations.firstWhereOrNull(
+      (declaration) => declaration.declaredFragment?.element == element,
+    );

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/freezed/lib/src/parse_generator.dart around lines 76-79, the code
matches declarations by comparing declaration.declaredFragment?.element.name3 to
element.name3!, which can NPE on unnamed elements; change the predicate to
compare element identity instead (e.g., compare element ==
declaration.declaredFragment?.element or element ==
declaration.declaredElement), remove the null-bang, and keep the
firstWhereOrNull call so unnamed elements are handled safely.

Comment on lines +44 to 46
bool isDefaultConstructor(ConstructorElement2 constructor) {
return constructor.name3 == 'new';
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Default-ctor detection via string 'new' is brittle; handle both unnamed forms.

Some analyzer versions expose the unnamed constructor as '' (empty), others as 'new'. Comparing to 'new' only risks misclassification.

Apply this for robustness:

-bool isDefaultConstructor(ConstructorElement2 constructor) {
-  return constructor.name3 == 'new';
-}
+bool isDefaultConstructor(ConstructorElement2 constructor) {
+  final n = constructor.name3;
+  return n.isEmpty || n == 'new';
+}

If ConstructorElement2 offers a boolean for unnamed/default, prefer that instead (e.g., isDefaultConstructor / isNamedConstructor). Would you like me to adjust if confirmed?


🏁 Script executed:

#!/bin/bash
set -eux

echo "Snippet around isDefaultConstructor:"
rg -n "isDefaultConstructor" -C3 packages/freezed/lib/src/templates/prototypes.dart || true

echo "Imports in file:"
sed -n '1,20p' packages/freezed/lib/src/templates/prototypes.dart || true

echo "Search for name3 usage:"
rg -n "name3" -C3 packages/freezed/lib/src/templates/prototypes.dart || true

Length of output: 1329


Use the built‐in isDefaultConstructor instead of manual string checks.

Replace the name3 comparison with the API’s boolean:

-bool isDefaultConstructor(ConstructorElement2 constructor) {
-  return constructor.name3 == 'new';
-}
+bool isDefaultConstructor(ConstructorElement2 constructor) {
+  return constructor.isDefaultConstructor;
+}
```([pub.dev](https://pub.dev/documentation/analyzer/latest/dart_element_element2/ConstructorElement2-class.html))

<details>
<summary>🤖 Prompt for AI Agents</summary>

In packages/freezed/lib/src/templates/prototypes.dart around lines 44–46, the
code checks for a default constructor by comparing constructor.name3 == 'new';
replace this manual string check with the built-in boolean property by using
constructor.isDefaultConstructor instead (update the conditional accordingly).
Ensure any related logic expecting the old check still works with the boolean
API and run tests/linting to confirm no further adjustments are needed.


</details>

<!-- fingerprinting:phantom:poseidon:chinchilla -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +31 to 32
yield* children2;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Yielding library.children2 likely returns units, not top-level elements.

Return top-level declarations from each compilation unit instead.

Apply this diff:

-    yield* children2;
+    for (final unit in fragments) {
+      // CompilationUnitElement2.children2 are the unit's top-level elements.
+      yield* unit.children2;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
yield* children2;
// Instead of yielding the units themselves...
// ...iterate each compilation unit fragment and yield its top‐level elements.
for (final unit in fragments) {
// CompilationUnitElement2.children2 are the unit's top‐level declarations.
yield* unit.children2;
}
🤖 Prompt for AI Agents
In packages/freezed/lib/src/tools/recursive_import_locator.dart around lines
31-32, the code currently does "yield* children2;" which yields compilation
units rather than top-level declarations; replace that with iterating over each
compilation unit in children2 and yield its top-level declarations (e.g., for
each unit in children2 do "yield* unit.declarations") so the stream returns
top-level members instead of units.

Comment on lines 55 to 60
return (directive.showStatements.isEmpty &&
directive.hideStatements.isEmpty) ||
(directive.hideStatements.isNotEmpty &&
!directive.hideStatements.contains(element.name)) ||
directive.showStatements.contains(element.name);
!directive.hideStatements.contains(element.name3)) ||
directive.showStatements.contains(element.name3);
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Show/hide combinator logic is incorrect (OR vs AND).

When both are present, result must be (in show OR show is empty) AND not in hide.

Apply this diff:

-          .where((element) {
-            return (directive.showStatements.isEmpty &&
-                    directive.hideStatements.isEmpty) ||
-                (directive.hideStatements.isNotEmpty &&
-                    !directive.hideStatements.contains(element.name3)) ||
-                directive.showStatements.contains(element.name3);
-          });
+          .where((element) {
+            final name = element.name3;
+            if (name == null) return false;
+            final show = directive.showStatements;
+            final hide = directive.hideStatements;
+            final shown = show.isEmpty || show.contains(name);
+            final notHidden = !hide.contains(name);
+            return shown && notHidden;
+          });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (directive.showStatements.isEmpty &&
directive.hideStatements.isEmpty) ||
(directive.hideStatements.isNotEmpty &&
!directive.hideStatements.contains(element.name)) ||
directive.showStatements.contains(element.name);
!directive.hideStatements.contains(element.name3)) ||
directive.showStatements.contains(element.name3);
});
.where((element) {
final name = element.name3;
if (name == null) return false;
final show = directive.showStatements;
final hide = directive.hideStatements;
final shown = show.isEmpty || show.contains(name);
final notHidden = !hide.contains(name);
return shown && notHidden;
});
🤖 Prompt for AI Agents
In packages/freezed/lib/src/tools/recursive_import_locator.dart around lines 55
to 60, the combinator logic uses ORs causing incorrect results when both show
and hide are present; replace the current condition with one that requires (show
is empty OR show contains the symbol) AND the symbol is not in hide. Concretely,
change the predicate to ensure directive.showStatements.isEmpty ||
directive.showStatements.contains(element.name3) is combined with &&
!directive.hideStatements.contains(element.name3), preserving the existing
checks for empty hide/show lists.

Comment on lines +45 to 47
return l.importedLibrary2!.anyTransitiveExport((library) {
return library.id == _getElementForType(type)?.library2?.id;
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential NPE on importedLibrary2.
l.importedLibrary2! can be null for unresolved/conditional imports, causing crashes.

Apply:

-      return l.importedLibrary2!.anyTransitiveExport((library) {
-        return library.id == _getElementForType(type)?.library2?.id;
-      });
+      final imported = l.importedLibrary2;
+      if (imported == null) return false;
+      return imported.anyTransitiveExport(
+        (library) => library.id == _getElementForType(type)?.library2?.id,
+      );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return l.importedLibrary2!.anyTransitiveExport((library) {
return library.id == _getElementForType(type)?.library2?.id;
});
final imported = l.importedLibrary2;
if (imported == null) return false;
return imported.anyTransitiveExport(
(library) => library.id == _getElementForType(type)?.library2?.id,
);
🤖 Prompt for AI Agents
In packages/freezed/lib/src/tools/type.dart around lines 45 to 47, the code
force-unwraps l.importedLibrary2 which can be null for unresolved or conditional
imports; guard against that by checking for null before calling
anyTransitiveExport — either use a null-aware call with a fallback (e.g.
l.importedLibrary2?.anyTransitiveExport(...) ?? false) or assign
l.importedLibrary2 to a local variable and return false if it is null, then call
anyTransitiveExport when non-null.

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