Index: cfe/trunk/lib/Format/BreakableToken.h =================================================================== --- cfe/trunk/lib/Format/BreakableToken.h +++ cfe/trunk/lib/Format/BreakableToken.h @@ -358,6 +358,10 @@ // Either "* " if all lines begin with a "*", or empty. StringRef Decoration; + + // If this block comment has decorations, this is the column of the start of + // the decorations. + unsigned DecorationColumn; }; class BreakableLineCommentSection : public BreakableComment { Index: cfe/trunk/lib/Format/BreakableToken.cpp =================================================================== --- cfe/trunk/lib/Format/BreakableToken.cpp +++ cfe/trunk/lib/Format/BreakableToken.cpp @@ -344,6 +344,20 @@ for (size_t i = 1; i < Lines.size(); ++i) adjustWhitespace(i, IndentDelta); + // Align decorations with the column of the star on the first line, + // that is one column after the start "/*". + DecorationColumn = StartColumn + 1; + + // Account for comment decoration patterns like this: + // + // /* + // ** blah blah blah + // */ + if (Lines.size() >= 2 && Content[1].startswith("**") && + static_cast(ContentColumn[1]) == StartColumn) { + DecorationColumn = StartColumn; + } + Decoration = "* "; if (Lines.size() == 1 && !FirstInLine) { // Comments for which FirstInLine is false can start on arbitrary column, @@ -373,6 +387,10 @@ // trailing */. We also need to preserve whitespace, so that */ is // correctly indented. LastLineNeedsDecoration = false; + // Align the star in the last '*/' with the stars on the previous lines. + if (e >= 2 && !Decoration.empty()) { + ContentColumn[i] = DecorationColumn; + } } else if (Decoration.empty()) { // For all other lines, set the start column to 0 if they're empty, so // we do not insert trailing whitespace anywhere. @@ -382,12 +400,15 @@ } // The first line already excludes the star. + // The last line excludes the star if LastLineNeedsDecoration is false. // For all other lines, adjust the line to exclude the star and // (optionally) the first whitespace. unsigned DecorationSize = Decoration.startswith(Content[i]) ? Content[i].size() : Decoration.size(); - ContentColumn[i] += DecorationSize; + if (DecorationSize) { + ContentColumn[i] = DecorationColumn + DecorationSize; + } Content[i] = Content[i].substr(DecorationSize); if (!Decoration.startswith(Content[i])) IndentAtLineBreak = @@ -400,7 +421,8 @@ llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n"; for (size_t i = 0; i < Lines.size(); ++i) { llvm::dbgs() << i << " |" << Content[i] << "| " - << (Content[i].data() - Lines[i].data()) << "\n"; + << "CC=" << ContentColumn[i] << "| " + << "IN=" << (Content[i].data() - Lines[i].data()) << "\n"; } }); } Index: cfe/trunk/unittests/Format/FormatTest.cpp =================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp +++ cfe/trunk/unittests/Format/FormatTest.cpp @@ -1966,7 +1966,7 @@ format("#define A \\\nint i;\\\n int j;", getLLVMStyleWithColumns(11))); EXPECT_EQ("#define A\n\nint i;", format("#define A \\\n\n int i;")); EXPECT_EQ("template f();", format("\\\ntemplate f();")); - EXPECT_EQ("/* \\ \\ \\\n*/", format("\\\n/* \\ \\ \\\n*/")); + EXPECT_EQ("/* \\ \\ \\\n */", format("\\\n/* \\ \\ \\\n */")); EXPECT_EQ("", format("")); } Index: cfe/trunk/unittests/Format/FormatTestComments.cpp =================================================================== --- cfe/trunk/unittests/Format/FormatTestComments.cpp +++ cfe/trunk/unittests/Format/FormatTestComments.cpp @@ -937,11 +937,11 @@ getLLVMStyleWithColumns(20))); EXPECT_EQ("/* some comment\n" - " * a comment\n" - "* that we break\n" - " * another comment\n" - "* we have to break\n" - "* a left comment\n" + " * a comment that\n" + " * we break another\n" + " * comment we have\n" + " * to break a left\n" + " * comment\n" " */", format(" /* some comment\n" " * a comment that we break\n" @@ -1856,10 +1856,10 @@ getLLVMStyleWithColumns(15))); EXPECT_EQ("/*\n**\n*/", format("/*\n**\n*/")); EXPECT_EQ("/*\n" - "*\n" + " *\n" " * aaaaaa\n" " * aaaaaa\n" - "*/", + " */", format("/*\n" "*\n" " * aaaaaa aaaaaa\n" @@ -2164,6 +2164,194 @@ " long b;", getLLVMStyleWithColumns(80))); } + +TEST_F(FormatTestComments, AlignsBlockCommentDecorations) { + EXPECT_EQ("/*\n" + " */", + format("/*\n" + "*/", getLLVMStyle())); + EXPECT_EQ("/*\n" + " */", + format("/*\n" + " */", getLLVMStyle())); + EXPECT_EQ("/*\n" + " */", + format("/*\n" + " */", getLLVMStyle())); + + // Align a single line. + EXPECT_EQ("/*\n" + " * line */", + format("/*\n" + "* line */", + getLLVMStyle())); + EXPECT_EQ("/*\n" + " * line */", + format("/*\n" + " * line */", + getLLVMStyle())); + EXPECT_EQ("/*\n" + " * line */", + format("/*\n" + " * line */", + getLLVMStyle())); + EXPECT_EQ("/*\n" + " * line */", + format("/*\n" + " * line */", + getLLVMStyle())); + EXPECT_EQ("/**\n" + " * line */", + format("/**\n" + "* line */", + getLLVMStyle())); + EXPECT_EQ("/**\n" + " * line */", + format("/**\n" + " * line */", + getLLVMStyle())); + EXPECT_EQ("/**\n" + " * line */", + format("/**\n" + " * line */", + getLLVMStyle())); + EXPECT_EQ("/**\n" + " * line */", + format("/**\n" + " * line */", + getLLVMStyle())); + EXPECT_EQ("/**\n" + " * line */", + format("/**\n" + " * line */", + getLLVMStyle())); + + // Align the end '*/' after a line. + EXPECT_EQ("/*\n" + " * line\n" + " */", + format("/*\n" + "* line\n" + "*/", getLLVMStyle())); + EXPECT_EQ("/*\n" + " * line\n" + " */", + format("/*\n" + " * line\n" + " */", getLLVMStyle())); + EXPECT_EQ("/*\n" + " * line\n" + " */", + format("/*\n" + " * line\n" + " */", getLLVMStyle())); + + // Align two lines. + EXPECT_EQ("/* line 1\n" + " * line 2 */", + format("/* line 1\n" + " * line 2 */", + getLLVMStyle())); + EXPECT_EQ("/* line 1\n" + " * line 2 */", + format("/* line 1\n" + "* line 2 */", + getLLVMStyle())); + EXPECT_EQ("/* line 1\n" + " * line 2 */", + format("/* line 1\n" + " * line 2 */", + getLLVMStyle())); + EXPECT_EQ("/* line 1\n" + " * line 2 */", + format("/* line 1\n" + " * line 2 */", + getLLVMStyle())); + EXPECT_EQ("/* line 1\n" + " * line 2 */", + format("/* line 1\n" + " * line 2 */", + getLLVMStyle())); + EXPECT_EQ("int i; /* line 1\n" + " * line 2 */", + format("int i; /* line 1\n" + "* line 2 */", + getLLVMStyle())); + EXPECT_EQ("int i; /* line 1\n" + " * line 2 */", + format("int i; /* line 1\n" + " * line 2 */", + getLLVMStyle())); + EXPECT_EQ("int i; /* line 1\n" + " * line 2 */", + format("int i; /* line 1\n" + " * line 2 */", + getLLVMStyle())); + + // Align several lines. + EXPECT_EQ("/* line 1\n" + " * line 2\n" + " * line 3 */", + format("/* line 1\n" + " * line 2\n" + "* line 3 */", + getLLVMStyle())); + EXPECT_EQ("/* line 1\n" + " * line 2\n" + " * line 3 */", + format("/* line 1\n" + " * line 2\n" + "* line 3 */", + getLLVMStyle())); + EXPECT_EQ("/*\n" + "** line 1\n" + "** line 2\n" + "*/", + format("/*\n" + "** line 1\n" + " ** line 2\n" + "*/", + getLLVMStyle())); + + // Align with different indent after the decorations. + EXPECT_EQ("/*\n" + " * line 1\n" + " * line 2\n" + " * line 3\n" + " * line 4\n" + " */", + format("/*\n" + "* line 1\n" + " * line 2\n" + " * line 3\n" + "* line 4\n" + "*/", getLLVMStyle())); + + // Align empty or blank lines. + EXPECT_EQ("/**\n" + " *\n" + " *\n" + " *\n" + " */", + format("/**\n" + "* \n" + " * \n" + " *\n" + "*/", getLLVMStyle())); + + // Align while breaking and reflowing. + EXPECT_EQ("/*\n" + " * long long long\n" + " * long long\n" + " *\n" + " * long */", + format("/*\n" + " * long long long long\n" + " * long\n" + " *\n" + "* long */", + getLLVMStyleWithColumns(20))); +} } // end namespace } // end namespace format } // end namespace clang