Skip to content

fix: embedded snippets with parenthesis#9828

Merged
ematipico merged 2 commits intomainfrom
fix/embedded-source-maps
Apr 6, 2026
Merged

fix: embedded snippets with parenthesis#9828
ematipico merged 2 commits intomainfrom
fix/embedded-source-maps

Conversation

@ematipico
Copy link
Copy Markdown
Member

Summary

Closes #9484

We needed to use source maps to track the original text range.

Used coding agent to track the bug and fix it.

Test Plan

Added various tests, even one to match the expanded parents.

Docs

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 6, 2026

🦋 Changeset detected

Latest commit: a05db18

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added A-Project Area: project A-Formatter Area: formatter L-JavaScript Language: JavaScript and super languages labels Apr 6, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 6, 2026

Merging this PR will not alter performance

✅ 58 untouched benchmarks
⏩ 196 skipped benchmarks1


Comparing fix/embedded-source-maps (a05db18) with main (75454bd)2

Open in CodSpeed

Footnotes

  1. 196 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (d5ca672) during the generation of this report, so 75454bd was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff9cda02-c0db-478b-9923-546b1fc00dec

📥 Commits

Reviewing files that changed from the base of the PR and between 18d62bf and a05db18.

📒 Files selected for processing (1)
  • crates/biome_js_formatter/src/js/auxiliary/template_chunk_element.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_js_formatter/src/js/auxiliary/template_chunk_element.rs

Walkthrough

A patch release for @biomejs/biome addressing issue #9484 where the formatter could panic when graphql tagged template literals appear next to parenthesised expressions. The embedded formatter now only replaces StartEmbedded when fn_format_embedded returns a document and conditionally emits a hard line for EndEmbedded. Template chunk ranges are mapped back to original source positions when a source map exists. propagate_expand() is invoked after embedded formatting. Three regression tests were added covering the reported crash and related group-expansion behaviour.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly addresses the main change: fixing embedded snippets that fail when paired with parentheses, matching the core issue from #9484.
Description check ✅ Passed The description references the linked issue (#9484), explains the fix approach (source maps), mentions AI assistance, and lists test additions—all relevant to the changeset.
Linked Issues check ✅ Passed Changes comprehensively address #9484: (1) format_embedded now conditionally tracks StartEmbedded resolution via source maps [lib.rs], (2) embedded_node_range maps transformed ranges back to original coordinates [template_chunk_element.rs], (3) propagate_expand re-applies group expansion after embedding [javascript.rs], and (4) regression tests validate parenthesis cases and expand propagation [server.tests.rs].
Out of Scope Changes check ✅ Passed All changes directly target the embedded snippets crash: formatter logic fixes, source map integration, and comprehensive regression tests. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/embedded-source-maps

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

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

🧹 Nitpick comments (1)
crates/biome_formatter/src/lib.rs (1)

1036-1057: Consider a nesting stack over one shared flag for more robust handling.

last_start_resolved only tracks the most recent StartEmbedded, so if Document::transform() descends into an inserted embedded document (which it does, per the Interned documentation), an inner StartEmbedded would overwrite the outer state. The result: an unresolved inner embed would incorrectly suppress the outer EndEmbedded. A small Vec<bool> keyed by embed depth would handle nesting safely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_formatter/src/lib.rs` around lines 1036 - 1057, The current
single-boolean state last_start_resolved is insufficient for nested embeds;
replace it with a stack (e.g., Vec<bool>) tracked across the transform closure
so each StartEmbedded/EndEmbedded pair uses its own depth entry: when matching
FormatElement::Tag(Tag::StartEmbedded(range)) call fn_format_embedded(*range)
and push true onto the stack if Some(document) (and output the Interned), or
push false and output None to keep the StartEmbedded; when matching
FormatElement::Tag(Tag::EndEmbedded) pop the top value and if it was true emit
FormatElement::Line(LineMode::Hard) otherwise emit None so unresolved inner
embeds no longer clobber outer state (adjust variable names around
last_start_resolved, Interned, fn_format_embedded, and the
self.document.transform closure accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_formatter/src/lib.rs`:
- Around line 1036-1057: The current single-boolean state last_start_resolved is
insufficient for nested embeds; replace it with a stack (e.g., Vec<bool>)
tracked across the transform closure so each StartEmbedded/EndEmbedded pair uses
its own depth entry: when matching FormatElement::Tag(Tag::StartEmbedded(range))
call fn_format_embedded(*range) and push true onto the stack if Some(document)
(and output the Interned), or push false and output None to keep the
StartEmbedded; when matching FormatElement::Tag(Tag::EndEmbedded) pop the top
value and if it was true emit FormatElement::Line(LineMode::Hard) otherwise emit
None so unresolved inner embeds no longer clobber outer state (adjust variable
names around last_start_resolved, Interned, fn_format_embedded, and the
self.document.transform closure accordingly).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1b2260b6-0e0c-49f4-906d-f13e55d9cb8f

📥 Commits

Reviewing files that changed from the base of the PR and between d5ca672 and 18d62bf.

⛔ Files ignored due to path filters (3)
  • crates/biome_service/src/workspace/snapshots/biome_service__workspace__server__tests__issue_9484_parens_before_graphql_call.snap is excluded by !**/*.snap and included by **
  • crates/biome_service/src/workspace/snapshots/biome_service__workspace__server__tests__issue_9484_parens_jsx_with_graphql_tag.snap is excluded by !**/*.snap and included by **
  • crates/biome_service/src/workspace/snapshots/biome_service__workspace__server__tests__issue_9484_propagate_expand_after_embed.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (5)
  • .changeset/chatty-showers-cover.md
  • crates/biome_formatter/src/lib.rs
  • crates/biome_js_formatter/src/js/auxiliary/template_chunk_element.rs
  • crates/biome_service/src/file_handlers/javascript.rs
  • crates/biome_service/src/workspace/server.tests.rs

@ematipico ematipico merged commit 9e40844 into main Apr 6, 2026
28 checks passed
@ematipico ematipico deleted the fix/embedded-source-maps branch April 6, 2026 17:06
@github-actions github-actions Bot mentioned this pull request Apr 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Formatter Area: formatter A-Project Area: project L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeScript File with GraphQL and gql`` crashes

2 participants