google-java-format icon indicating copy to clipboard operation
google-java-format copied to clipboard

multiline strings poorly formatted

Open niels1voo opened this issue 2 years ago • 10 comments
trafficstars

We use multiline strings to write queries using the @Query annotation. The formatter does a poor job of formatting these strings and in some cases does not attempt to format strings that are poorly formatted (to my eyes).

The formatter considers the following examples to be correctly formatted. image

image

niels1voo avatar Jan 19 '23 15:01 niels1voo

Well, technically, they are: Google Java Format won't change the content of the string, it cannot know whether the spaces and line ends are meaningful or not. Your IDE highlights the SQL syntax inside the string, but from a Java perspective they are just string and without that special knowledge from the IDE that they contain SQL, they'd be all green like quotes that delimit them.

tbroyer avatar Jan 19 '23 17:01 tbroyer

Note that in the first picture, the indentation is known to be irrelevant. The horizontal placement of the opening delimiter has no effect on the string content, and both other lines (SELECT and closing delimiter) have the same amount of indentation, so all indentation is removed. The value of that string is just the SELECT statement with a trailing line break.

I would also find it great if google-java-format would adjust and fix indentation of text blocks. In this particular example, all lines of the text block should get the same indentation as the opening delimiter.

For the second picture, it seems that the SELECT has no indentation at all. In this case, everything about the text block except the placement of the opening delimiter is relevant for the string content, so google-java-format can indeed do nothing.

PhilippWendler avatar Jan 20 '23 07:01 PhilippWendler

I would also find it great if google-java-format would adjust and fix indentation of text blocks.

I want my text blocks to be formatted and stay exactly formatted like I formatted them.

sormuras avatar Jan 20 '23 07:01 sormuras

@sormuras Note that google-java-format is an opinionated code formatter and deliberately ignores almost all existing formatting in the input. I don't think indentation of text blocks meets these criteria so it is expected that google-java-format will change it.

PhilippWendler avatar Jan 20 '23 14:01 PhilippWendler

String s = "a\n\nb\n";
String t = """
a

b
""";

Any change any formatter, opinionated or not, does to any String literal I wrote in a Java source file that results in a different String instance at run-time ... is broken. If formatter moves a String or text block around, the String instance must stay as-is.

Or in other words: formatter, style my code, but don't alter it.

sormuras avatar Jan 20 '23 15:01 sormuras

As explained above (https://github.com/google/google-java-format/issues/883#issuecomment-1398005211), common indentation of a text block is not relevant for its content.

PhilippWendler avatar Jan 20 '23 15:01 PhilippWendler

Then we are on the same page. 👍

String s = "a\n\n" + "b\n";
String t = """
           a

           b
           """;

sormuras avatar Jan 20 '23 15:01 sormuras

I would also find it great if google-java-format would adjust and fix indentation of text blocks.

I want my text blocks to be formatted and stay exactly formatted like I formatted them.

This would be better than what it does now

niels1voo avatar Jan 25 '23 22:01 niels1voo

Hello. It happens I was part of the group that designed text blocks for Java (though all credit goes to Jim Laskey and others). First here's some possibly-unnecessary clarity on exactly how the feature works:

Ignore the line containing the opening """, but don't ignore the closing """. Now visualize the smallest bounding rectangle around all visible (non-whitespace) characters (again, including the closing """). Lastly chop off that """, trim trailing whitespace from every line, and don't add a final newline (in most cases you already had that).

The result is the exact contents of the string. The lines in that rectangle will never be shifted relative to each other. (Yeah, did I coin two different "rectangle rules"? I think I did.)

The effect is that a rectangle of spaces, shown here as dots, is ignored as if they were not present:

image

(from https://docs.oracle.com/en/java/javase/15/text-blocks/index.html)

That means that the formatter is every bit as justified in adding or removing columns to that rectangle-shown-as-dots as it is in changing any other indentation. And I agree that leaving the indentation as it was doesn't meet the criteria @PhilippWendler linked to.

I think it should be indented to the level at which the line containing the """ is, plus either a regular or a continuation indent. First thought would be regular, since it doesn't fit the definition of a continuation line (which IIRC is: when no style rule would have forced you to break except for the column limit, then all lines but the first are continuation lines; this holds whether the column limit did force the break or it was elective).

kevinb9n avatar Jan 25 '23 23:01 kevinb9n

Then we are on the same page. 👍

String s = "a\n\n" + "b\n";
String t = """
           a

           b
           """;

(To be clear, it wouldn't do that specifically, since it would be vulnerable to simple refactorings.)

kevinb9n avatar Jan 25 '23 23:01 kevinb9n