Skip to content

Commit 4cf17dd

Browse files
cushonabashev
authored andcommitted
Join hyphenated words broken across lines in Javadoc comments.
When a compound word was hyphenated across a line break in Javadoc (e.g., `infinite-\n * precision`), the formatter previously joined the tokens with a space, resulting in `infinite- precision`. Join adjacent word literals across a line break when the preceding literal ends in a hyphen following a word character, while preserving spaces after suspended hyphens (e.g., `pre- and post-`). Ported from google/google-java-format#1475 (commit 55863463), adapted to this fork's Token API. The markdown `///` test does not apply here. The tests were written first: hyphenatedLineBreakJoined failed with `infinite- precision`, suspendedHyphenPreserved and hyphenBeforeParagraphBreakNotJoined guard the cases that must stay as they are.
1 parent a9a4744 commit 4cf17dd

2 files changed

Lines changed: 80 additions & 4 deletions

File tree

‎open-java-format/src/main/java/com/palantir/javaformat/java/javadoc/JavadocLexer.java‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,16 @@ private static ImmutableList<Token> joinAdjacentLiteralsAndAdjacentWhitespace(Li
339339
continue;
340340
}
341341

342+
if (seenWhitespace.indexOf("\n") >= 0
343+
&& !hasMultipleNewlines(seenWhitespace.toString())
344+
&& isHyphenatedWordEnd(accumulated)
345+
&& tokens.peek().getType() == LITERAL
346+
&& isWordStart(tokens.peek().getValue())
347+
&& !isSuspendedHyphenConjunction(tokens.peek().getValue())) {
348+
accumulated.append(tokens.next().getValue());
349+
continue;
350+
}
351+
342352
output.add(new Token(LITERAL, accumulated.toString()));
343353
accumulated.setLength(0);
344354

@@ -350,13 +360,26 @@ private static ImmutableList<Token> joinAdjacentLiteralsAndAdjacentWhitespace(Li
350360
// We have another token coming, possibly of type OTHER. Leave it for the next iteration.
351361
}
352362

353-
/*
354-
* TODO(cpovirk): Another case where we could try to join tokens is if a line ends with
355-
* /[^ -]-/, as in "non-\nblocking."
356-
*/
357363
return output.build();
358364
}
359365

366+
private static boolean isHyphenatedWordEnd(CharSequence cs) {
367+
int length = cs.length();
368+
return length >= 2 && cs.charAt(length - 1) == '-' && isWordChar(cs.charAt(length - 2));
369+
}
370+
371+
private static boolean isWordChar(char c) {
372+
return Character.isLetterOrDigit(c) || c == '_';
373+
}
374+
375+
private static boolean isWordStart(String s) {
376+
return !s.isEmpty() && isWordChar(s.charAt(0));
377+
}
378+
379+
private static boolean isSuspendedHyphenConjunction(String s) {
380+
return s.equals("and") || s.equals("or");
381+
}
382+
360383
/**
361384
* Where the input has two consecutive line breaks between literals, insert a {@code <p>} tag between the literals.
362385
*

‎open-java-format/src/test/java/com/palantir/javaformat/java/JavadocFormattingTest.java‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,4 +1496,57 @@ void snippetKeepsCommentsAndIndentation() {
14961496
};
14971497
doFormatTest(input, input);
14981498
}
1499+
1500+
@Test
1501+
void hyphenatedLineBreakJoined() {
1502+
String[] input = {
1503+
"/**", //
1504+
" * This calculation requires an infinite-",
1505+
" * precision number.",
1506+
" */",
1507+
"class Test {}",
1508+
};
1509+
String[] expected = {
1510+
"/** This calculation requires an infinite-precision number. */", //
1511+
"class Test {}",
1512+
};
1513+
doFormatTest(input, expected);
1514+
}
1515+
1516+
@Test
1517+
void suspendedHyphenPreserved() {
1518+
String[] input = {
1519+
"/**", //
1520+
" * Both pre-",
1521+
" * and post-processing steps.",
1522+
" */",
1523+
"class Test {}",
1524+
};
1525+
String[] expected = {
1526+
"/** Both pre- and post-processing steps. */", //
1527+
"class Test {}",
1528+
};
1529+
doFormatTest(input, expected);
1530+
}
1531+
1532+
@Test
1533+
void hyphenBeforeParagraphBreakNotJoined() {
1534+
String[] input = {
1535+
"/**", //
1536+
" * Ends with a non-",
1537+
" *",
1538+
" * blocking paragraph.",
1539+
" */",
1540+
"class Test {}",
1541+
};
1542+
String[] expected = {
1543+
"/**", //
1544+
" * Ends with a non-",
1545+
" *",
1546+
" * <p>blocking paragraph.",
1547+
" */",
1548+
"class Test {}",
1549+
};
1550+
doFormatTest(input, expected);
1551+
}
14991552
}

0 commit comments

Comments
 (0)