From e2c90fdcf5d90834f541a1b36791747d58ce13e3 Mon Sep 17 00:00:00 2001 From: Zayan Khan <108294002+ZayanKhan-12@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:53:48 +0300 Subject: [PATCH 1/2] Run the string wrapping pass to a fixed point From palantir/palantir-java-format#1784 by Zayan Khan, which fixes palantir/palantir-java-format#1343 (#34 here). The indentation StringWrapper picks for a text block is derived from the layout around it, but the same pass can move that layout, so one round is not always a fixed point. In the nested array initialisers of palantir/palantir-java-format#1343 the second text block moved four columns on a second run, so a file that --replace had just written was reported by --set-exit-if-changed. wrap already recomputed its replacements after reformatting, twice; it now repeats the pass while it keeps changing the source, up to MAX_ROUNDS = 5. Adapted while bringing it over: paths moved from palantir-java-format/ to open-java-format/, and the changelog entry left out. Of the 15,747 files of the JDK 21 sources one formats differently, java/lang/Module.java, whose text block argument the old code moved again on a second run; one run now gives that second result. Formatting the sources takes no longer. Co-authored-by: Claude Opus 5 (1M context) --- .../javaformat/java/StringWrapper.java | 17 +++++++++ ...-issue-1343-text-block-indent-stable.input | 35 +++++++++++++++++++ ...issue-1343-text-block-indent-stable.output | 21 +++++++++++ 3 files changed, 73 insertions(+) create mode 100644 open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.input create mode 100644 open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.output diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java b/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java index efe1552ab..fc9526862 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java @@ -56,8 +56,25 @@ public final class StringWrapper { public static final String TEXT_BLOCK_DELIMITER = "\"\"\""; + /** + * How many times {@link #wrapOnce} may be re-run while it is still changing the source. The indentation chosen + * for a text block is derived from the layout around it, which this pass can itself move, so a single round is + * not always a fixed point and the formatter would not be idempotent. See + * #1343. + */ + private static final int MAX_ROUNDS = 5; + /** Reflows string literals in the given Java source code that extend past the given column limit. */ static String wrap(final int columnLimit, String input, Formatter formatter) throws FormatterException { + String result = wrapOnce(columnLimit, input, formatter); + for (int round = 1; round < MAX_ROUNDS && !result.equals(input); round++) { + input = result; + result = wrapOnce(columnLimit, input, formatter); + } + return result; + } + + private static String wrapOnce(final int columnLimit, String input, Formatter formatter) throws FormatterException { if (!needWrapping(columnLimit, input)) { // fast path return input; diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.input b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.input new file mode 100644 index 000000000..162408a62 --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.input @@ -0,0 +1,35 @@ +class PalantirIssue1343TextBlockIndentStable { + String[][] withCommentFirstLine = { + { + """ + // tmp fix + @Deprecated + class Test {} + """ + }, + { + """ + + @Deprecated + class Test {} + """ + } + }; + + String[][] blankLineInTheMiddle = { + { + """ + import java.util.List; + + @Deprecated + class Test {} + """ + }, + { + """ + + class Test {} + """ + } + }; +} diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.output b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.output new file mode 100644 index 000000000..30b3a9625 --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/palantir-issue-1343-text-block-indent-stable.output @@ -0,0 +1,21 @@ +class PalantirIssue1343TextBlockIndentStable { + String[][] withCommentFirstLine = {{""" + // tmp fix + @Deprecated + class Test {} + """}, {""" + + @Deprecated + class Test {} + """}}; + + String[][] blankLineInTheMiddle = {{""" + import java.util.List; + + @Deprecated + class Test {} + """}, {""" + + class Test {} + """}}; +} From 95c738acea2f1375f287dc8f7a3fb95d24a7317e Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Wed, 23 Sep 2026 10:53:49 +0300 Subject: [PATCH 2/2] Cover two more text blocks that settled only on a second run A text block that is a method argument with more arguments after it, and a text block in each branch of a ternary, came out of one run at one indentation and out of the next at another. The inputs come from google/google-java-format#805 and google/google-java-format#1378, where they show other symptoms; the first is also the shape of java/lang/Module.java, the one JDK 21 file the fixed point changes. With the string wrapping pass run to a fixed point, one run gives the second result; without it, both new goldens fail (#34). --- .../testdata/ojf-issue-34-text-block-argument.input | 8 ++++++++ .../testdata/ojf-issue-34-text-block-argument.output | 9 +++++++++ .../testdata/ojf-issue-34-text-block-ternary.input | 11 +++++++++++ .../testdata/ojf-issue-34-text-block-ternary.output | 9 +++++++++ 4 files changed, 37 insertions(+) create mode 100644 open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.input create mode 100644 open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.output create mode 100644 open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.input create mode 100644 open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.output diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.input b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.input new file mode 100644 index 000000000..ceaabe7d1 --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.input @@ -0,0 +1,8 @@ +class T { + void f() { + LOGGER.warning(String.format(""" + @Gauge is configured on a bean %s that is neither ApplicationScoped nor \ + Singleton. This is most likely a bug. You may set 'metrics.warn-dependent' \ + configuration option to 'false' to remove this warning.""", clazz.getName())); + } +} diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.output b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.output new file mode 100644 index 000000000..f3be4f87c --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-argument.output @@ -0,0 +1,9 @@ +class T { + void f() { + LOGGER.warning(String.format(""" + @Gauge is configured on a bean %s that is neither ApplicationScoped nor \ + Singleton. This is most likely a bug. You may set 'metrics.warn-dependent' \ + configuration option to 'false' to remove this warning.\ + """, clazz.getName())); + } +} diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.input b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.input new file mode 100644 index 000000000..323fb518c --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.input @@ -0,0 +1,11 @@ +class TernaryBug { + boolean flag = true; + + String a = flag + ? """ + yes + """ + : """ + no + """; +} diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.output b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.output new file mode 100644 index 000000000..967170e72 --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-34-text-block-ternary.output @@ -0,0 +1,9 @@ +class TernaryBug { + boolean flag = true; + + String a = flag ? """ + yes + """ : """ + no + """; +}