Summary
A string literal containing an embedded newline gains a space of indentation
every time the statement is formatted, so format() is not a fixed point and
the literal's value drifts on each pass.
This changes data, not just layout: the extra spaces land inside the string
constant.
Reproduction
SELECT js FROM (VALUES ('[{"a":"1"},
{"b":"2","b":"3"}]')) foo(js);
Formatting repeatedly with Style::River:
pass 1 ... (VALUES ('[{"a":"1"},
{"b":"2","b":"3"}]')) AS foo(js);
pass 2 ... (VALUES ('[{"a":"1"},
{"b":"2","b":"3"}]')) AS foo(js);
pass 3 ... (VALUES ('[{"a":"1"},
{"b":"2","b":"3"}]')) AS foo(js);
One space is added per pass, and the value of the JSON string changes each
time.
Cause
Continuation lines of multi-line content are re-indented to the content column.
A newline inside a string literal is data rather than layout, so the line that
follows it must be left exactly as written.
#56 fixed this in river_line by skipping lines whose preceding newline falls
inside a literal (newlines_inside_literal in src/formatter/select.rs). At
least one other path still re-indents — the drift shrinks from several spaces
per pass to one, but does not stop. The remaining path is somewhere between
format_values_clause and the subquery/table-ref rendering that wraps it.
Suggested approach
The quote-aware check added in #56 is reusable; the remaining call site needs
the same treatment. A broader fix would be to make the indenting helpers take
the literal-awareness into account once, rather than at each call site.
Test
tests/reparse_test.rs::formatting_is_idempotent_in_every_style currently skips
this statement:
if sql.contains("array w. UK?") {
continue;
}
Removing that skip should be part of the fix.
Summary
A string literal containing an embedded newline gains a space of indentation
every time the statement is formatted, so
format()is not a fixed point andthe literal's value drifts on each pass.
This changes data, not just layout: the extra spaces land inside the string
constant.
Reproduction
Formatting repeatedly with
Style::River:One space is added per pass, and the value of the JSON string changes each
time.
Cause
Continuation lines of multi-line content are re-indented to the content column.
A newline inside a string literal is data rather than layout, so the line that
follows it must be left exactly as written.
#56 fixed this in
river_lineby skipping lines whose preceding newline fallsinside a literal (
newlines_inside_literalinsrc/formatter/select.rs). Atleast one other path still re-indents — the drift shrinks from several spaces
per pass to one, but does not stop. The remaining path is somewhere between
format_values_clauseand the subquery/table-ref rendering that wraps it.Suggested approach
The quote-aware check added in #56 is reusable; the remaining call site needs
the same treatment. A broader fix would be to make the indenting helpers take
the literal-awareness into account once, rather than at each call site.
Test
tests/reparse_test.rs::formatting_is_idempotent_in_every_stylecurrently skipsthis statement:
Removing that skip should be part of the fix.