Repository navigation
fix(pretty_print): align CASE branches in expanded layout - #884
Merged
psteinroe merged 1 commit intoOct 21, 2026
Merged
Conversation
This was referenced Oct 23, 2026
psteinroe
added a commit
that referenced
this pull request
Oct 26, 2026
Stacked on #893. Follow-up to #884. Expanded CASE expressions lost their alignment when `CASE` started left of the current indent, and a broken `WHEN` condition continued at the `WHEN` column. **Alignment from where CASE starts** The renderer stored an alignment as an offset from the indent of the level it started at, and clamped a negative offset to zero. When the text on a line starts left of that indent, the offset is negative. That happens for `select case` once the select list has opened its indent, or `on case` in a join, and `WHEN` and `END` then drifted right: ```sql -- layout: expanded, clauseBodyStyle: compact, indentSize: 8 -- before select case when a then 1 else 2 end from t; -- after select case when a then 1 else 2 end from t; ``` An alignment now keeps the column `CASE` starts at together with the indent level at that point. A continuation line starts at that column plus one indent per level opened since. When the offset is not negative this gives the same columns as before, so the existing expanded CASE output is unchanged. With `indentStyle: "tabs"` an aligned line is written as one tab per indent level and spaces for the rest, as before. When the column is left of the indent, it uses only as many tabs as fit before the column: `\t when` instead of `\t\t when`. **WHEN conditions are indented** A `WHEN` condition that breaks continued at the column of `WHEN`, so `and` read as a sibling of `when`. In expanded layout every AND/OR breaks, so this affected every multi-operand condition: ```sql -- before case when aaaa = 1 and bbbb = 2 then 'x' -- after case when aaaa = 1 and bbbb = 2 then 'x' ``` The condition is now one indent level in from `WHEN`, the same way a WHERE condition is. Fit layout does the same once the condition breaks. Expanded layout still breaks at every AND/OR in a WHEN condition. I left that alone because it is what expanded layout does everywhere else, and the reporter of #884 uses it that way. **Docs** `docs/features/formatting.md` now describes the expanded CASE layout and what tabs do to alignment: the columns only line up when the editor's tab width equals `indentSize`. A test checks that the example in the docs is what the formatter prints. **Tests and snapshot changes** New tests in `case_layout.rs`: CASE after `on` with `indentSize: 4`, `select case` with `indentSize: 8` in spaces and tabs, the exact tab and space output after a leading comma, and WHEN condition continuation in expanded and fit layout. Two tests in `comment_layout.rs` now expect the `AND` of a WHEN condition, and the comment before it, one tab further in. The only snapshot that changes is `expanded_case_expr_200`, where the AND lines of two WHEN conditions move one level in. **Not covered** A CASE nested in the THEN of another CASE still moves right by about 9 columns per level in expanded layout. Twenty levels reach 184 columns at width 100. Three or four levels stay within the width, so I didn't change the layout for this. **Follow-ups:** The nested CASE drift in expanded layout is fixed in #935.
psteinroe
added a commit
that referenced
this pull request
Oct 26, 2026
Stacked on #934. In expanded layout, a CASE nested in the THEN of another CASE moved right by `then ` plus two indent levels per level of nesting. #884 aligns each CASE's branches with the column it starts at, and a nested CASE starts after `then `. With the default indent, twenty levels reached 184 columns at width 100. Finding P16 of the release review. **What changed** A CASE written as the result of a `THEN` or `ELSE` no longer aligns with its own column. It is indented from the line of its keyword: its branches one level in, and `END` under `THEN` or `ELSE`. Each level now costs two indents, the minimum for a WHEN and its THEN: ```sql -- layout: expanded, indentSize: 4 -- before case status when 'A' then case when enabled then 'active' else 'paused' end else 'closed' end -- after case status when 'A' then case when enabled then 'active' else 'paused' end else 'closed' end ``` `else case when ... else case ...` chains read the same way. A CASE anywhere else, after `select` or a leading comma for instance, still aligns with the column it starts at, which is what #884 was about. Fit layout doesn't align, so it is unchanged. This changes the nested layout that #884's `expanded_nested_case_keeps_each_branch_at_its_own_indent` test asserted, and the test now expects the new layout. I preferred this over breaking after `then` for every nested CASE: that would add a line and a level for every nested CASE, also the shallow ones that fit today. The docs section on expanded CASE describes the nested layout. **Tests and snapshot changes** - `case_layout.rs`: the updated nested test, a CASE nested in ELSE, and twenty levels nested in THEN staying within width 100. - The only snapshot change is the nested CASE in `expanded_case_alignment` (added in #912), whose inner branches move left to the new indent. - The option matrix passes over the fixtures and the regression suite.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem and resulting behavior
In
expandedlayout, the firstWHENstays on theCASEline, andENDloses its alignment withCASEwhen the expression follows a leading comma or aTHEN.This change puts every
WHENon a new line and aligns continuation lines relative to the column where eachCASEstarts.WHENandELSEuse one extra indentation level, andTHENuses another. Nested expressions keep their own alignment.For example, with four-space indentation and leading commas:
Implementation and coverage
CASEexpressions.ELSE, using tabs and spaces at line widths of 80 and 200.fitlayout retains its existing behavior.Validation
pgls_pretty_printtests pass.cargo clippy --all-targets --all-featurespasses.cargo fmt --all --checkpasses.git diff --checkpasses.