diff --git a/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java b/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java index 7c6e42958..d02196972 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java +++ b/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java @@ -145,17 +145,28 @@ private List wrapLineComments(Tok tok, List lines, int column0) result.add(line); continue; } + // Preserve the original line-comment marker (`//` or `///`, etc.) on wrapped continuations. + // Hardcoding `//` used to inject `//` lines into `///` comments and would also break at the + // space after `///`, which mangled long unbreakable tokens such as markdown links + // (https://github.com/google/google-java-format/issues/1369). + int slashCount = 0; + while (slashCount < line.length() && line.charAt(slashCount) == '/') { + slashCount++; + } + // Line comments always start with at least "//". + String lineCommentPrefix = line.substring(0, Math.max(slashCount, 2)); + int prefixLength = lineCommentPrefix.length(); while (line.length() + column0 > Formatter.MAX_LINE_LENGTH) { int idx = Formatter.MAX_LINE_LENGTH - column0; - // only break on whitespace characters, and ignore the leading `// ` - while (idx >= 2 && !CharMatcher.whitespace().matches(line.charAt(idx))) { + // only break on whitespace characters, and ignore the leading comment marker + while (idx >= prefixLength && !CharMatcher.whitespace().matches(line.charAt(idx))) { idx--; } - if (idx <= 2) { + if (idx <= prefixLength) { break; } result.add(line.substring(0, idx)); - line = "//" + line.substring(idx); + line = lineCommentPrefix + line.substring(idx); } result.add(line); } diff --git a/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java b/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java index 9ba460428..7f1b47e23 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java @@ -648,6 +648,55 @@ class T { """); } + // https://github.com/google/google-java-format/issues/1369 + @Test + public void wrapTripleSlashLineCommentPreservesPrefix() throws Exception { + assertThat( + new Formatter() + .formatSource( +""" +class T { + void m() { + /// one long incredibly unbroken sentence moving from topic to topic so that no-one had a chance to interrupt the speaker at all; + } +} +""")) + .isEqualTo( +""" +class T { + void m() { + /// one long incredibly unbroken sentence moving from topic to topic so that no-one had a chance + /// to interrupt the speaker at all; + } +} +"""); + } + + // https://github.com/google/google-java-format/issues/1369 + @Test + public void doNotBreakLongUnbreakableTripleSlashLink() throws Exception { + assertThat( + new Formatter() + .formatSource( +""" +class T { + void m() { + /// [Design-doc](8901234567890123456789012345678901234567890123456789012345678901234567890123456789) + /// [Design-doc](89012345678901234567890123456789012345678901234567890123456789012345678901234567890) + } +} +""")) + .isEqualTo( +""" +class T { + void m() { + /// [Design-doc](8901234567890123456789012345678901234567890123456789012345678901234567890123456789) + /// [Design-doc](89012345678901234567890123456789012345678901234567890123456789012345678901234567890) + } +} +"""); + } + @Test public void removeTrailingTabsInComments() throws Exception { assertThat( diff --git a/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java b/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java index 2ab647c9f..9cef17b50 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java @@ -1678,14 +1678,14 @@ T method() { } /// This long line of text looks like a javadoc comment, but is not, because it is separated from - // the actual javadoc comment by a plain comment. + /// the actual javadoc comment by a plain comment. // This is the plain comment. /// A third very long line of text, this time a javadoc comment on a field, which again exceeds /// the maximum line length. String field; /// A fourth very long line of text, which however is not a javadoc comment so will be wrapped - // like a regular // comment. + /// like a regular // comment. } """; doFormatTest(input, expected);