Skip to content

fix: keep a block comment leading a later statement on its own line - #961

Open
MildlyMeticulous wants to merge 1 commit into
sql-formatter-org:masterfrom
MildlyMeticulous:fix/block-comment-leading-statement
Open

fix: keep a block comment leading a later statement on its own line#961
MildlyMeticulous wants to merge 1 commit into
sql-formatter-org:masterfrom
MildlyMeticulous:fix/block-comment-leading-statement

Conversation

@MildlyMeticulous

Copy link
Copy Markdown

A block comment before a statement that follows another is formatted inline on the first pass but moved onto its own line on the second, so formatting isn't idempotent:

format('SELECT 1; /* c */ COMMIT;');
// => "SELECT\n  1;\n\n/* c */ COMMIT;"
// reformatted => "SELECT\n  1;\n\n/* c */\nCOMMIT;"

Same shape as #952, one level up. That fix made a block comment standalone when layout.isAtStartOfLine(), but formatAst gives each statement its own Layout, so for a leading comment the layout is still empty and isAtStartOfLine() falls through to return false. Statements are joined with newlines, so every statement after the first does start on a line — the second pass sees that newline as the comment's precedingWhitespace and flips the decision.

Layout now takes whether its statement is preceded by others, and an empty layout reports isAtStartOfLine() accordingly. The first statement is unaffected, so a leading comment on the whole query still formats inline as before.

Found by fuzzing format(format(x)) === format(x) with comments injected at every token boundary: 14,427 variants over 14 dialects, 10 failures before, 0 after. It reproduces in 11 of 21 dialects and for any keyword-only statement — COMMIT, ROLLBACK, BEGIN, END, GO, USE, VACUUM, ANALYZE, SAVEPOINT. Statements with clauses are stable because the following keyword forces the newline anyway.

5,861 tests pass; tsc, eslint and prettier clean.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bd34be73-cb71-49aa-a22b-499c9c50c3cc

📥 Commits

Reviewing files that changed from the base of the PR and between aa8efae and 67ee978.

📒 Files selected for processing (3)
  • src/formatter/Formatter.ts
  • src/formatter/Layout.ts
  • test/features/comments.ts

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved formatting for block comments between statements by placing them on their own line.
    • Ensured formatted output remains consistent when formatting is applied repeatedly.
  • Tests

    • Added coverage for comment placement and formatting consistency after statement delimiters.

Walkthrough

The formatter now tracks whether each statement follows another statement, passes that state into Layout, and uses it when determining line starts. A regression test verifies standalone block-comment placement and formatting idempotency.

Changes

Statement layout formatting

Layer / File(s) Summary
Track statement line-start state
src/formatter/Layout.ts
Layout stores whether its statement starts on a new line, and isAtStartOfLine() uses that state for indentation-only layouts.
Propagate statement position and validate comments
src/formatter/Formatter.ts, test/features/comments.ts
Statement indexes are passed into Layout, with a regression test covering block-comment placement and idempotent formatting.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: nene, sarathfrancis90

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main fix: keeping block comments before later statements on their own line.
Description check ✅ Passed The description is directly about the same idempotency bug and the formatting fix in this changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

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.

1 participant