diff --git a/core/src/main/java/com/google/googlejavaformat/java/StringWrapper.java b/core/src/main/java/com/google/googlejavaformat/java/StringWrapper.java index 52d55adba..f530c2c5f 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/StringWrapper.java +++ b/core/src/main/java/com/google/googlejavaformat/java/StringWrapper.java @@ -97,6 +97,14 @@ static String wrap(final int columnLimit, String input, Formatter formatter) } } + // applyReplacements chooses continuation indents from the string literal's start column. + // The pretty-printer may break the '+' at a different column (for example relative to + // `return`), so format once more. Without this, a second format pass changes indentation + // and wrapping is not idempotent (https://github.com/google/google-java-format/issues/935). + if (!result.equals(input)) { + result = formatter.formatSource(result); + } + return result; } diff --git a/core/src/test/java/com/google/googlejavaformat/java/StringWrapperTest.java b/core/src/test/java/com/google/googlejavaformat/java/StringWrapperTest.java index afc1533f4..d8647721c 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/StringWrapperTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/StringWrapperTest.java @@ -209,4 +209,28 @@ public class T { String actual = StringWrapper.wrap(100, input, new Formatter()); assertThat(actual).isEqualTo(expected); } + + /** + * Wrapping a long string that does not start at the beginning of its statement (e.g. after + * {@code return}) must produce output that is stable under a subsequent {@link + * Formatter#formatSource} pass. See https://github.com/google/google-java-format/issues/935. + */ + @Test + public void wrapThenFormatIsIdempotentForPrefixedString() throws Exception { + String input = + """ + public class JavaFormatterExample { + + public static String veryLongString() { + return "Very, very, very, very, very, very, very, very, very, very, very long string that will need to be split"; + } + } + """; + Formatter formatter = new Formatter(); + String wrapped = StringWrapper.wrap(100, formatter.formatSource(input), formatter); + String reformatted = formatter.formatSource(wrapped); + assertThat(reformatted).isEqualTo(wrapped); + // And a second wrap+format round trip must not change anything either. + assertThat(StringWrapper.wrap(100, reformatted, formatter)).isEqualTo(wrapped); + } }