Index: lib/Format/BreakableToken.h =================================================================== --- lib/Format/BreakableToken.h +++ lib/Format/BreakableToken.h @@ -161,8 +161,8 @@ /// /// A result having offset == StringRef::npos means that no reformat is /// necessary. - virtual Split getSplitAfterLastLine(unsigned TailOffset, unsigned ColumnLimit, - llvm::Regex &CommentPragmasRegex) const { + virtual Split getSplitAfterLastLine(unsigned TailOffset, + unsigned ColumnLimit) const { return Split(StringRef::npos, 0); } @@ -347,8 +347,8 @@ void replaceWhitespaceBefore(unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit, Split SplitBefore, WhitespaceManager &Whitespaces) override; - Split getSplitAfterLastLine(unsigned TailOffset, unsigned ColumnLimit, - llvm::Regex &CommentPragmasRegex) const override; + Split getSplitAfterLastLine(unsigned TailOffset, + unsigned ColumnLimit) const override; bool mayReflow(unsigned LineIndex, llvm::Regex &CommentPragmasRegex) const override; Index: lib/Format/BreakableToken.cpp =================================================================== --- lib/Format/BreakableToken.cpp +++ lib/Format/BreakableToken.cpp @@ -681,12 +681,17 @@ InPPDirective, /*Newlines=*/1, ContentColumn[LineIndex] - Prefix.size()); } -BreakableToken::Split BreakableBlockComment::getSplitAfterLastLine( - unsigned TailOffset, unsigned ColumnLimit, - llvm::Regex &CommentPragmasRegex) const { - if (DelimitersOnNewline) - return getSplit(Lines.size() - 1, TailOffset, ColumnLimit, - CommentPragmasRegex); +BreakableToken::Split +BreakableBlockComment::getSplitAfterLastLine(unsigned TailOffset, + unsigned ColumnLimit) const { + if (DelimitersOnNewline) { + StringRef TrimmedContent = Content.back().substr(TailOffset).rtrim(Blanks); + if (!TrimmedContent.empty()) { + size_t Whitespaces = + Lines.back().size() - Lines.back().rtrim(Blanks).size(); + return Split(TrimmedContent.size(), Whitespaces); + } + } return Split(StringRef::npos, 0); } Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -1383,8 +1383,8 @@ } } - BreakableToken::Split SplitAfterLastLine = Token->getSplitAfterLastLine( - TailOffset, ColumnLimit, CommentPragmasRegex); + BreakableToken::Split SplitAfterLastLine = + Token->getSplitAfterLastLine(TailOffset, ColumnLimit); if (SplitAfterLastLine.first != StringRef::npos) { if (!DryRun) Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine, Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -158,6 +158,53 @@ "var x = 1;\n" "}", getGoogleJSStyleWithColumns(20))); + + // Don't break the first line of a single line short jsdoc comment pragma. + EXPECT_EQ("/** @returns j */", + format("/** @returns j */", + getGoogleJSStyleWithColumns(20))); + + // Break a single line long jsdoc comment pragma. + EXPECT_EQ("/**\n" + " * @returns {string} jsdoc line 12\n" + " */", + format("/** @returns {string} jsdoc line 12 */", + getGoogleJSStyleWithColumns(20))); + + EXPECT_EQ("/**\n" + " * @returns {string} jsdoc line 12\n" + " */", + format("/** @returns {string} jsdoc line 12 */", + getGoogleJSStyleWithColumns(20))); + + EXPECT_EQ("/**\n" + " * @returns {string} jsdoc line 12\n" + " */", + format("/** @returns {string} jsdoc line 12*/", + getGoogleJSStyleWithColumns(20))); + + // Fix a multiline jsdoc comment ending in a comment pragma. + EXPECT_EQ("/**\n" + " * line 1\n" + " * line 2\n" + " * @returns {string} jsdoc line 12\n" + " */", + format("/** line 1\n" + " * line 2\n" + " * @returns {string} jsdoc line 12 */", + getGoogleJSStyleWithColumns(20))); + + EXPECT_EQ("/**\n" + " * line 1\n" + " * line 2\n" + " *\n" + " * @returns j\n" + " */", + format("/** line 1\n" + " * line 2\n" + " *\n" + " * @returns j */", + getGoogleJSStyleWithColumns(20))); } TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {