Skip to content

fix(hir): error on widget method-chain modifier syntax (closes #195)#201

Merged
proggeramlug merged 1 commit into
mainfrom
fix-195-method-chain-modifier-diagnostic
Apr 26, 2026
Merged

fix(hir): error on widget method-chain modifier syntax (closes #195)#201
proggeramlug merged 1 commit into
mainfrom
fix-195-method-chain-modifier-diagnostic

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Summary

  • Option B chosen: reject method-chain modifier syntax at compile time with a clear diagnostic. Option A (fold chain into constructor options-object) was deliberately deferred per the issue guidance — it requires a multi-hundred-line HIR pre-pass.
  • Adds is_widget_modifier_name helper + a ~28-line detection block inside lower_expr's ast::Expr::Member handler.
  • Adds 6 regression tests in crates/perry-hir/tests/widget_modifier_diagnostic.rs.
  • Minimal docs update: rewrites the "Text Modifiers" example in docs/src/widgets/components.md to use the options-object form and adds a one-line note. The larger "Modifiers" section (lines 116–175) examples still show the chained form; updating all of them would exceed ~30 lines — left for a follow-up.

Modifiers recognised

font, fontWeight, weight, foregroundColor, color, foreground, padding, cornerRadius, background, backgroundColor, opacity, lineLimit, frame, minimumScaleFactor, containerBackground, maxWidth, url, bold, italic, underline, fontSize, strikethrough, multilineTextAlignment, lineSpacing

Example error output

error: modifier 'font' must be passed as an option-object on the widget constructor; use: Text("...", { font: ... })

Chained calls fail on the first modifier via natural recursion — processing .color(...) tries to lower the inner Text(...).font(...), which fails, and the error propagates.

Scope / known limitation

The check lives in lower_expr, which is the path for standalone perry/ui code. Method-chain modifiers inside Widget({...}) render bodies (from perry/widget) travel a separate AST-only path (parse_widget_node) that never calls lower_expr, so they still silently drop rather than error there. Fixing that path requires changing parse_render_body_stmts to return Result — deferred as a follow-up.

Test plan

  • cargo test -p perry-hir --test widget_modifier_diagnostic — 6 new tests pass
  • cargo build --release -p perry-runtime -p perry-stdlib -p perry — clean build
  • Full workspace test suite — 0 failures

https://claude.ai/code/session_01Q6AhxeUKokdecgMWrqyzkB


Generated by Claude Code

Method-chain modifier calls like `Text("hi").font("title")` previously
compiled fine but silently dropped every modifier. Option B: reject them
at HIR lowering time with a clear diagnostic so users discover the
supported options-object form.

Adds `is_widget_modifier_name` helper and a detection block in
`lower_expr` (inside the `ast::Expr::Member` handler). When a call's
receiver is a direct `perry/ui` widget constructor call AND the method
name is a known modifier, `Err` is returned:

  modifier 'font' must be passed as an option-object on the widget
  constructor; use: Text("...", { font: ... })

Chained chains (`.font().color()`) fail on the first modifier via
natural recursion — the outer `.color()` processing tries to lower the
inner `Text(...).font(...)`, which fails, and the error propagates.

Modifiers recognised: font, fontWeight, weight, foregroundColor, color,
foreground, padding, cornerRadius, background, backgroundColor, opacity,
lineLimit, frame, minimumScaleFactor, containerBackground, maxWidth, url,
bold, italic, underline, fontSize, strikethrough, multilineTextAlignment,
lineSpacing.

Note: method-chain modifiers inside `Widget({...})` render bodies
(perry/widget, not perry/ui) travel a separate AST-only path
(parse_widget_node) that never calls lower_expr, so they still silently
drop rather than error. Fixing that path would require changing
parse_render_body_stmts to return Result — deferred as a follow-up.

Option A (fold chain into constructor options-object) was deliberately
deferred per the issue guidance.

https://claude.ai/code/session_01Q6AhxeUKokdecgMWrqyzkB
@proggeramlug proggeramlug force-pushed the fix-195-method-chain-modifier-diagnostic branch from 9625268 to 2a6411b Compare April 26, 2026 12:23
@proggeramlug proggeramlug merged commit 56ff5ae into main Apr 26, 2026
1 check passed
@proggeramlug proggeramlug deleted the fix-195-method-chain-modifier-diagnostic branch April 26, 2026 14:20
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