Repository navigation
fix(cli): clearer formatter option errors and check output - #917
Merged
Merged
Conversation
…functions break sensibly
…print-grant-admin-option
…int-long-identifiers
psteinroe
changed the base branch from
test/pretty-print-option-matrix
to
main
October 26, 2026 09:32
psteinroe
added a commit
that referenced
this pull request
Oct 26, 2026
…ace (#934) Stacked on #917. Comments written before a keyword that has no AST node of its own (`ELSE`, `THEN`, `END`, GRANT's `ON`/`TO`/`FROM`) moved past the keyword, sometimes into another branch or clause. The output was stable on reformat, so nothing flagged it, but the comment no longer sat where it was written. Finding P17 of the release review. ```sql select case -- why when a then 'x' /* inline */ else 'y' end from t; -- before select case when a then 'x' else /* inline */ 'y' -- why end from t; -- after select case -- why when a then 'x' /* inline */ else 'y' end from t; select case when a /* cond */ then 1 else 2 /* last */ end from t; -- before select case when a then /* cond */ 1 else 2 end from /* last */ t; -- after select case when a /* cond */ then 1 else 2 /* last */ end from t; grant select -- c on t to u; -- before grant select on table -- c t to u; -- after grant select -- c on table t to u; ``` **Why they moved** Comments are attached to AST nodes by source position, and a comment that leads goes to the next node: a block comment, an own-line comment, or a comment after a clause keyword. For `'x' /* inline */ else 'y'` the next node is `'y'`, so the comment came out after `else`. A comment right after `case` didn't count as following a clause keyword, so it trailed the whole CASE and came out after the last branch. A comment before `end` led the next node after the CASE, in the FROM clause. **What changed** - When the token after a comment is a keyword that no node starts at, the comment remembers that keyword (`before_keyword`). A parent that writes such a keyword before a child can take the comments written before it, with `emit_comments_before_keyword`, and emit them before the keyword. They are emitted like the trailing comments of the previous node, so an own-line comment keeps its own line. Only comments recorded for that exact keyword are taken. A parent that doesn't call it keeps today's placement, so nothing else moves. - CASE takes them before `ELSE` and `THEN`. GRANT/REVOKE takes them before `ON` and `TO`/`FROM`, and GRANT role before `TO`/`FROM`. - A comment before `END` stays with the last branch: it trails the previous node instead of leading the next one, because nothing inside the CASE follows `END`. - `CASE` counts as a clause keyword, so a line comment right after it goes before the first `WHEN`. - The renderer collapses two spaces in a row inside a group that stays on one line, as it already did for broken groups. The comment emission otherwise gave `a /* cond */ then`. **Tests** - New tests in `comment_layout.rs` cover a comment before `ELSE`, `THEN` and `END`, after `CASE`, and before GRANT's `ON` and `TO`, in fit and expanded layout, each formatted twice to check idempotence. - Two unit tests in `comments.rs` cover the attachment. - No snapshot changes: the snapshot harness renders without comments. - The option matrix from #912 passes over the fixtures and the regression suite. **Not covered** Other keyword-only positions (`ON` in a join, `AS` before an alias, `FROM` in a SELECT, ...) keep the old placement. They can opt in the same way when needed.
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.
Stacked on #912.
Fixes formatter options and
formatcheck output that were hard to use, found in the release review.Option errors list the valid values
All formatter enums now say what they expect, without naming the Rust type.
Layoutis shared by--layoutand--values-row-layout, and the user never sees that name.A zero line width or indent size is rejected
--line-width=0and--indent-size=0, and"lineWidth": 0/"indentSize": 0in the config file, were accepted.lineWidthandindentSizeare nowNonZeroU16/NonZeroU8, asfiles.maxSizealready is. The CLI sayscouldn't parse '0': number would be zero for non-zero type, the config fileinvalid value: integer '0', expected a nonzero u16. The JSON schema now hasminimum: 1for both.Check output names the line
Without
--write,formatprinted one diagnostic per statement that would change. When a statement's diff fits on one line, it is printed without line numbers, and the header only names the file. In a large file there was no way to find the statement. The message now carries the line:I put the line in the message rather than giving the diagnostic a span. With a span, the printer adds a code frame of the statement above the diff. When only the blank lines between statements change, the whole-file diff now says "File could be formatted" instead of "Statement".
Help shows the values
Every format flag was shown as
=ARGin--helpand in the CLI reference. They now showNUMBER,<spaces|tabs>,<fit|expanded>and so on, like the other options.Docs
The
layoutoption was described as "always breaks between clauses". Expanded layout also puts every select list item and every AND/OR operand on its own line and breaks before every CASE branch. A select-list-only subquery and a CHECK condition follow the line width instead. The option's description (and so the schema, bindings and CLI reference) anddocs/features/formatting.mdnow say this, and the docs have an example. Together with the CASE and tabs docs in #894, this covers the docs gaps from the review.Tests
just gen-lint.Risks
A config file with
lineWidthorindentSizeset to 0 used to load and now fails to load with the error above. With either set to 0 the formatter output was unusable anyway: every group broke, or nothing was indented.