Skip to content

String literals with embedded newlines gain indentation on every format pass #57

Description

@gmr

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions