fix(theme): tolerate unknown spacing tokens instead of throwing#156
Conversation
Unknown theme-spacing tokens like p-primary, m-foo, top-abc, or gap-x-blue currently throw ArgumentError: Invalid spacing multiplier inside build(), producing a red screen. That violates the parser contract (wind_parser.dart:369, unknown className is dropped with a debug warning) that other parsers already follow — sizing_parser already pre-validates with double.tryParse. Adds a non-throwing WindThemeData.tryGetSpacing sibling and switches the four throwing callers (padding, margin, position, flex-gap) to use it and skip on null. getSpacing is retained unchanged for backward compatibility.
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughUnknown theme-spacing tokens now resolve to ChangesTheme spacing token handling
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Remove the duplicated full/container/numeric branches: getSpacing now delegates to tryGetSpacing and throws only when it returns null. Behavior is identical (full -> infinity, container lookup, numeric parse, ArgumentError on unknown), so backward compatibility holds and the single source of truth removes the drift risk between the two lookups. Also drop an em-dash from the tryGetSpacing docstring to match the repo convention.
anilcancakir
left a comment
There was a problem hiding this comment.
Thanks for the thorough writeup, @thejesh23. The diagnosis is exactly right: getSpacing throwing inside build() violates the "unknown className is dropped with a debug warning" contract that wind_parser.dart and the sibling sizing_parser already honor, and a color-name typo like p-primary producing a red screen is a real trap.
I verified the fix end to end on a maintainer machine (the CI-equivalent Definition of Done gate you could not run locally):
dart analyze(lib + test): no issues.dart format --set-exit-if-changed: 0 changed.flutter test: 1671 pass, 1 pre-existing skip../tool/coverage.sh 90: 94.6%, above the 90% floor.
A few things I checked beyond the four listed callers:
- Completeness. The other two
getSpacingcallers,sizing_parser.dartandtext_parser.dart(line-height branch), both pre-validate withdouble.tryParsebefore calling, so they were already safe. No crash site is left behind. - No silent regression.
tryGetSpacingmirrorsgetSpacingbyte for byte except for the throw, and the fraction case (p-1/2) was already going through thedouble.tryParse-> null -> throw path before this PR, so nothing that used to resolve now silently drops. - Regression tests are genuine. Before the fix
parser.parse(...)threw, so each newreturnsNormallyassertion fails on the old code and passes on the new one.
I pushed one follow-up commit on top (refactor(theme): fold getSpacing into tryGetSpacing): getSpacing now delegates to tryGetSpacing and throws only when it returns null, instead of keeping a parallel copy of the full/container/numeric branches. Behavior is identical and backward compatibility holds, it just removes the drift risk between the two lookups. I also dropped an em-dash from the tryGetSpacing docstring to match the repo's punctuation convention. Both stay within your intent of keeping getSpacing's observable behavior unchanged.
Approving. Thank you for the clean, well-tested contribution.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR fixes a runtime crash where spacing-related utility parsers could throw ArgumentError during build() when given unknown (often typo) tokens like p-primary or gap-x-blue. It introduces a non-throwing spacing lookup on WindThemeData and updates the affected parsers to drop unknown spacing tokens instead of crashing, aligning behavior with Wind’s “unknown tokens are ignored” contract.
Changes:
- Added
WindThemeData.tryGetSpacing(String)(returnsnullfor unrecognized tokens) and refactoredgetSpacingto delegate to it while preserving existing throwing behavior. - Updated padding, margin, position, and flex-gap parsing to use
tryGetSpacingso unknown spacing tokens no-op instead of throwing. - Added targeted regression tests ensuring unknown spacing tokens do not throw, and documented the fix in
CHANGELOG.md.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
lib/src/theme/wind_theme_data.dart |
Adds tryGetSpacing and refactors getSpacing to share logic while keeping getSpacing’s throwing contract. |
lib/src/parser/parsers/padding_parser.dart |
Switches theme spacing resolution to tryGetSpacing to safely ignore unknown padding tokens. |
lib/src/parser/parsers/margin_parser.dart |
Switches theme spacing resolution to tryGetSpacing to safely ignore unknown margin tokens. |
lib/src/parser/parsers/position_parser.dart |
Switches theme spacing resolution to tryGetSpacing to safely ignore unknown offset tokens. |
lib/src/parser/parsers/flexbox_grid_parser.dart |
Switches gap theme spacing resolution to tryGetSpacing to safely ignore unknown gap tokens. |
test/theme/wind_theme_data_test.dart |
Adds tests asserting tryGetSpacing matches getSpacing for valid inputs and returns null for unknown tokens. |
test/parser/parsers/padding_parser_test.dart |
Adds regression test ensuring unknown padding tokens don’t throw and don’t apply padding. |
test/parser/parsers/margin_parser_test.dart |
Adds regression test ensuring unknown margin tokens don’t throw and don’t apply margin. |
test/parser/parsers/position_parser_test.dart |
Adds regression test ensuring unknown position tokens don’t throw and don’t apply offsets. |
test/parser/parsers/flexbox_grid_parser_test.dart |
Adds regression test ensuring unknown gap tokens don’t throw and don’t apply gaps. |
CHANGELOG.md |
Documents the behavior change under [Unreleased] > Fixed. |
Patch release: three bug fixes since 1.2.0. Unknown theme-spacing tokens (`p-primary`, `m-foo`, `top-abc`, `gap-x-blue`) now drop instead of throwing `ArgumentError` inside `build()` (#156); `WAnchor` hit-tests its whole bounds via `HitTestBehavior.translucent` so transparent-content anchors are fully tappable (#152); `WPopover` no longer flickers open-then-closed on the first web trigger tap and its menu items respond on the first open (#157). Bump pubspec.yaml 1.2.0 -> 1.2.1 and promote ## [Unreleased] to ## [1.2.1] - 2026-07-21 in CHANGELOG.md, with the [1.2.1] link reference and the [Unreleased] compare link redirected to 1.2.1...HEAD. Sync example/pubspec.yaml, dartdoc_options.yaml source-link tag, and the llms.txt version string to 1.2.1.
Patch release: three bug fixes since 1.2.0. Unknown theme-spacing tokens (`p-primary`, `m-foo`, `top-abc`, `gap-x-blue`) now drop instead of throwing `ArgumentError` inside `build()` (#156); `WAnchor` hit-tests its whole bounds via `HitTestBehavior.translucent` so transparent-content anchors are fully tappable (#152); `WPopover` no longer flickers open-then-closed on the first web trigger tap and its menu items respond on the first open (#157). Bump pubspec.yaml 1.2.0 -> 1.2.1 and promote ## [Unreleased] to ## [1.2.1] - 2026-07-21 in CHANGELOG.md, with the [1.2.1] link reference and the [Unreleased] compare link redirected to 1.2.1...HEAD. Sync example/pubspec.yaml, dartdoc_options.yaml source-link tag, and the llms.txt version string to 1.2.1.
Fixes #155
Summary
WindThemeData.getSpacingthrowsArgumentErrorfor anymultiplierthat isn't'full', a container key, or numeric. The padding, margin, position, and flex-gap parsers each pass the raw regex-captured value directly, so tokens likep-primary,m-foo,top-abc,gap-x-blue— natural typos after usingbg-primary/text-primary— throw at build time and produce a red screen. This violates the parser contract atwind_parser.dart:369(unknown className is dropped with a debug warning); the siblingsizing_parser.dartalready pre-validates withdouble.tryParse.Adds
WindThemeData.tryGetSpacing(String)— same behaviour asgetSpacingbut returnsnullfor unrecognised tokens. Switches the four throwing callers to use it and drop the token via their existingif (value == null) continue;guards.getSpacingis unchanged.Definition of done
dart analyze— please run in CI (no toolchain on audit machine).dart format .— please run in CI.flutter test— added coverage:-
test/theme/wind_theme_data_test.dart—tryGetSpacingmatchesgetSpacingfor known tokens; returnsnullfor unknown.-
test/parser/parsers/padding_parser_test.dart—p-primary/mx-foo/py-barno longer throw.-
test/parser/parsers/margin_parser_test.dart—m-primary/mx-foo/my-barno longer throw.-
test/parser/parsers/position_parser_test.dart—top-abc/left-foo/inset-x-barno longer throw.-
test/parser/parsers/flexbox_grid_parser_test.dart—gap-blue/gap-x-primary/gap-y-foono longer throw../tool/coverage.sh 90— newtryGetSpacingis fully exercised and each patched parser gains a dedicated test, so coverage should hold at ≥ 90 %. Please confirm in CI.Post-change sync
This is a pure defect fix; no new widget/parser/token/theme field is added.
doc/,example/lib/pages/,skills/wind-ui/, andREADME.mdare unchanged per the guidance. CHANGELOG updated under[Unreleased] > Fixed.Notes
I could not run
flutter test/dart analyze/dart formatlocally (no Flutter toolchain on the audit machine). Please rely on CI. All edits were made against HEADaa07198and follow the parser conventions in.github/instructions/parsers.instructions.md.Summary by CodeRabbit
Bug Fixes
full.Tests
Documentation