Skip to content

feat: add class-model helpers for code generators (1.4.0) - #78

Merged
kevmoo merged 4 commits into
mainfrom
class-model
Oct 19, 2026
Merged

kevmoo merged 4 commits into
mainfrom
class-model

Conversation

@kevmoo

@kevmoo kevmoo commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Add shared analyzer class-model helpers used across json_serializable, build_cli, codable_builder, and go_router_builder, plus two additions on DartTypeExtension:

  • Field set & property annotations:
    • createSortedFieldSet(InterfaceElement, {scope, includeSetterOnly, keepObjectMemberOverride}) and InheritedMemberScope (concrete, all) using public InterfaceElement.inheritedConcreteMembers / inheritedMembers (no analyzer/src/... imports).
    • fieldOverrideChain(InterfaceElement, FieldElement) returning [field, ...overridden super fields] in inheritance order as a pure function of the element model.
    • firstAnnotationOnProperty(InterfaceElement, String, TypeChecker) walking each property's field and getter across its override chain by name.
  • Constructor planning & type parameters:
    • constructorByName(InterfaceElement, String) ('' selects the unnamed constructor; throws InvalidGenerationSourceError when missing).
    • planConstruction(ConstructorElement, Set<String>) returning ConstructorPlan (constructor, positional, named, unmatched, consumedNames), keeping unmatched positional parameters in positional so callers cannot shift subsequent positional argument slots.
    • typeParameterListCode(InterfaceElement, {required bool withBounds}).
  • Tear-off & DartType helpers:
    • ExecutableElementExtension.qualifiedName (fn, Class.method, Class, Class.named).
    • DartTypeExtension.toStringNonNullable() and DartTypeExtension.enumConstants.
  • Constraints & verification:
    • Requires analyzer: '>=10.1.0 <15.0.0' (isOriginGetterSetter, isOriginDeclaringFormalParameter, and non-experimental declaringFormalParameter) and source_gen: ^4.1.2.
    • Verified with lower_bound (✓ analyzer 10.1.0, ✓ source_gen 4.1.2) and 71 new resolver-based tests (92 total).

Moves the field-set and constructor-planning logic that json_serializable,
build_cli, codable_builder and go_router_builder each carry a copy of into
source_helper, behind `@experimental`:

- `createSortedFieldSet` with `InheritedMemberScope`, `fieldOverrideChain`
  and `firstAnnotationOnProperty`.
- `constructorByName`, `planConstruction` / `ConstructorPlan` and
  `typeParameterListCode`.
- `ExecutableElementExtension.qualifiedName`.

Stable additions to `DartTypeExtension`: `toStringNonNullable()` and
`enumConstants`.

Requires `analyzer >=10.1.0` (`isOriginGetterSetter`,
`isOriginDeclaringFormalParameter`; `declaringFormalParameter` is still
`@experimental` in 10.0.0) and adds `meta`. Resolver-based tests cover
every new symbol plus the previously untested `DartTypeExtension`.
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Package publishing

If you have publishing permissions, you can use the links below to publish the changes after merging this PR.

Package Version Status Publish tag (post-merge)
package:source_helper ⭐ 1.4.0 ready to publish v1.4.0

Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

@coveralls

coveralls commented Oct 19, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 99.51% (+37.7%) from 61.818% — class-model into main

@kevmoo
kevmoo requested a review from davidmorgan October 19, 2026 05:49

@davidmorgan davidmorgan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks. constructorByName, planConstruction, typeParameterListCode, enumConstants and toStringNonNullable look good, and a two-level override chain Base/Middle/Leaf correctly finds the annotation on Base.

The main issue is how the override chain is built in _overrideChains: it is seeded from inheritedConcreteMembers and then extended from allSupertypes, and neither gives override order. That causes the chain comments below on missing and wrong annotations.

