diff --git a/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java b/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java index 4eda2fc2f..4c3b27e0d 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/doc/Level.java @@ -339,9 +339,19 @@ private Optional tryInlinePrefixOntoCurrentLine( // Add the width of tokens, breaks before the lastLevel. We must always have space for // these. - List leadingDocs = docs.subList(0, docs.indexOf(lastLevel)); + int lastLevelIndex = docs.indexOf(lastLevel); + List leadingDocs = docs.subList(0, lastLevelIndex); float leadingWidth = getWidth(leadingDocs); + // A forced break after the lastLevel, such as the ones around a // comment that sits before this level's + // closing token, cannot be laid out flat by tryToLayOutLevelOnOneLine: the comment would swallow every token + // after it on the line. Such a level breaks normally instead, as tryBreakInnerLevel refuses it for the same + // reason. (A forced break before the lastLevel makes leadingWidth infinite and fails the check below.) + List trailingDocs = docs.subList(lastLevelIndex + 1, docs.size()); + if (Float.isInfinite(getWidth(trailingDocs))) { + return Optional.empty(); + } + // Potentially add the width of prefixes we want to consider as part of the width that // must fit on the same line, so that we don't accidentally break prefixes when we could // have avoided doing so. @@ -592,6 +602,9 @@ private static Optional tryBreakInnerLevel_checkInner( * Mark breaks in this level as not broken, but lay out the inner levels normally, according to their own * {@link BreakBehaviour}. The resulting {@link State#mustBreak} will be true if this level did not fit on exactly * one line. + * + *

The callers make sure that none of this level's own breaks is forced: a forced break laid out flat would put + * the tokens after a {@code //} comment inside the comment. */ private State tryToLayOutLevelOnOneLine( CommentsHelper commentsHelper, diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-62-comment-before-lambda-close-parens.input b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-62-comment-before-lambda-close-parens.input new file mode 100644 index 000000000..750e34a5f --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-62-comment-before-lambda-close-parens.input @@ -0,0 +1,24 @@ +import java.util.stream.IntStream; + +class Repro { + int find(Item[] items) { + return IntStream.range(0, items.length) + .filter(i -> (items[i].getName().equals("alpha") || items[i].getName().equals("beta") + || items[i].getName().equals("gamma") + // || (items[i].getName().equals("delta") && items.length > i + // && items[i + 1].getName().equals("epsilon")) + )).findFirst().orElse(-1); + } + + void plainCall() { + check(i -> (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(i) || bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(i) + // || c(i) + )); + } + + void blockComment() { + check(i -> (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(i) || bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(i) + /* block */ + )); + } +} diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-62-comment-before-lambda-close-parens.output b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-62-comment-before-lambda-close-parens.output new file mode 100644 index 000000000..f6b141e66 --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-62-comment-before-lambda-close-parens.output @@ -0,0 +1,32 @@ +import java.util.stream.IntStream; + +class Repro { + int find(Item[] items) { + return IntStream.range(0, items.length) + .filter(i -> + (items[i].getName().equals("alpha") + || items[i].getName().equals("beta") + || items[i].getName().equals("gamma") + // || (items[i].getName().equals("delta") && items.length > i + // && items[i + 1].getName().equals("epsilon")) + )) + .findFirst() + .orElse(-1); + } + + void plainCall() { + check(i -> + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(i) + || bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(i) + // || c(i) + )); + } + + void blockComment() { + check(i -> + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(i) + || bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(i) + /* block */ + )); + } +}