Skip to content

fix(vue): preserve array/object destructuring in v-for without extra parentheses#178

Merged
g-plane merged 2 commits into
g-plane:mainfrom
fabriq:fix-v-for-destructuring
Dec 19, 2025
Merged

fix(vue): preserve array/object destructuring in v-for without extra parentheses#178
g-plane merged 2 commits into
g-plane:mainfrom
fabriq:fix-v-for-destructuring

Conversation

@yacinehmito

Copy link
Copy Markdown
Contributor

Problem

The formatter was incorrectly adding parentheses around destructuring patterns in v-for directives. For example:

  • [key, value] of Object.entries(obj) became ([key, value]) of ...
  • { foo, bar } of items became ({ foo, bar }) of ...

This changes the semantics in Vue templates, where (key, value) is interpreted as Vue's v-for index syntax rather than JavaScript array destructuring.

Cause

The issue was in the format_v_for function which added parentheses whenever the left side contained a comma but no parenthesis:

if left.contains(',') && !left.contains('(') {
    format!("({left}) {delimiter} {right}")
}

This logic didn't account for array destructuring [...] or object destructuring {...} which are already valid grouping constructs.

Solution

The fix checks if the left side starts with [, {, or ( before deciding whether to wrap with parentheses:

let left_trimmed = left.trim_start();
let needs_parens = left.contains(',')
    && !left_trimmed.starts_with('(')
    && !left_trimmed.starts_with('[')
    && !left_trimmed.starts_with('{');

This ensures:

  • Tuple unpacking still gets parentheses: a, i(a, i)
  • Array destructuring is preserved: [key, value] stays as-is
  • Object destructuring is preserved: { foo, bar } stays as-is
  • Mixed patterns work correctly: ([key, value], i) stays as-is

Testing

Added test cases covering:

  • Simple iteration: a in b, a of b
  • Tuple with index: (a, i) in b
  • Array destructuring: [key, value] in Object.entries(obj)
  • Object destructuring: { foo, bar } in items
  • Mixed patterns: ([key, value], i) in Object.entries(obj)

…parentheses

The formatter was incorrectly adding parentheses around destructuring
patterns in v-for directives. For example:

- `[key, value] of Object.entries(obj)` became `([key, value]) of ...`
- `{ foo, bar } of items` became `({ foo, bar }) of ...`

The issue was in the `format_v_for` function which added parentheses
whenever the left side contained a comma but no parenthesis. This logic
didn't account for array destructuring `[...]` or object destructuring
`{...}` which are already valid grouping constructs.

The fix checks if the left side starts with `[`, `{`, or `(` before
deciding whether to wrap with parentheses. This ensures:

- Tuple unpacking still gets parentheses: `a, i` → `(a, i)`
- Array destructuring is preserved: `[key, value]` stays as-is
- Object destructuring is preserved: `{ foo, bar }` stays as-is
- Mixed patterns work correctly: `([key, value], i)` stays as-is

@g-plane g-plane left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks!

Comment thread markup_fmt/src/printer.rs Outdated
@g-plane g-plane merged commit 789d15e into g-plane:main Dec 19, 2025
@yacinehmito yacinehmito deleted the fix-v-for-destructuring branch December 19, 2025 16:59
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