Comment thread lib/src/field_set.dart Resolved
Comment thread lib/src/field_set.dart Resolved
@kevmoo
kevmoo merged commit 7435111 into main Oct 19, 2026
11 checks passed
@kevmoo
kevmoo deleted the class-model branch October 19, 2026 17:54
kevmoo added a commit to kevmoo/codable.dart that referenced this pull request Oct 19, 2026
…uilder (#102)

Adopts the shared constructor, property-annotation, enum, and
nullability helpers published in [`package:source_helper`
`1.4.0`](google/source_helper.dart#78).

- Adds `source_helper: ^1.4.0` to `pkgs/codable_builder/pubspec.yaml`.
- Replaces local `constructorByName`, `firstAnnotationOnProperty`,
`DartType.enumConstants`, and `DartType.isNullableType` helpers across
`model_visitor.dart`, `type_helper.dart`, `encoder_helper.dart`, and
`decoder_helper.dart`.
- Inherits `@CodableKey` and `@CodableTuple` annotations from overridden
superclass and superinterface properties (`firstAnnotationOnProperty`).
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Oct 19, 2026
… ^1.4.0 (#13337)

Fixes flutter/flutter#194817

Adopts shared analyzer helpers published in [`package:source_helper` `1.4.0`](google/source_helper.dart#78) to replace local copies in `go_router_builder`:

- Bumps `source_helper` constraint to `^1.4.0` and `go_router_builder` to `4.5.2`.
- Replaces local `ExecutableElement.qualifiedName`, `withoutNullability` / `_isNullableType`, and `isEnumConstant` filtering across `type_helpers.dart`, `route_config.dart`, and `go_router_generator.dart` with `ExecutableElement.qualifiedName`, `DartType.toStringNonNullable()`, and `DartType.enumConstants` from `package:source_helper/source_helper.dart`.

Pure internal deduplication; generated code is unchanged (`tool/run_tests.dart` and `example/test/ensure_build_test.dart` pass with zero diffs).

## Pre-Review Checklist

[^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
kevmoo added a commit to kevmoo/scripts.dart that referenced this pull request Oct 20, 2026
Adds an opt-in `--rev-deps` flag to `kscripts pr-check` that validates
touched publishable packages against already-published downstream
consumers on `pub.dev` before a non-major release.

### Why
- Isolated API diffing tools (`dart_apitool`, `api_summary`) classify
adding public top-level symbols or `extension` members as
backwards-compatible minor changes, even when downstream consumers on
`pub.dev` already import the package entrypoint without `show` and
declare colliding extension members
(`ambiguous_extension_member_access`) or top-level helpers
(`ambiguous_import`), as occurred in
google/source_helper.dart#78 (`1.4.0`).
- Validating against downstream `HEAD` branches misses these collisions
when donor helpers have already been deleted on the consumer's feature
branch.

### Non-Obvious Callouts
- Default `pr-check` runs make zero network calls and record `Skipped:
rev-deps:<pkg> (pass --rev-deps to run)` when a publishable package
modifies `lib/` in a non-major release
(`VersionConstraint.compatibleWith(baseRelease).allows(targetRelease)`).
- When `--rev-deps` is passed, `pr-check` queries `pub.dev`
(`dependency:<pkg>` and `dependency:<pkg> publisher:kevmoo.com`) plus
`~/.pub-cache/hosted/pub.dev`, unpacks each compatible consumer via
`dart pub unpack <consumer> --no-resolve`, strips
`analysis_options.yaml`, `resolution`, `workspace`, and
`dev_dependencies` via `YamlEditor`, writes `pubspec_overrides.yaml`
pointing `<pkg>` to the local checkout, and runs `dart pub get` + `dart
analyze lib`.

### Verification
- Verified against `source_helper` `1.4.0`: `[email protected]`
fails `dart analyze lib` with `11` real compile errors
(`ambiguous_import` on `constructorByName` / `createSortedFieldSet` and
`ambiguous_extension_member_access` on `toStringNonNullable` /
`qualifiedName`), while `[email protected]`, `[email protected]`,
and `[email protected]` pass cleanly.
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.

3 participants