Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -2820,7 +2820,7 @@ } void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { - llvm::errs() << "AnnotatedTokens:\n"; + llvm::errs() << "AnnotatedTokens(L=" << Line.Level << "):\n"; const FormatToken *Tok = Line.First; while (Tok) { llvm::errs() << " M=" << Tok->MustBreakBefore Index: lib/Format/UnwrappedLineParser.h =================================================================== --- lib/Format/UnwrappedLineParser.h +++ lib/Format/UnwrappedLineParser.h @@ -20,6 +20,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Format/Format.h" #include "llvm/Support/Regex.h" +#include "llvm/ADT/Optional.h" #include #include @@ -123,9 +124,9 @@ void tryToParseJSFunction(); void addUnwrappedLine(); bool eof() const; - void nextToken(); + void nextToken(llvm::Optional LevelOfCommentLinesAfter = None); const FormatToken *getPreviousToken(); - void readToken(); + void readToken(llvm::Optional LevelOfCommentLinesAfter = None); // Decides which comment tokens should be added to the current line and which // should be added as comments before the next token. Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -460,7 +460,8 @@ FormatTok->BlockKind = BK_Block; unsigned InitialLevel = Line->Level; - nextToken(); + nextToken(/*LevelOfCommentLinesAfter=*/ + InitialLevel + AddLevel); if (MacroBlock && FormatTok->is(tok::l_paren)) parseParens(); @@ -2288,13 +2289,14 @@ CommentsBeforeNextToken.clear(); } -void UnwrappedLineParser::nextToken() { +void UnwrappedLineParser::nextToken( + llvm::Optional LevelOfCommentLinesAfter) { if (eof()) return; flushComments(isOnNewLine(*FormatTok)); pushToken(FormatTok); if (Style.Language != FormatStyle::LK_JavaScript) - readToken(); + readToken(LevelOfCommentLinesAfter); else readTokenWithJavaScriptASI(); } @@ -2363,7 +2365,8 @@ } } -void UnwrappedLineParser::readToken() { +void UnwrappedLineParser::readToken( + llvm::Optional LevelOfCommentLinesAfter) { SmallVector Comments; do { FormatTok = Tokens->getNextToken(); @@ -2376,6 +2379,8 @@ // directives only after that unwrapped line was finished later. bool SwitchToPreprocessorLines = !Line->Tokens.empty(); ScopedLineState BlockState(*this, SwitchToPreprocessorLines); + if (LevelOfCommentLinesAfter) + Line->Level = *LevelOfCommentLinesAfter; // Comments stored before the preprocessor directive need to be output // before the preprocessor directive, at the same level as the // preprocessor directive, as we consider them to apply to the directive. Index: unittests/Format/FormatTestComments.cpp =================================================================== --- unittests/Format/FormatTestComments.cpp +++ unittests/Format/FormatTestComments.cpp @@ -855,6 +855,48 @@ "#endif\n" "}")); + EXPECT_EQ("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " // comment in else\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " // comment in else\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}")); + + EXPECT_EQ("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " /* comment in else */\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " /* comment in else */\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}")); + // Keep the current level if there is an empty line between the comment and // the preprocessor directive. EXPECT_EQ("void f() {\n" @@ -912,8 +954,55 @@ "#endif\n" "}")); + EXPECT_EQ("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " // comment in else\n" + "\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + "// comment in else\n" + "\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}")); + + EXPECT_EQ("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " /* comment in else */\n" + "\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + "/* comment in else */\n" + "\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}")); + // Align with the preprocessor directive if the comment was originally aligned - // with the preprocessor directive. + // with the preprocessor directive and there is no newline between the comment + // and the preprocessor directive. EXPECT_EQ("void f() {\n" " int i;\n" "/* comment */\n" @@ -945,6 +1034,48 @@ " int j;\n" "#endif\n" "}")); + + EXPECT_EQ("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + "// comment in else\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " // comment in else\n" + " #ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}")); + + EXPECT_EQ("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + "/* comment in else */\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " /* comment in else */\n" + " #ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}")); } TEST_F(FormatTestComments, SplitsLongLinesInComments) { @@ -2649,6 +2780,30 @@ "* long */", getLLVMStyleWithColumns(20))); } + +TEST_F(FormatTestComments, TODO) { + EXPECT_EQ("int f(int i, int j) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " // comment in else\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + format("int f(int i, int j) {\n" + " if (true) {\n" + " i++;\n" + " } else {\n" + " // comment in else\n" + "#ifdef A\n" + " j++;\n" + "#endif\n" + " }\n" + "}", + getLLVMStyle())); +} } // end namespace } // end namespace format } // end namespace clang