//===- unittest/Format/FormatTestComments.cpp - Formatting unit tests -----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Format/Format.h" #include "../Tooling/ReplacementTest.h" #include "FormatTestUtils.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" #define DEBUG_TYPE "format-test" using clang::tooling::ReplacementTest; namespace clang { namespace format { namespace { FormatStyle getGoogleStyle() { return getGoogleStyle(FormatStyle::LK_Cpp); } class FormatTestComments : public ::testing::Test { protected: enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck }; std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), StatusCheck CheckComplete = SC_ExpectComplete) { LLVM_DEBUG(llvm::errs() << "---\n"); LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector Ranges(1, tooling::Range(0, Code.size())); FormattingAttemptStatus Status; tooling::Replacements Replaces = reformat(Style, Code, Ranges, "", &Status); if (CheckComplete != SC_DoNotCheck) { bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete; EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete) << Code << "\n\n"; } ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(Result)); LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) { FormatStyle Style = getLLVMStyle(); Style.ColumnLimit = ColumnLimit; return Style; } FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) { FormatStyle Style = getGoogleStyle(FormatStyle::FormatStyle::LK_TextProto); Style.ColumnLimit = ColumnLimit; return Style; } void verifyFormat(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable"; EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); } void verifyGoogleFormat(llvm::StringRef Code) { verifyFormat(Code, getGoogleStyle()); } /// \brief Verify that clang-format does not crash on the given input. void verifyNoCrash(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { format(Code, Style, SC_DoNotCheck); } int ReplacementCount; }; //===----------------------------------------------------------------------===// // Tests for comments. //===----------------------------------------------------------------------===// TEST_F(FormatTestComments, UnderstandsSingleLineComments) { verifyFormat("//* */"); verifyFormat("// line 1\n" "// line 2\n" "void f() {}\n"); verifyFormat("void f() {\n" " // Doesn't do anything\n" "}"); verifyFormat("SomeObject\n" " // Calling someFunction on SomeObject\n" " .someFunction();"); verifyFormat("auto result = SomeObject\n" " // Calling someFunction on SomeObject\n" " .someFunction();"); verifyFormat("void f(int i, // some comment (probably for i)\n" " int j, // some comment (probably for j)\n" " int k); // some comment (probably for k)"); verifyFormat("void f(int i,\n" " // some comment (probably for j)\n" " int j,\n" " // some comment (probably for k)\n" " int k);"); verifyFormat("int i // This is a fancy variable\n" " = 5; // with nicely aligned comment."); verifyFormat("// Leading comment.\n" "int a; // Trailing comment."); verifyFormat("int a; // Trailing comment\n" " // on 2\n" " // or 3 lines.\n" "int b;"); verifyFormat("int a; // Trailing comment\n" "\n" "// Leading comment.\n" "int b;"); verifyFormat("int a; // Comment.\n" " // More details.\n" "int bbbb; // Another comment."); verifyFormat( "int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; // comment\n" "int bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; // comment\n" "int cccccccccccccccccccccccccccccc; // comment\n" "int ddd; // looooooooooooooooooooooooong comment\n" "int aaaaaaaaaaaaaaaaaaaaaaa; // comment\n" "int bbbbbbbbbbbbbbbbbbbbb; // comment\n" "int ccccccccccccccccccc; // comment"); verifyFormat("#include \"a\" // comment\n" "#include \"a/b/c\" // comment"); verifyFormat("#include // comment\n" "#include // comment"); EXPECT_EQ("#include \"a\" // comment\n" "#include \"a/b/c\" // comment", format("#include \\\n" " \"a\" // comment\n" "#include \"a/b/c\" // comment")); verifyFormat("enum E {\n" " // comment\n" " VAL_A, // comment\n" " VAL_B\n" "};"); EXPECT_EQ("enum A {\n" " // line a\n" " a,\n" " b, // line b\n" "\n" " // line c\n" " c\n" "};", format("enum A {\n" " // line a\n" " a,\n" " b, // line b\n" "\n" " // line c\n" " c\n" "};", getLLVMStyleWithColumns(20))); EXPECT_EQ("enum A {\n" " a, // line 1\n" " // line 2\n" "};", format("enum A {\n" " a, // line 1\n" " // line 2\n" "};", getLLVMStyleWithColumns(20))); EXPECT_EQ("enum A {\n" " a, // line 1\n" " // line 2\n" "};", format("enum A {\n" " a, // line 1\n" " // line 2\n" "};", getLLVMStyleWithColumns(20))); EXPECT_EQ("enum A {\n" " a, // line 1\n" " // line 2\n" " b\n" "};", format("enum A {\n" " a, // line 1\n" " // line 2\n" " b\n" "};", getLLVMStyleWithColumns(20))); EXPECT_EQ("enum A {\n" " a, // line 1\n" " // line 2\n" " b\n" "};", format("enum A {\n" " a, // line 1\n" " // line 2\n" " b\n" "};", getLLVMStyleWithColumns(20))); verifyFormat( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; // Trailing comment"); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" " // Comment inside a statement.\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;"); verifyFormat("SomeFunction(a,\n" " // comment\n" " b + x);"); verifyFormat("SomeFunction(a, a,\n" " // comment\n" " b + x);"); verifyFormat( "bool aaaaaaaaaaaaa = // comment\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaaaaa;"); verifyFormat("int aaaa; // aaaaa\n" "int aa; // aaaaaaa", getLLVMStyleWithColumns(20)); EXPECT_EQ("void f() { // This does something ..\n" "}\n" "int a; // This is unrelated", format("void f() { // This does something ..\n" " }\n" "int a; // This is unrelated")); EXPECT_EQ("class C {\n" " void f() { // This does something ..\n" " } // awesome..\n" "\n" " int a; // This is unrelated\n" "};", format("class C{void f() { // This does something ..\n" " } // awesome..\n" " \n" "int a; // This is unrelated\n" "};")); EXPECT_EQ("int i; // single line trailing comment", format("int i;\\\n// single line trailing comment")); verifyGoogleFormat("int a; // Trailing comment."); verifyFormat("someFunction(anotherFunction( // Force break.\n" " parameter));"); verifyGoogleFormat("#endif // HEADER_GUARD"); verifyFormat("const char *test[] = {\n" " // A\n" " \"aaaa\",\n" " // B\n" " \"aaaaa\"};"); verifyGoogleFormat( "aaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaaaaaa); // 81_cols_with_this_comment"); EXPECT_EQ("D(a, {\n" " // test\n" " int a;\n" "});", format("D(a, {\n" "// test\n" "int a;\n" "});")); EXPECT_EQ("lineWith(); // comment\n" "// at start\n" "otherLine();", format("lineWith(); // comment\n" "// at start\n" "otherLine();")); EXPECT_EQ("lineWith(); // comment\n" "/*\n" " * at start */\n" "otherLine();", format("lineWith(); // comment\n" "/*\n" " * at start */\n" "otherLine();")); EXPECT_EQ("lineWith(); // comment\n" " // at start\n" "otherLine();", format("lineWith(); // comment\n" " // at start\n" "otherLine();")); EXPECT_EQ("lineWith(); // comment\n" "// at start\n" "otherLine(); // comment", format("lineWith(); // comment\n" "// at start\n" "otherLine(); // comment")); EXPECT_EQ("lineWith();\n" "// at start\n" "otherLine(); // comment", format("lineWith();\n" " // at start\n" "otherLine(); // comment")); EXPECT_EQ("// first\n" "// at start\n" "otherLine(); // comment", format("// first\n" " // at start\n" "otherLine(); // comment")); EXPECT_EQ("f();\n" "// first\n" "// at start\n" "otherLine(); // comment", format("f();\n" "// first\n" " // at start\n" "otherLine(); // comment")); verifyFormat("f(); // comment\n" "// first\n" "// at start\n" "otherLine();"); EXPECT_EQ("f(); // comment\n" "// first\n" "// at start\n" "otherLine();", format("f(); // comment\n" "// first\n" " // at start\n" "otherLine();")); EXPECT_EQ("f(); // comment\n" " // first\n" "// at start\n" "otherLine();", format("f(); // comment\n" " // first\n" "// at start\n" "otherLine();")); EXPECT_EQ("void f() {\n" " lineWith(); // comment\n" " // at start\n" "}", format("void f() {\n" " lineWith(); // comment\n" " // at start\n" "}")); EXPECT_EQ("int xy; // a\n" "int z; // b", format("int xy; // a\n" "int z; //b")); EXPECT_EQ("int xy; // a\n" "int z; // bb", format("int xy; // a\n" "int z; //bb", getLLVMStyleWithColumns(12))); verifyFormat("#define A \\\n" " int i; /* iiiiiiiiiiiiiiiiiiiii */ \\\n" " int jjjjjjjjjjjjjjjjjjjjjjjj; /* */", getLLVMStyleWithColumns(60)); verifyFormat( "#define A \\\n" " int i; /* iiiiiiiiiiiiiiiiiiiii */ \\\n" " int jjjjjjjjjjjjjjjjjjjjjjjj; /* */", getLLVMStyleWithColumns(61)); verifyFormat("if ( // This is some comment\n" " x + 3) {\n" "}"); EXPECT_EQ("if ( // This is some comment\n" " // spanning two lines\n" " x + 3) {\n" "}", format("if( // This is some comment\n" " // spanning two lines\n" " x + 3) {\n" "}")); verifyNoCrash("/\\\n/"); verifyNoCrash("/\\\n* */"); // The 0-character somehow makes the lexer return a proper comment. verifyNoCrash(StringRef("/*\\\0\n/", 6)); } TEST_F(FormatTestComments, KeepsParameterWithTrailingCommentsOnTheirOwnLine) { EXPECT_EQ("SomeFunction(a,\n" " b, // comment\n" " c);", format("SomeFunction(a,\n" " b, // comment\n" " c);")); EXPECT_EQ("SomeFunction(a, b,\n" " // comment\n" " c);", format("SomeFunction(a,\n" " b,\n" " // comment\n" " c);")); EXPECT_EQ("SomeFunction(a, b, // comment (unclear relation)\n" " c);", format("SomeFunction(a, b, // comment (unclear relation)\n" " c);")); EXPECT_EQ("SomeFunction(a, // comment\n" " b,\n" " c); // comment", format("SomeFunction(a, // comment\n" " b,\n" " c); // comment")); EXPECT_EQ("aaaaaaaaaa(aaaa(aaaa,\n" " aaaa), //\n" " aaaa, bbbbb);", format("aaaaaaaaaa(aaaa(aaaa,\n" "aaaa), //\n" "aaaa, bbbbb);")); } TEST_F(FormatTestComments, RemovesTrailingWhitespaceOfComments) { EXPECT_EQ("// comment", format("// comment ")); EXPECT_EQ("int aaaaaaa, bbbbbbb; // comment", format("int aaaaaaa, bbbbbbb; // comment ", getLLVMStyleWithColumns(33))); EXPECT_EQ("// comment\\\n", format("// comment\\\n \t \v \f ")); EXPECT_EQ("// comment \\\n", format("// comment \\\n \t \v \f ")); } TEST_F(FormatTestComments, UnderstandsBlockComments) { verifyFormat("f(/*noSpaceAfterParameterNamingComment=*/true);"); verifyFormat("void f() { g(/*aaa=*/x, /*bbb=*/!y, /*c=*/::c); }"); EXPECT_EQ("f(aaaaaaaaaaaaaaaaaaaaaaaaa, /* Trailing comment for aa... */\n" " bbbbbbbbbbbbbbbbbbbbbbbbb);", format("f(aaaaaaaaaaaaaaaaaaaaaaaaa , \\\n" "/* Trailing comment for aa... */\n" " bbbbbbbbbbbbbbbbbbbbbbbbb);")); EXPECT_EQ( "f(aaaaaaaaaaaaaaaaaaaaaaaaa,\n" " /* Leading comment for bb... */ bbbbbbbbbbbbbbbbbbbbbbbbb);", format("f(aaaaaaaaaaaaaaaaaaaaaaaaa , \n" "/* Leading comment for bb... */ bbbbbbbbbbbbbbbbbbbbbbbbb);")); EXPECT_EQ( "void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaaaaa) { /*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/\n" "}", format("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaa ,\n" " aaaaaaaaaaaaaaaaaa) { /*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/\n" "}")); verifyFormat("f(/* aaaaaaaaaaaaaaaaaa = */\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); FormatStyle NoBinPacking = getLLVMStyle(); NoBinPacking.BinPackParameters = false; verifyFormat("aaaaaaaa(/* parameter 1 */ aaaaaa,\n" " /* parameter 2 */ aaaaaa,\n" " /* parameter 3 */ aaaaaa,\n" " /* parameter 4 */ aaaaaa);", NoBinPacking); // Aligning block comments in macros. verifyGoogleFormat("#define A \\\n" " int i; /*a*/ \\\n" " int jjj; /*b*/"); } TEST_F(FormatTestComments, AlignsBlockComments) { EXPECT_EQ("/*\n" " * Really multi-line\n" " * comment.\n" " */\n" "void f() {}", format(" /*\n" " * Really multi-line\n" " * comment.\n" " */\n" " void f() {}")); EXPECT_EQ("class C {\n" " /*\n" " * Another multi-line\n" " * comment.\n" " */\n" " void f() {}\n" "};", format("class C {\n" "/*\n" " * Another multi-line\n" " * comment.\n" " */\n" "void f() {}\n" "};")); EXPECT_EQ("/*\n" " 1. This is a comment with non-trivial formatting.\n" " 1.1. We have to indent/outdent all lines equally\n" " 1.1.1. to keep the formatting.\n" " */", format(" /*\n" " 1. This is a comment with non-trivial formatting.\n" " 1.1. We have to indent/outdent all lines equally\n" " 1.1.1. to keep the formatting.\n" " */")); EXPECT_EQ("/*\n" "Don't try to outdent if there's not enough indentation.\n" "*/", format(" /*\n" " Don't try to outdent if there's not enough indentation.\n" " */")); EXPECT_EQ("int i; /* Comment with empty...\n" " *\n" " * line. */", format("int i; /* Comment with empty...\n" " *\n" " * line. */")); EXPECT_EQ("int foobar = 0; /* comment */\n" "int bar = 0; /* multiline\n" " comment 1 */\n" "int baz = 0; /* multiline\n" " comment 2 */\n" "int bzz = 0; /* multiline\n" " comment 3 */", format("int foobar = 0; /* comment */\n" "int bar = 0; /* multiline\n" " comment 1 */\n" "int baz = 0; /* multiline\n" " comment 2 */\n" "int bzz = 0; /* multiline\n" " comment 3 */")); EXPECT_EQ("int foobar = 0; /* comment */\n" "int bar = 0; /* multiline\n" " comment */\n" "int baz = 0; /* multiline\n" "comment */", format("int foobar = 0; /* comment */\n" "int bar = 0; /* multiline\n" "comment */\n" "int baz = 0; /* multiline\n" "comment */")); } TEST_F(FormatTestComments, CommentReflowingCanBeTurnedOff) { FormatStyle Style = getLLVMStyleWithColumns(20); Style.ReflowComments = false; verifyFormat("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style); verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style); } TEST_F(FormatTestComments, CorrectlyHandlesLengthOfBlockComments) { EXPECT_EQ("double *x; /* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */", format("double *x; /* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */")); EXPECT_EQ( "void ffffffffffff(\n" " int aaaaaaaa, int bbbbbbbb,\n" " int cccccccccccc) { /*\n" " aaaaaaaaaa\n" " aaaaaaaaaaaaa\n" " bbbbbbbbbbbbbb\n" " bbbbbbbbbb\n" " */\n" "}", format("void ffffffffffff(int aaaaaaaa, int bbbbbbbb, int cccccccccccc)\n" "{ /*\n" " aaaaaaaaaa aaaaaaaaaaaaa\n" " bbbbbbbbbbbbbb bbbbbbbbbb\n" " */\n" "}", getLLVMStyleWithColumns(40))); } TEST_F(FormatTestComments, DontBreakNonTrailingBlockComments) { EXPECT_EQ("void ffffffffff(\n" " int aaaaa /* test */);", format("void ffffffffff(int aaaaa /* test */);", getLLVMStyleWithColumns(35))); } TEST_F(FormatTestComments, SplitsLongCxxComments) { EXPECT_EQ("// A comment that\n" "// doesn't fit on\n" "// one line", format("// A comment that doesn't fit on one line", getLLVMStyleWithColumns(20))); EXPECT_EQ("/// A comment that\n" "/// doesn't fit on\n" "/// one line", format("/// A comment that doesn't fit on one line", getLLVMStyleWithColumns(20))); EXPECT_EQ("//! A comment that\n" "//! doesn't fit on\n" "//! one line", format("//! A comment that doesn't fit on one line", getLLVMStyleWithColumns(20))); EXPECT_EQ("// a b c d\n" "// e f g\n" "// h i j k", format("// a b c d e f g h i j k", getLLVMStyleWithColumns(10))); EXPECT_EQ( "// a b c d\n" "// e f g\n" "// h i j k", format("\\\n// a b c d e f g h i j k", getLLVMStyleWithColumns(10))); EXPECT_EQ("if (true) // A comment that\n" " // doesn't fit on\n" " // one line", format("if (true) // A comment that doesn't fit on one line ", getLLVMStyleWithColumns(30))); EXPECT_EQ("// Don't_touch_leading_whitespace", format("// Don't_touch_leading_whitespace", getLLVMStyleWithColumns(20))); EXPECT_EQ("// Add leading\n" "// whitespace", format("//Add leading whitespace", getLLVMStyleWithColumns(20))); EXPECT_EQ("/// Add leading\n" "/// whitespace", format("///Add leading whitespace", getLLVMStyleWithColumns(20))); EXPECT_EQ("//! Add leading\n" "//! whitespace", format("//!Add leading whitespace", getLLVMStyleWithColumns(20))); EXPECT_EQ("// whitespace", format("//whitespace", getLLVMStyle())); EXPECT_EQ("// Even if it makes the line exceed the column\n" "// limit", format("//Even if it makes the line exceed the column limit", getLLVMStyleWithColumns(51))); EXPECT_EQ("//--But not here", format("//--But not here", getLLVMStyle())); EXPECT_EQ("/// line 1\n" "// add leading whitespace", format("/// line 1\n" "//add leading whitespace", getLLVMStyleWithColumns(30))); EXPECT_EQ("/// line 1\n" "/// line 2\n" "//! line 3\n" "//! line 4\n" "//! line 5\n" "// line 6\n" "// line 7", format("///line 1\n" "///line 2\n" "//! line 3\n" "//!line 4\n" "//!line 5\n" "// line 6\n" "//line 7", getLLVMStyleWithColumns(20))); EXPECT_EQ("// aa bb cc dd", format("// aa bb cc dd ", getLLVMStyleWithColumns(15))); EXPECT_EQ("// A comment before\n" "// a macro\n" "// definition\n" "#define a b", format("// A comment before a macro definition\n" "#define a b", getLLVMStyleWithColumns(20))); EXPECT_EQ("void ffffff(\n" " int aaaaaaaaa, // wwww\n" " int bbbbbbbbbb, // xxxxxxx\n" " // yyyyyyyyyy\n" " int c, int d, int e) {}", format("void ffffff(\n" " int aaaaaaaaa, // wwww\n" " int bbbbbbbbbb, // xxxxxxx yyyyyyyyyy\n" " int c, int d, int e) {}", getLLVMStyleWithColumns(40))); EXPECT_EQ("//\t aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", format("//\t aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", getLLVMStyleWithColumns(20))); EXPECT_EQ( "#define XXX // a b c d\n" " // e f g h", format("#define XXX // a b c d e f g h", getLLVMStyleWithColumns(22))); EXPECT_EQ( "#define XXX // q w e r\n" " // t y u i", format("#define XXX //q w e r t y u i", getLLVMStyleWithColumns(22))); EXPECT_EQ("{\n" " //\n" " //\\\n" " // long 1 2 3 4 5\n" "}", format("{\n" " //\n" " //\\\n" " // long 1 2 3 4 5\n" "}", getLLVMStyleWithColumns(20))); EXPECT_EQ("{\n" " //\n" " //\\\n" " // long 1 2 3 4 5\n" " // 6\n" "}", format("{\n" " //\n" " //\\\n" " // long 1 2 3 4 5 6\n" "}", getLLVMStyleWithColumns(20))); EXPECT_EQ("//: A comment that\n" "//: doesn't fit on\n" "//: one line", format("//: A comment that doesn't fit on one line", getLLVMStyleWithColumns(20))); } TEST_F(FormatTestComments, PreservesHangingIndentInCxxComments) { EXPECT_EQ("// A comment\n" "// that doesn't\n" "// fit on one\n" "// line", format("// A comment that doesn't fit on one line", getLLVMStyleWithColumns(20))); EXPECT_EQ("/// A comment\n" "/// that doesn't\n" "/// fit on one\n" "/// line", format("/// A comment that doesn't fit on one line", getLLVMStyleWithColumns(20))); } TEST_F(FormatTestComments, DontSplitLineCommentsWithEscapedNewlines) { EXPECT_EQ("// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\n" "// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\n" "// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", format("// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\n" "// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\n" "// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); EXPECT_EQ("int a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", format("int a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", getLLVMStyleWithColumns(50))); // FIXME: One day we might want to implement adjustment of leading whitespace // of the consecutive lines in this kind of comment: EXPECT_EQ("double\n" " a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", format("double a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n" " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", getLLVMStyleWithColumns(49))); } TEST_F(FormatTestComments, DontIntroduceMultilineComments) { // Avoid introducing a multiline comment by breaking after `\`. for (int ColumnLimit = 15; ColumnLimit <= 17; ++ColumnLimit) { EXPECT_EQ( "// aaaaaaaaaa\n" "// \\ bb", format("// aaaaaaaaaa \\ bb", getLLVMStyleWithColumns(ColumnLimit))); EXPECT_EQ( "// aaaaaaaaa\n" "// \\ bb", format("// aaaaaaaaa \\ bb", getLLVMStyleWithColumns(ColumnLimit))); EXPECT_EQ( "// aaaaaaaaa\n" "// \\ \\ bb", format("// aaaaaaaaa \\ \\ bb", getLLVMStyleWithColumns(ColumnLimit))); } } TEST_F(FormatTestComments, DontSplitLineCommentsWithPragmas) { FormatStyle Pragmas = getLLVMStyleWithColumns(30); Pragmas.CommentPragmas = "^ IWYU pragma:"; EXPECT_EQ( "// IWYU pragma: aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbb", format("// IWYU pragma: aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbb", Pragmas)); EXPECT_EQ( "/* IWYU pragma: aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbb */", format("/* IWYU pragma: aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbb */", Pragmas)); } TEST_F(FormatTestComments, PriorityOfCommentBreaking) { EXPECT_EQ("if (xxx ==\n" " yyy && // aaaaaaaaaaaa bbbbbbbbb\n" " zzz)\n" " q();", format("if (xxx == yyy && // aaaaaaaaaaaa bbbbbbbbb\n" " zzz) q();", getLLVMStyleWithColumns(40))); EXPECT_EQ("if (xxxxxxxxxx ==\n" " yyy && // aaaaaa bbbbbbbb cccc\n" " zzz)\n" " q();", format("if (xxxxxxxxxx == yyy && // aaaaaa bbbbbbbb cccc\n" " zzz) q();", getLLVMStyleWithColumns(40))); EXPECT_EQ("if (xxxxxxxxxx &&\n" " yyy || // aaaaaa bbbbbbbb cccc\n" " zzz)\n" " q();", format("if (xxxxxxxxxx && yyy || // aaaaaa bbbbbbbb cccc\n" " zzz) q();", getLLVMStyleWithColumns(40))); EXPECT_EQ("fffffffff(\n" " &xxx, // aaaaaaaaaaaa bbbbbbbbbbb\n" " zzz);", format("fffffffff(&xxx, // aaaaaaaaaaaa bbbbbbbbbbb\n" " zzz);", getLLVMStyleWithColumns(40))); } TEST_F(FormatTestComments, MultiLineCommentsInDefines) { EXPECT_EQ("#define A(x) /* \\\n" " a comment \\\n" " inside */ \\\n" " f();", format("#define A(x) /* \\\n" " a comment \\\n" " inside */ \\\n" " f();", getLLVMStyleWithColumns(17))); EXPECT_EQ("#define A( \\\n" " x) /* \\\n" " a comment \\\n" " inside */ \\\n" " f();", format("#define A( \\\n" " x) /* \\\n" " a comment \\\n" " inside */ \\\n" " f();", getLLVMStyleWithColumns(17))); } TEST_F(FormatTestComments, ParsesCommentsAdjacentToPPDirectives) { EXPECT_EQ("namespace {}\n// Test\n#define A", format("namespace {}\n // Test\n#define A")); EXPECT_EQ("namespace {}\n/* Test */\n#define A", format("namespace {}\n /* Test */\n#define A")); EXPECT_EQ("namespace {}\n/* Test */ #define A", format("namespace {}\n /* Test */ #define A")); } TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) { // Keep the current level if the comment was originally not aligned with // the preprocessor directive. EXPECT_EQ("void f() {\n" " int i;\n" " /* comment */\n" "#ifdef A\n" " int j;\n" "}", format("void f() {\n" " int i;\n" " /* comment */\n" "#ifdef A\n" " int j;\n" "}")); EXPECT_EQ("void f() {\n" " int i;\n" " /* comment */\n" "\n" "#ifdef A\n" " int j;\n" "}", format("void f() {\n" " int i;\n" " /* comment */\n" "\n" "#ifdef A\n" " int j;\n" "}")); EXPECT_EQ("int f(int i) {\n" " if (true) {\n" " ++i;\n" " }\n" " // comment\n" "#ifdef A\n" " int j;\n" "#endif\n" "}", format("int f(int i) {\n" " if (true) {\n" " ++i;\n" " }\n" " // comment\n" "#ifdef A\n" "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" "}")); // Keep the current level if there is an empty line between the comment and // the preprocessor directive. EXPECT_EQ("void f() {\n" " int i;\n" " /* comment */\n" "\n" "#ifdef A\n" " int j;\n" "}", format("void f() {\n" " int i;\n" "/* comment */\n" "\n" "#ifdef A\n" " int j;\n" "}")); EXPECT_EQ("void f() {\n" " int i;\n" " return i;\n" "}\n" "// comment\n" "\n" "#ifdef A\n" "int i;\n" "#endif // A", format("void f() {\n" " int i;\n" " return i;\n" "}\n" "// comment\n" "\n" "#ifdef A\n" "int i;\n" "#endif // A")); EXPECT_EQ("int f(int i) {\n" " if (true) {\n" " ++i;\n" " }\n" " // comment\n" "\n" "#ifdef A\n" " int j;\n" "#endif\n" "}", format("int f(int i) {\n" " if (true) {\n" " ++i;\n" " }\n" " // comment\n" "\n" "#ifdef A\n" " int j;\n" "#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 and there is no newline between the comment // and the preprocessor directive. EXPECT_EQ("void f() {\n" " int i;\n" "/* comment */\n" "#ifdef A\n" " int j;\n" "}", format("void f() {\n" " int i;\n" "/* comment */\n" "#ifdef A\n" " int j;\n" "}")); EXPECT_EQ("int f(int i) {\n" " if (true) {\n" " ++i;\n" " }\n" "// comment\n" "#ifdef A\n" " int j;\n" "#endif\n" "}", format("int f(int i) {\n" " if (true) {\n" " ++i;\n" " }\n" "// comment\n" "#ifdef A\n" " 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) { // FIXME: Do we need to fix up the " */" at the end? // It doesn't look like any of our current logic triggers this. EXPECT_EQ("/* This is a long\n" " * comment that\n" " * doesn't fit on\n" " * one line. */", format("/* " "This is a long " "comment that " "doesn't " "fit on one line. */", getLLVMStyleWithColumns(20))); EXPECT_EQ( "/* a b c d\n" " * e f g\n" " * h i j k\n" " */", format("/* a b c d e f g h i j k */", getLLVMStyleWithColumns(10))); EXPECT_EQ( "/* a b c d\n" " * e f g\n" " * h i j k\n" " */", format("\\\n/* a b c d e f g h i j k */", getLLVMStyleWithColumns(10))); EXPECT_EQ("/*\n" "This is a long\n" "comment that doesn't\n" "fit on one line.\n" "*/", format("/*\n" "This is a long " "comment that doesn't " "fit on one line. \n" "*/", getLLVMStyleWithColumns(20))); EXPECT_EQ("/*\n" " * This is a long\n" " * comment that\n" " * doesn't fit on\n" " * one line.\n" " */", format("/* \n" " * This is a long " " comment that " " doesn't fit on " " one line. \n" " */", getLLVMStyleWithColumns(20))); EXPECT_EQ("/*\n" " * This_is_a_comment_with_words_that_dont_fit_on_one_line\n" " * so_it_should_be_broken\n" " * wherever_a_space_occurs\n" " */", format("/*\n" " * This_is_a_comment_with_words_that_dont_fit_on_one_line " " so_it_should_be_broken " " wherever_a_space_occurs \n" " */", getLLVMStyleWithColumns(20))); EXPECT_EQ("/*\n" " * This_comment_can_not_be_broken_into_lines\n" " */", format("/*\n" " * This_comment_can_not_be_broken_into_lines\n" " */", getLLVMStyleWithColumns(20))); EXPECT_EQ("{\n" " /*\n" " This is another\n" " long comment that\n" " doesn't fit on one\n" " line 1234567890\n" " */\n" "}", format("{\n" "/*\n" "This is another " " long comment that " " doesn't fit on one" " line 1234567890\n" "*/\n" "}", getLLVMStyleWithColumns(20))); EXPECT_EQ("{\n" " /*\n" " * This i s\n" " * another comment\n" " * t hat doesn' t\n" " * fit on one l i\n" " * n e\n" " */\n" "}", format("{\n" "/*\n" " * This i s" " another comment" " t hat doesn' t" " fit on one l i" " n e\n" " */\n" "}", getLLVMStyleWithColumns(20))); EXPECT_EQ("/*\n" " * This is a long\n" " * comment that\n" " * doesn't fit on\n" " * one line\n" " */", format(" /*\n" " * This is a long comment that doesn't fit on one line\n" " */", getLLVMStyleWithColumns(20))); EXPECT_EQ("{\n" " if (something) /* This is a\n" " long\n" " comment */\n" " ;\n" "}", format("{\n" " if (something) /* This is a long comment */\n" " ;\n" "}", getLLVMStyleWithColumns(30))); EXPECT_EQ("/* A comment before\n" " * a macro\n" " * definition */\n" "#define a b", format("/* A comment before a macro definition */\n" "#define a b", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* some 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" " * another comment we have to break\n" "* a left comment\n" " */", getLLVMStyleWithColumns(20))); EXPECT_EQ("/**\n" " * multiline block\n" " * comment\n" " *\n" " */", format("/**\n" " * multiline block comment\n" " *\n" " */", getLLVMStyleWithColumns(20))); // This reproduces a crashing bug where both adaptStartOfLine and // getCommentSplit were trying to wrap after the "/**". EXPECT_EQ("/** multilineblockcommentwithnowrapopportunity */", format("/** multilineblockcommentwithnowrapopportunity */", getLLVMStyleWithColumns(20))); EXPECT_EQ("/*\n" "\n" "\n" " */\n", format(" /* \n" " \n" " \n" " */\n")); EXPECT_EQ("/* a a */", format("/* a a */", getLLVMStyleWithColumns(15))); EXPECT_EQ("/* a a bc */", format("/* a a bc */", getLLVMStyleWithColumns(15))); EXPECT_EQ("/* aaa aaa\n" " * aaaaa */", format("/* aaa aaa aaaaa */", getLLVMStyleWithColumns(15))); EXPECT_EQ("/* aaa aaa\n" " * aaaaa */", format("/* aaa aaa aaaaa */", getLLVMStyleWithColumns(15))); } TEST_F(FormatTestComments, SplitsLongLinesInCommentsInPreprocessor) { EXPECT_EQ("#define X \\\n" " /* \\\n" " Test \\\n" " Macro comment \\\n" " with a long \\\n" " line \\\n" " */ \\\n" " A + B", format("#define X \\\n" " /*\n" " Test\n" " Macro comment with a long line\n" " */ \\\n" " A + B", getLLVMStyleWithColumns(20))); EXPECT_EQ("#define X \\\n" " /* Macro comment \\\n" " with a long \\\n" " line */ \\\n" " A + B", format("#define X \\\n" " /* Macro comment with a long\n" " line */ \\\n" " A + B", getLLVMStyleWithColumns(20))); EXPECT_EQ("#define X \\\n" " /* Macro comment \\\n" " * with a long \\\n" " * line */ \\\n" " A + B", format("#define X \\\n" " /* Macro comment with a long line */ \\\n" " A + B", getLLVMStyleWithColumns(20))); } TEST_F(FormatTestComments, KeepsTrailingPPCommentsAndSectionCommentsSeparate) { verifyFormat("#ifdef A // line about A\n" "// section comment\n" "#endif", getLLVMStyleWithColumns(80)); verifyFormat("#ifdef A // line 1 about A\n" " // line 2 about A\n" "// section comment\n" "#endif", getLLVMStyleWithColumns(80)); EXPECT_EQ("#ifdef A // line 1 about A\n" " // line 2 about A\n" "// section comment\n" "#endif", format("#ifdef A // line 1 about A\n" " // line 2 about A\n" "// section comment\n" "#endif", getLLVMStyleWithColumns(80))); verifyFormat("int f() {\n" " int i;\n" "#ifdef A // comment about A\n" " // section comment 1\n" " // section comment 2\n" " i = 2;\n" "#else // comment about #else\n" " // section comment 3\n" " i = 4;\n" "#endif\n" "}", getLLVMStyleWithColumns(80)); } TEST_F(FormatTestComments, AlignsPPElseEndifComments) { verifyFormat("#if A\n" "#else // A\n" "int iiii;\n" "#endif // B", getLLVMStyleWithColumns(20)); verifyFormat("#if A\n" "#else // A\n" "int iiii; // CC\n" "#endif // B", getLLVMStyleWithColumns(20)); EXPECT_EQ("#if A\n" "#else // A1\n" " // A2\n" "int ii;\n" "#endif // B", format("#if A\n" "#else // A1\n" " // A2\n" "int ii;\n" "#endif // B", getLLVMStyleWithColumns(20))); } TEST_F(FormatTestComments, CommentsInStaticInitializers) { EXPECT_EQ( "static SomeType type = {aaaaaaaaaaaaaaaaaaaa, /* comment */\n" " aaaaaaaaaaaaaaaaaaaa /* comment */,\n" " /* comment */ aaaaaaaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaaaaaaa, // comment\n" " aaaaaaaaaaaaaaaaaaaa};", format("static SomeType type = { aaaaaaaaaaaaaaaaaaaa , /* comment */\n" " aaaaaaaaaaaaaaaaaaaa /* comment */ ,\n" " /* comment */ aaaaaaaaaaaaaaaaaaaa ,\n" " aaaaaaaaaaaaaaaaaaaa , // comment\n" " aaaaaaaaaaaaaaaaaaaa };")); verifyFormat("static SomeType type = {aaaaaaaaaaa, // comment for aa...\n" " bbbbbbbbbbb, ccccccccccc};"); verifyFormat("static SomeType type = {aaaaaaaaaaa,\n" " // comment for bb....\n" " bbbbbbbbbbb, ccccccccccc};"); verifyGoogleFormat( "static SomeType type = {aaaaaaaaaaa, // comment for aa...\n" " bbbbbbbbbbb, ccccccccccc};"); verifyGoogleFormat("static SomeType type = {aaaaaaaaaaa,\n" " // comment for bb....\n" " bbbbbbbbbbb, ccccccccccc};"); verifyFormat("S s = {{a, b, c}, // Group #1\n" " {d, e, f}, // Group #2\n" " {g, h, i}}; // Group #3"); verifyFormat("S s = {{// Group #1\n" " a, b, c},\n" " {// Group #2\n" " d, e, f},\n" " {// Group #3\n" " g, h, i}};"); EXPECT_EQ("S s = {\n" " // Some comment\n" " a,\n" "\n" " // Comment after empty line\n" " b}", format("S s = {\n" " // Some comment\n" " a,\n" " \n" " // Comment after empty line\n" " b\n" "}")); EXPECT_EQ("S s = {\n" " /* Some comment */\n" " a,\n" "\n" " /* Comment after empty line */\n" " b}", format("S s = {\n" " /* Some comment */\n" " a,\n" " \n" " /* Comment after empty line */\n" " b\n" "}")); verifyFormat("const uint8_t aaaaaaaaaaaaaaaaaaaaaa[0] = {\n" " 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // comment\n" " 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // comment\n" " 0x00, 0x00, 0x00, 0x00}; // comment\n"); } TEST_F(FormatTestComments, LineCommentsAfterRightBrace) { EXPECT_EQ("if (true) { // comment about branch\n" " // comment about f\n" " f();\n" "}", format("if (true) { // comment about branch\n" " // comment about f\n" " f();\n" "}", getLLVMStyleWithColumns(80))); EXPECT_EQ("if (1) { // if line 1\n" " // if line 2\n" " // if line 3\n" " // f line 1\n" " // f line 2\n" " f();\n" "} else { // else line 1\n" " // else line 2\n" " // else line 3\n" " // g line 1\n" " g();\n" "}", format("if (1) { // if line 1\n" " // if line 2\n" " // if line 3\n" " // f line 1\n" " // f line 2\n" " f();\n" "} else { // else line 1\n" " // else line 2\n" " // else line 3\n" " // g line 1\n" " g();\n" "}")); EXPECT_EQ("do { // line 1\n" " // line 2\n" " // line 3\n" " f();\n" "} while (true);", format("do { // line 1\n" " // line 2\n" " // line 3\n" " f();\n" "} while (true);", getLLVMStyleWithColumns(80))); EXPECT_EQ("while (a < b) { // line 1\n" " // line 2\n" " // line 3\n" " f();\n" "}", format("while (a < b) {// line 1\n" " // line 2\n" " // line 3\n" " f();\n" "}", getLLVMStyleWithColumns(80))); } TEST_F(FormatTestComments, ReflowsComments) { // Break a long line and reflow with the full next line. EXPECT_EQ("// long long long\n" "// long long", format("// long long long long\n" "// long", getLLVMStyleWithColumns(20))); // Keep the trailing newline while reflowing. EXPECT_EQ("// long long long\n" "// long long\n", format("// long long long long\n" "// long\n", getLLVMStyleWithColumns(20))); // Break a long line and reflow with a part of the next line. EXPECT_EQ("// long long long\n" "// long long\n" "// long_long", format("// long long long long\n" "// long long_long", getLLVMStyleWithColumns(20))); // Break but do not reflow if the first word from the next line is too long. EXPECT_EQ("// long long long\n" "// long\n" "// long_long_long\n", format("// long long long long\n" "// long_long_long\n", getLLVMStyleWithColumns(20))); // Don't break or reflow short lines. verifyFormat("// long\n" "// long long long lo\n" "// long long long lo\n" "// long", getLLVMStyleWithColumns(20)); // Keep prefixes and decorations while reflowing. EXPECT_EQ("/// long long long\n" "/// long long\n", format("/// long long long long\n" "/// long\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("//! long long long\n" "//! long long\n", format("//! long long long long\n" "//! long\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* long long long\n" " * long long */", format("/* long long long long\n" " * long */", getLLVMStyleWithColumns(20))); EXPECT_EQ("///< long long long\n" "///< long long\n", format("///< long long long long\n" "///< long\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("//!< long long long\n" "//!< long long\n", format("//!< long long long long\n" "//!< long\n", getLLVMStyleWithColumns(20))); // Don't bring leading whitespace up while reflowing. EXPECT_EQ("/* long long long\n" " * long long long\n" " */", format("/* long long long long\n" " * long long\n" " */", getLLVMStyleWithColumns(20))); // Reflow the last line of a block comment with its trailing '*/'. EXPECT_EQ("/* long long long\n" " long long */", format("/* long long long long\n" " long */", getLLVMStyleWithColumns(20))); // Reflow two short lines; keep the postfix of the last one. EXPECT_EQ("/* long long long\n" " * long long long */", format("/* long long long long\n" " * long\n" " * long */", getLLVMStyleWithColumns(20))); // Put the postfix of the last short reflow line on a newline if it doesn't // fit. EXPECT_EQ("/* long long long\n" " * long long longg\n" " */", format("/* long long long long\n" " * long\n" " * longg */", getLLVMStyleWithColumns(20))); // Reflow lines with leading whitespace. EXPECT_EQ("{\n" " /*\n" " * long long long\n" " * long long long\n" " * long long long\n" " */\n" "}", format("{\n" "/*\n" " * long long long long\n" " * long\n" " * long long long long\n" " */\n" "}", getLLVMStyleWithColumns(20))); // Break single line block comments that are first in the line with ' *' // decoration. EXPECT_EQ("/* long long long\n" " * long */", format("/* long long long long */", getLLVMStyleWithColumns(20))); // Break single line block comment that are not first in the line with ' ' // decoration. EXPECT_EQ("int i; /* long long\n" " long */", format("int i; /* long long long */", getLLVMStyleWithColumns(20))); // Reflow a line that goes just over the column limit. EXPECT_EQ("// long long long\n" "// lon long", format("// long long long lon\n" "// long", getLLVMStyleWithColumns(20))); // Stop reflowing if the next line has a different indentation than the // previous line. EXPECT_EQ("// long long long\n" "// long\n" "// long long\n" "// long", format("// long long long long\n" "// long long\n" "// long", getLLVMStyleWithColumns(20))); // Reflow into the last part of a really long line that has been broken into // multiple lines. EXPECT_EQ("// long long long\n" "// long long long\n" "// long long long\n", format("// long long long long long long long long\n" "// long\n", getLLVMStyleWithColumns(20))); // Break the first line, then reflow the beginning of the second and third // line up. EXPECT_EQ("// long long long\n" "// lon1 lon2 lon2\n" "// lon2 lon3 lon3", format("// long long long lon1\n" "// lon2 lon2 lon2\n" "// lon3 lon3", getLLVMStyleWithColumns(20))); // Reflow the beginning of the second line, then break the rest. EXPECT_EQ("// long long long\n" "// lon1 lon2 lon2\n" "// lon2 lon2 lon2\n" "// lon3", format("// long long long lon1\n" "// lon2 lon2 lon2 lon2 lon2 lon3", getLLVMStyleWithColumns(20))); // Shrink the first line, then reflow the second line up. EXPECT_EQ("// long long long", format("// long long\n" "// long", getLLVMStyleWithColumns(20))); // Don't shrink leading whitespace. EXPECT_EQ("int i; /// a", format("int i; /// a", getLLVMStyleWithColumns(20))); // Shrink trailing whitespace if there is no postfix and reflow. EXPECT_EQ("// long long long\n" "// long long", format("// long long long long \n" "// long", getLLVMStyleWithColumns(20))); // Shrink trailing whitespace to a single one if there is postfix. EXPECT_EQ("/* long long long */", format("/* long long long */", getLLVMStyleWithColumns(20))); // Break a block comment postfix if exceeding the line limit. EXPECT_EQ("/* long\n" " */", format("/* long */", getLLVMStyleWithColumns(20))); // Reflow indented comments. EXPECT_EQ("{\n" " // long long long\n" " // long long\n" " int i; /* long lon\n" " g long\n" " */\n" "}", format("{\n" " // long long long long\n" " // long\n" " int i; /* long lon g\n" " long */\n" "}", getLLVMStyleWithColumns(20))); // Don't realign trailing comments after reflow has happened. EXPECT_EQ("// long long long\n" "// long long\n" "long i; // long", format("// long long long long\n" "// long\n" "long i; // long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// long long long\n" "// longng long long\n" "// long lo", format("// long long long longng\n" "// long long long\n" "// lo", getLLVMStyleWithColumns(20))); // Reflow lines after a broken line. EXPECT_EQ("int a; // Trailing\n" " // comment on\n" " // 2 or 3\n" " // lines.\n", format("int a; // Trailing comment\n" " // on 2\n" " // or 3\n" " // lines.\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("/// This long line\n" "/// gets reflown.\n", format("/// This long line gets\n" "/// reflown.\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("//! This long line\n" "//! gets reflown.\n", format(" //! This long line gets\n" " //! reflown.\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* This long line\n" " * gets reflown.\n" " */\n", format("/* This long line gets\n" " * reflown.\n" " */\n", getLLVMStyleWithColumns(20))); // Reflow after indentation makes a line too long. EXPECT_EQ("{\n" " // long long long\n" " // lo long\n" "}\n", format("{\n" "// long long long lo\n" "// long\n" "}\n", getLLVMStyleWithColumns(20))); // Break and reflow multiple lines. EXPECT_EQ("/*\n" " * Reflow the end of\n" " * line by 11 22 33\n" " * 4.\n" " */\n", format("/*\n" " * Reflow the end of line\n" " * by\n" " * 11\n" " * 22\n" " * 33\n" " * 4.\n" " */\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("/// First line gets\n" "/// broken. Second\n" "/// line gets\n" "/// reflown and\n" "/// broken. Third\n" "/// gets reflown.\n", format("/// First line gets broken.\n" "/// Second line gets reflown and broken.\n" "/// Third gets reflown.\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("int i; // first long\n" " // long snd\n" " // long.\n", format("int i; // first long long\n" " // snd long.\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("{\n" " // first long line\n" " // line second\n" " // long line line\n" " // third long line\n" " // line\n" "}\n", format("{\n" " // first long line line\n" " // second long line line\n" " // third long line line\n" "}\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("int i; /* first line\n" " * second\n" " * line third\n" " * line\n" " */", format("int i; /* first line\n" " * second line\n" " * third line\n" " */", getLLVMStyleWithColumns(20))); // Reflow the last two lines of a section that starts with a line having // different indentation. EXPECT_EQ("// long\n" "// long long long\n" "// long long", format("// long\n" "// long long long long\n" "// long", getLLVMStyleWithColumns(20))); // Keep the block comment endling '*/' while reflowing. EXPECT_EQ("/* Long long long\n" " * line short */\n", format("/* Long long long line\n" " * short */\n", getLLVMStyleWithColumns(20))); // Don't reflow between separate blocks of comments. EXPECT_EQ("/* First comment\n" " * block will */\n" "/* Snd\n" " */\n", format("/* First comment block\n" " * will */\n" "/* Snd\n" " */\n", getLLVMStyleWithColumns(20))); // Don't reflow across blank comment lines. EXPECT_EQ("int i; // This long\n" " // line gets\n" " // broken.\n" " //\n" " // keep.\n", format("int i; // This long line gets broken.\n" " // \n" " // keep.\n", getLLVMStyleWithColumns(20))); EXPECT_EQ("{\n" " /// long long long\n" " /// long long\n" " ///\n" " /// long\n" "}", format("{\n" " /// long long long long\n" " /// long\n" " ///\n" " /// long\n" "}", getLLVMStyleWithColumns(20))); EXPECT_EQ("//! long long long\n" "//! long\n" "\n" "//! long", format("//! long long long long\n" "\n" "//! long", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* long long long\n" " long\n" "\n" " long */", format("/* long long long long\n" "\n" " long */", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* long long long\n" " * long\n" " *\n" " * long */", format("/* long long long long\n" " *\n" " * long */", getLLVMStyleWithColumns(20))); // Don't reflow lines having content that is a single character. EXPECT_EQ("// long long long\n" "// long\n" "// l", format("// long long long long\n" "// l", getLLVMStyleWithColumns(20))); // Don't reflow lines starting with two punctuation characters. EXPECT_EQ("// long long long\n" "// long\n" "// ... --- ...", format("// long long long long\n" "// ... --- ...", getLLVMStyleWithColumns(20))); // Don't reflow lines starting with '@'. EXPECT_EQ("// long long long\n" "// long\n" "// @param arg", format("// long long long long\n" "// @param arg", getLLVMStyleWithColumns(20))); // Don't reflow lines starting with 'TODO'. EXPECT_EQ("// long long long\n" "// long\n" "// TODO: long", format("// long long long long\n" "// TODO: long", getLLVMStyleWithColumns(20))); // Don't reflow lines starting with 'FIXME'. EXPECT_EQ("// long long long\n" "// long\n" "// FIXME: long", format("// long long long long\n" "// FIXME: long", getLLVMStyleWithColumns(20))); // Don't reflow lines starting with 'XXX'. EXPECT_EQ("// long long long\n" "// long\n" "// XXX: long", format("// long long long long\n" "// XXX: long", getLLVMStyleWithColumns(20))); // Don't reflow comment pragmas. EXPECT_EQ("// long long long\n" "// long\n" "// IWYU pragma:", format("// long long long long\n" "// IWYU pragma:", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* long long long\n" " * long\n" " * IWYU pragma:\n" " */", format("/* long long long long\n" " * IWYU pragma:\n" " */", getLLVMStyleWithColumns(20))); // Reflow lines that have a non-punctuation character among their first 2 // characters. EXPECT_EQ("// long long long\n" "// long 'long'", format("// long long long long\n" "// 'long'", getLLVMStyleWithColumns(20))); // Don't reflow between separate blocks of comments. EXPECT_EQ("/* First comment\n" " * block will */\n" "/* Snd\n" " */\n", format("/* First comment block\n" " * will */\n" "/* Snd\n" " */\n", getLLVMStyleWithColumns(20))); // Don't reflow lines having different indentation. EXPECT_EQ("// long long long\n" "// long\n" "// long", format("// long long long long\n" "// long", getLLVMStyleWithColumns(20))); // Don't reflow separate bullets in list EXPECT_EQ("// - long long long\n" "// long\n" "// - long", format("// - long long long long\n" "// - long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// * long long long\n" "// long\n" "// * long", format("// * long long long long\n" "// * long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// + long long long\n" "// long\n" "// + long", format("// + long long long long\n" "// + long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// 1. long long long\n" "// long\n" "// 2. long", format("// 1. long long long long\n" "// 2. long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// -# long long long\n" "// long\n" "// -# long", format("// -# long long long long\n" "// -# long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// - long long long\n" "// long long long\n" "// - long", format("// - long long long long\n" "// long long\n" "// - long", getLLVMStyleWithColumns(20))); EXPECT_EQ("// - long long long\n" "// long long long\n" "// long\n" "// - long", format("// - long long long long\n" "// long long long\n" "// - long", getLLVMStyleWithColumns(20))); // Large number (>2 digits) are not list items EXPECT_EQ("// long long long\n" "// long 1024. long.", format("// long long long long\n" "// 1024. long.", getLLVMStyleWithColumns(20))); // Do not break before number, to avoid introducing a non-reflowable doxygen // list item. EXPECT_EQ("// long long\n" "// long 10. long.", format("// long long long 10.\n" "// long.", getLLVMStyleWithColumns(20))); // Don't break or reflow after implicit string literals. verifyFormat("#include // l l l\n" " // l", getLLVMStyleWithColumns(20)); // Don't break or reflow comments on import lines. EXPECT_EQ("#include \"t\" /* l l l\n" " * l */", format("#include \"t\" /* l l l\n" " * l */", getLLVMStyleWithColumns(20))); // Don't reflow between different trailing comment sections. EXPECT_EQ("int i; // long long\n" " // long\n" "int j; // long long\n" " // long\n", format("int i; // long long long\n" "int j; // long long long\n", getLLVMStyleWithColumns(20))); // Don't reflow if the first word on the next line is longer than the // available space at current line. EXPECT_EQ("int i; // trigger\n" " // reflow\n" " // longsec\n", format("int i; // trigger reflow\n" " // longsec\n", getLLVMStyleWithColumns(20))); // Simple case that correctly handles reflow in parameter lists. EXPECT_EQ("a = f(/* looooooooong\n" " * long long\n" " */\n" " a);", format("a = f(/* looooooooong long\n* long\n*/ a);", getLLVMStyleWithColumns(22))); // Tricky case that has fewer lines if we reflow the comment, ending up with // fewer lines. EXPECT_EQ("a = f(/* loooooong\n" " * long long\n" " */\n" " a);", format("a = f(/* loooooong long\n* long\n*/ a);", getLLVMStyleWithColumns(22))); // Keep empty comment lines. EXPECT_EQ("/**/", format(" /**/", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* */", format(" /* */", getLLVMStyleWithColumns(20))); EXPECT_EQ("/* */", format(" /* */", getLLVMStyleWithColumns(20))); EXPECT_EQ("//", format(" // ", getLLVMStyleWithColumns(20))); EXPECT_EQ("///", format(" /// ", getLLVMStyleWithColumns(20))); } TEST_F(FormatTestComments, ReflowsCommentsPrecise) { // FIXME: This assumes we do not continue compressing whitespace once we are // in reflow mode. Consider compressing whitespace. // Test that we stop reflowing precisely at the column limit. // After reflowing, "// reflows into foo" does not fit the column limit, // so we compress the whitespace. EXPECT_EQ("// some text that\n" "// reflows into foo\n", format("// some text that reflows\n" "// into foo\n", getLLVMStyleWithColumns(20))); // Given one more column, "// reflows into foo" does fit the limit, so we // do not compress the whitespace. EXPECT_EQ("// some text that\n" "// reflows into foo\n", format("// some text that reflows\n" "// into foo\n", getLLVMStyleWithColumns(21))); // Make sure that we correctly account for the space added in the reflow case // when making the reflowing decision. // First, when the next line ends precisely one column over the limit, do not // reflow. EXPECT_EQ("// some text that\n" "// reflows\n" "// into1234567\n", format("// some text that reflows\n" "// into1234567\n", getLLVMStyleWithColumns(21))); // Secondly, when the next line ends later, but the first word in that line // is precisely one column over the limit, do not reflow. EXPECT_EQ("// some text that\n" "// reflows\n" "// into1234567 f\n", format("// some text that reflows\n" "// into1234567 f\n", getLLVMStyleWithColumns(21))); } TEST_F(FormatTestComments, ReflowsCommentsWithExtraWhitespace) { // Baseline. EXPECT_EQ("// some text\n" "// that re flows\n", format("// some text that\n" "// re flows\n", getLLVMStyleWithColumns(16))); EXPECT_EQ("// some text\n" "// that re flows\n", format("// some text that\n" "// re flows\n", getLLVMStyleWithColumns(16))); EXPECT_EQ("/* some text\n" " * that re flows\n" " */\n", format("/* some text that\n" "* re flows\n" "*/\n", getLLVMStyleWithColumns(16))); // FIXME: We do not reflow if the indent of two subsequent lines differs; // given that this is different behavior from block comments, do we want // to keep this? EXPECT_EQ("// some text\n" "// that\n" "// re flows\n", format("// some text that\n" "// re flows\n", getLLVMStyleWithColumns(16))); // Space within parts of a line that fit. // FIXME: Use the earliest possible split while reflowing to compress the // whitespace within the line. EXPECT_EQ("// some text that\n" "// does re flow\n" "// more here\n", format("// some text that does\n" "// re flow more here\n", getLLVMStyleWithColumns(21))); } TEST_F(FormatTestComments, IgnoresIf0Contents) { EXPECT_EQ("#if 0\n" "}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n" "#endif\n" "void f() {}", format("#if 0\n" "}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n" "#endif\n" "void f( ) { }")); EXPECT_EQ("#if false\n" "void f( ) { }\n" "#endif\n" "void g() {}\n", format("#if false\n" "void f( ) { }\n" "#endif\n" "void g( ) { }\n")); EXPECT_EQ("enum E {\n" " One,\n" " Two,\n" "#if 0\n" "Three,\n" " Four,\n" "#endif\n" " Five\n" "};", format("enum E {\n" " One,Two,\n" "#if 0\n" "Three,\n" " Four,\n" "#endif\n" " Five};")); EXPECT_EQ("enum F {\n" " One,\n" "#if 1\n" " Two,\n" "#if 0\n" "Three,\n" " Four,\n" "#endif\n" " Five\n" "#endif\n" "};", format("enum F {\n" "One,\n" "#if 1\n" "Two,\n" "#if 0\n" "Three,\n" " Four,\n" "#endif\n" "Five\n" "#endif\n" "};")); EXPECT_EQ("enum G {\n" " One,\n" "#if 0\n" "Two,\n" "#else\n" " Three,\n" "#endif\n" " Four\n" "};", format("enum G {\n" "One,\n" "#if 0\n" "Two,\n" "#else\n" "Three,\n" "#endif\n" "Four\n" "};")); EXPECT_EQ("enum H {\n" " One,\n" "#if 0\n" "#ifdef Q\n" "Two,\n" "#else\n" "Three,\n" "#endif\n" "#endif\n" " Four\n" "};", format("enum H {\n" "One,\n" "#if 0\n" "#ifdef Q\n" "Two,\n" "#else\n" "Three,\n" "#endif\n" "#endif\n" "Four\n" "};")); EXPECT_EQ("enum I {\n" " One,\n" "#if /* test */ 0 || 1\n" "Two,\n" "Three,\n" "#endif\n" " Four\n" "};", format("enum I {\n" "One,\n" "#if /* test */ 0 || 1\n" "Two,\n" "Three,\n" "#endif\n" "Four\n" "};")); EXPECT_EQ("enum J {\n" " One,\n" "#if 0\n" "#if 0\n" "Two,\n" "#else\n" "Three,\n" "#endif\n" "Four,\n" "#endif\n" " Five\n" "};", format("enum J {\n" "One,\n" "#if 0\n" "#if 0\n" "Two,\n" "#else\n" "Three,\n" "#endif\n" "Four,\n" "#endif\n" "Five\n" "};")); // Ignore stuff in SWIG-blocks. EXPECT_EQ("#ifdef SWIG\n" "}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n" "#endif\n" "void f() {}", format("#ifdef SWIG\n" "}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n" "#endif\n" "void f( ) { }")); EXPECT_EQ("#ifndef SWIG\n" "void f() {}\n" "#endif", format("#ifndef SWIG\n" "void f( ) { }\n" "#endif")); } TEST_F(FormatTestComments, DontCrashOnBlockComments) { EXPECT_EQ( "int xxxxxxxxx; /* " "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\n" "zzzzzz\n" "0*/", format("int xxxxxxxxx; /* " "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy zzzzzz\n" "0*/")); } TEST_F(FormatTestComments, BlockCommentsInControlLoops) { verifyFormat("if (0) /* a comment in a strange place */ {\n" " f();\n" "}"); verifyFormat("if (0) /* a comment in a strange place */ {\n" " f();\n" "} /* another comment */ else /* comment #3 */ {\n" " g();\n" "}"); verifyFormat("while (0) /* a comment in a strange place */ {\n" " f();\n" "}"); verifyFormat("for (;;) /* a comment in a strange place */ {\n" " f();\n" "}"); verifyFormat("do /* a comment in a strange place */ {\n" " f();\n" "} /* another comment */ while (0);"); } TEST_F(FormatTestComments, BlockComments) { EXPECT_EQ("/* */ /* */ /* */\n/* */ /* */ /* */", format("/* *//* */ /* */\n/* *//* */ /* */")); EXPECT_EQ("/* */ a /* */ b;", format(" /* */ a/* */ b;")); EXPECT_EQ("#define A /*123*/ \\\n" " b\n" "/* */\n" "someCall(\n" " parameter);", format("#define A /*123*/ b\n" "/* */\n" "someCall(parameter);", getLLVMStyleWithColumns(15))); EXPECT_EQ("#define A\n" "/* */ someCall(\n" " parameter);", format("#define A\n" "/* */someCall(parameter);", getLLVMStyleWithColumns(15))); EXPECT_EQ("/*\n**\n*/", format("/*\n**\n*/")); EXPECT_EQ("/*\n" " *\n" " * aaaaaa\n" " * aaaaaa\n" " */", format("/*\n" "*\n" " * aaaaaa aaaaaa\n" "*/", getLLVMStyleWithColumns(10))); EXPECT_EQ("/*\n" "**\n" "* aaaaaa\n" "*aaaaaa\n" "*/", format("/*\n" "**\n" "* aaaaaa aaaaaa\n" "*/", getLLVMStyleWithColumns(10))); EXPECT_EQ("int aaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" " /* line 1\n" " bbbbbbbbbbbb */\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbb;", format("int aaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" " /* line 1\n" " bbbbbbbbbbbb */ bbbbbbbbbbbbbbbbbbbbbbbbbbbb;", getLLVMStyleWithColumns(50))); FormatStyle NoBinPacking = getLLVMStyle(); NoBinPacking.BinPackParameters = false; EXPECT_EQ("someFunction(1, /* comment 1 */\n" " 2, /* comment 2 */\n" " 3, /* comment 3 */\n" " aaaa,\n" " bbbb);", format("someFunction (1, /* comment 1 */\n" " 2, /* comment 2 */ \n" " 3, /* comment 3 */\n" "aaaa, bbbb );", NoBinPacking)); verifyFormat( "bool aaaaaaaaaaaaa = /* comment: */ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaa;"); EXPECT_EQ( "bool aaaaaaaaaaaaa = /* trailing comment */\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaa ||\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaa;", format( "bool aaaaaaaaaaaaa = /* trailing comment */\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaa||aaaaaaaaaaaaaaaaaaaaaaaaa ||\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaa;")); EXPECT_EQ( "int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; /* comment */\n" "int bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; /* comment */\n" "int cccccccccccccccccccccccccccccc; /* comment */\n", format("int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; /* comment */\n" "int bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; /* comment */\n" "int cccccccccccccccccccccccccccccc; /* comment */\n")); verifyFormat("void f(int * /* unused */) {}"); EXPECT_EQ("/*\n" " **\n" " */", format("/*\n" " **\n" " */")); EXPECT_EQ("/*\n" " *q\n" " */", format("/*\n" " *q\n" " */")); EXPECT_EQ("/*\n" " * q\n" " */", format("/*\n" " * q\n" " */")); EXPECT_EQ("/*\n" " **/", format("/*\n" " **/")); EXPECT_EQ("/*\n" " ***/", format("/*\n" " ***/")); } TEST_F(FormatTestComments, BlockCommentsInMacros) { EXPECT_EQ("#define A \\\n" " { \\\n" " /* one line */ \\\n" " someCall();", format("#define A { \\\n" " /* one line */ \\\n" " someCall();", getLLVMStyleWithColumns(20))); EXPECT_EQ("#define A \\\n" " { \\\n" " /* previous */ \\\n" " /* one line */ \\\n" " someCall();", format("#define A { \\\n" " /* previous */ \\\n" " /* one line */ \\\n" " someCall();", getLLVMStyleWithColumns(20))); } TEST_F(FormatTestComments, BlockCommentsAtEndOfLine) { EXPECT_EQ("a = {\n" " 1111 /* */\n" "};", format("a = {1111 /* */\n" "};", getLLVMStyleWithColumns(15))); EXPECT_EQ("a = {\n" " 1111 /* */\n" "};", format("a = {1111 /* */\n" "};", getLLVMStyleWithColumns(15))); EXPECT_EQ("a = {\n" " 1111 /* a\n" " */\n" "};", format("a = {1111 /* a */\n" "};", getLLVMStyleWithColumns(15))); } TEST_F(FormatTestComments, BreaksAfterMultilineBlockCommentsInParamLists) { EXPECT_EQ("a = f(/* long\n" " long */\n" " a);", format("a = f(/* long long */ a);", getLLVMStyleWithColumns(16))); EXPECT_EQ("a = f(\n" " /* long\n" " long */\n" " a);", format("a = f(/* long long */ a);", getLLVMStyleWithColumns(15))); EXPECT_EQ("a = f(/* long\n" " long\n" " */\n" " a);", format("a = f(/* long\n" " long\n" " */a);", getLLVMStyleWithColumns(16))); EXPECT_EQ("a = f(/* long\n" " long\n" " */\n" " a);", format("a = f(/* long\n" " long\n" " */ a);", getLLVMStyleWithColumns(16))); EXPECT_EQ("a = f(/* long\n" " long\n" " */\n" " (1 + 1));", format("a = f(/* long\n" " long\n" " */ (1 + 1));", getLLVMStyleWithColumns(16))); EXPECT_EQ( "a = f(a,\n" " /* long\n" " long */\n" " b);", format("a = f(a, /* long long */ b);", getLLVMStyleWithColumns(16))); EXPECT_EQ( "a = f(\n" " a,\n" " /* long\n" " long */\n" " b);", format("a = f(a, /* long long */ b);", getLLVMStyleWithColumns(15))); EXPECT_EQ("a = f(a,\n" " /* long\n" " long */\n" " (1 + 1));", format("a = f(a, /* long long */ (1 + 1));", getLLVMStyleWithColumns(16))); EXPECT_EQ("a = f(\n" " a,\n" " /* long\n" " long */\n" " (1 + 1));", format("a = f(a, /* long long */ (1 + 1));", getLLVMStyleWithColumns(15))); } TEST_F(FormatTestComments, IndentLineCommentsInStartOfBlockAtEndOfFile) { verifyFormat("{\n" " // a\n" " // b"); } TEST_F(FormatTestComments, AlignTrailingComments) { EXPECT_EQ("#define MACRO(V) \\\n" " V(Rt2) /* one more char */ \\\n" " V(Rs) /* than here */ \\\n" "/* comment 3 */\n", format("#define MACRO(V)\\\n" "V(Rt2) /* one more char */ \\\n" "V(Rs) /* than here */ \\\n" "/* comment 3 */\n", getLLVMStyleWithColumns(40))); EXPECT_EQ("int i = f(abc, // line 1\n" " d, // line 2\n" " // line 3\n" " b);", format("int i = f(abc, // line 1\n" " d, // line 2\n" " // line 3\n" " b);", getLLVMStyleWithColumns(40))); // Align newly broken trailing comments. EXPECT_EQ("int ab; // line\n" "int a; // long\n" " // long\n", format("int ab; // line\n" "int a; // long long\n", getLLVMStyleWithColumns(15))); EXPECT_EQ("int ab; // line\n" "int a; // long\n" " // long\n" " // long", format("int ab; // line\n" "int a; // long long\n" " // long", getLLVMStyleWithColumns(15))); EXPECT_EQ("int ab; // line\n" "int a; // long\n" " // long\n" "pt c; // long", format("int ab; // line\n" "int a; // long long\n" "pt c; // long", getLLVMStyleWithColumns(15))); EXPECT_EQ("int ab; // line\n" "int a; // long\n" " // long\n" "\n" "// long", format("int ab; // line\n" "int a; // long long\n" "\n" "// long", getLLVMStyleWithColumns(15))); // Don't align newly broken trailing comments if that would put them over the // column limit. EXPECT_EQ("int i, j; // line 1\n" "int k; // line longg\n" " // long", format("int i, j; // line 1\n" "int k; // line longg long", getLLVMStyleWithColumns(20))); // Always align if ColumnLimit = 0 EXPECT_EQ("int i, j; // line 1\n" "int k; // line longg long", format("int i, j; // line 1\n" "int k; // line longg long", getLLVMStyleWithColumns(0))); // Align comment line sections aligned with the next token with the next // token. EXPECT_EQ("class A {\n" "public: // public comment\n" " // comment about a\n" " int a;\n" "};", format("class A {\n" "public: // public comment\n" " // comment about a\n" " int a;\n" "};", getLLVMStyleWithColumns(40))); EXPECT_EQ("class A {\n" "public: // public comment 1\n" " // public comment 2\n" " // comment 1 about a\n" " // comment 2 about a\n" " int a;\n" "};", format("class A {\n" "public: // public comment 1\n" " // public comment 2\n" " // comment 1 about a\n" " // comment 2 about a\n" " int a;\n" "};", getLLVMStyleWithColumns(40))); EXPECT_EQ("int f(int n) { // comment line 1 on f\n" " // comment line 2 on f\n" " // comment line 1 before return\n" " // comment line 2 before return\n" " return n; // comment line 1 on return\n" " // comment line 2 on return\n" " // comment line 1 after return\n" "}", format("int f(int n) { // comment line 1 on f\n" " // comment line 2 on f\n" " // comment line 1 before return\n" " // comment line 2 before return\n" " return n; // comment line 1 on return\n" " // comment line 2 on return\n" " // comment line 1 after return\n" "}", getLLVMStyleWithColumns(40))); EXPECT_EQ("int f(int n) {\n" " switch (n) { // comment line 1 on switch\n" " // comment line 2 on switch\n" " // comment line 1 before case 1\n" " // comment line 2 before case 1\n" " case 1: // comment line 1 on case 1\n" " // comment line 2 on case 1\n" " // comment line 1 before return 1\n" " // comment line 2 before return 1\n" " return 1; // comment line 1 on return 1\n" " // comment line 2 on return 1\n" " // comment line 1 before default\n" " // comment line 2 before default\n" " default: // comment line 1 on default\n" " // comment line 2 on default\n" " // comment line 1 before return 2\n" " return 2 * f(n - 1); // comment line 1 on return 2\n" " // comment line 2 on return 2\n" " // comment line 1 after return\n" " // comment line 2 after return\n" " }\n" "}", format("int f(int n) {\n" " switch (n) { // comment line 1 on switch\n" " // comment line 2 on switch\n" " // comment line 1 before case 1\n" " // comment line 2 before case 1\n" " case 1: // comment line 1 on case 1\n" " // comment line 2 on case 1\n" " // comment line 1 before return 1\n" " // comment line 2 before return 1\n" " return 1; // comment line 1 on return 1\n" " // comment line 2 on return 1\n" " // comment line 1 before default\n" " // comment line 2 before default\n" " default: // comment line 1 on default\n" " // comment line 2 on default\n" " // comment line 1 before return 2\n" " return 2 * f(n - 1); // comment line 1 on return 2\n" " // comment line 2 on return 2\n" " // comment line 1 after return\n" " // comment line 2 after return\n" " }\n" "}", getLLVMStyleWithColumns(80))); // If all the lines in a sequence of line comments are aligned with the next // token, the first line belongs to the previous token and the other lines // belong to the next token. EXPECT_EQ("int a; // line about a\n" "long b;", format("int a; // line about a\n" " long b;", getLLVMStyleWithColumns(80))); EXPECT_EQ("int a; // line about a\n" "// line about b\n" "long b;", format("int a; // line about a\n" " // line about b\n" " long b;", getLLVMStyleWithColumns(80))); EXPECT_EQ("int a; // line about a\n" "// line 1 about b\n" "// line 2 about b\n" "long b;", format("int a; // line about a\n" " // line 1 about b\n" " // line 2 about b\n" " long b;", getLLVMStyleWithColumns(80))); // Checks an edge case in preprocessor handling. // These comments should *not* be aligned EXPECT_NE( // change for EQ when fixed "#if FOO\n" "#else\n" "long a; // Line about a\n" "#endif\n" "#if BAR\n" "#else\n" "long b_long_name; // Line about b\n" "#endif\n", format("#if FOO\n" "#else\n" "long a; // Line about a\n" // Previous (bad) behavior "#endif\n" "#if BAR\n" "#else\n" "long b_long_name; // Line about b\n" "#endif\n", getLLVMStyleWithColumns(80))); // bug 47589 EXPECT_EQ( "namespace m {\n\n" "#define FOO_GLOBAL 0 // Global scope.\n" "#define FOO_LINKLOCAL 1 // Link-local scope.\n" "#define FOO_SITELOCAL 2 // Site-local scope (deprecated).\n" "#define FOO_UNIQUELOCAL 3 // Unique local\n" "#define FOO_NODELOCAL 4 // Loopback\n\n" "} // namespace m\n", format("namespace m {\n\n" "#define FOO_GLOBAL 0 // Global scope.\n" "#define FOO_LINKLOCAL 1 // Link-local scope.\n" "#define FOO_SITELOCAL 2 // Site-local scope (deprecated).\n" "#define FOO_UNIQUELOCAL 3 // Unique local\n" "#define FOO_NODELOCAL 4 // Loopback\n\n" "} // namespace m\n", 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))); } TEST_F(FormatTestComments, NoCrash_Bug34236) { // This is a test case from a crasher reported in: // https://bugs.llvm.org/show_bug.cgi?id=34236 // Temporarily disable formatting for readability. // clang-format off EXPECT_EQ( "/* */ /*\n" " * a\n" " * b c d*/", format( "/* */ /*\n" " * a b\n" " * c d*/", getLLVMStyleWithColumns(80))); // clang-format on } TEST_F(FormatTestComments, NonTrailingBlockComments) { verifyFormat("const /** comment comment */ A = B;", getLLVMStyleWithColumns(40)); verifyFormat("const /** comment comment comment */ A =\n" " B;", getLLVMStyleWithColumns(40)); EXPECT_EQ("const /** comment comment comment\n" " comment */\n" " A = B;", format("const /** comment comment comment comment */\n" " A = B;", getLLVMStyleWithColumns(40))); } TEST_F(FormatTestComments, PythonStyleComments) { // Keeps a space after '#'. EXPECT_EQ("# comment\n" "key: value", format("#comment\n" "key:value", getTextProtoStyleWithColumns(20))); EXPECT_EQ("# comment\n" "key: value", format("# comment\n" "key:value", getTextProtoStyleWithColumns(20))); // Breaks long comment. EXPECT_EQ("# comment comment\n" "# comment\n" "key: value", format("# comment comment comment\n" "key:value", getTextProtoStyleWithColumns(20))); // Indents comments. EXPECT_EQ("data {\n" " # comment comment\n" " # comment\n" " key: value\n" "}", format("data {\n" "# comment comment comment\n" "key: value}", getTextProtoStyleWithColumns(20))); EXPECT_EQ("data {\n" " # comment comment\n" " # comment\n" " key: value\n" "}", format("data {# comment comment comment\n" "key: value}", getTextProtoStyleWithColumns(20))); // Reflows long comments. EXPECT_EQ("# comment comment\n" "# comment comment\n" "key: value", format("# comment comment comment\n" "# comment\n" "key:value", getTextProtoStyleWithColumns(20))); // Breaks trailing comments. EXPECT_EQ("k: val # comment\n" " # comment\n" "a: 1", format("k:val#comment comment\n" "a:1", getTextProtoStyleWithColumns(20))); EXPECT_EQ("id {\n" " k: val # comment\n" " # comment\n" " # line line\n" " a: 1\n" "}", format("id {k:val#comment comment\n" "# line line\n" "a:1}", getTextProtoStyleWithColumns(20))); // Aligns trailing comments. EXPECT_EQ("k: val # commen1\n" " # commen2\n" " # commen3\n" "# commen4\n" "a: 1 # commen5\n" " # commen6\n" " # commen7", format("k:val#commen1 commen2\n" " # commen3\n" "# commen4\n" "a:1#commen5 commen6\n" " #commen7", getTextProtoStyleWithColumns(20))); } TEST_F(FormatTestComments, BreaksBeforeTrailingUnbreakableSequence) { // The end of /* trail */ is exactly at 80 columns, but the unbreakable // trailing sequence ); after it exceeds the column limit. Make sure we // correctly break the line in that case. verifyFormat("int a =\n" " foo(/* trail */);", getLLVMStyleWithColumns(23)); } TEST_F(FormatTestComments, ReflowBackslashCrash) { // clang-format off EXPECT_EQ( "// How to run:\n" "// bbbbb run \\\n" "// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n" "// \\ -- --output_directory=\"\"", format( "// How to run:\n" "// bbbbb run \\\n" "// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr \\\n" "// -- --output_directory=\"\"")); // clang-format on } TEST_F(FormatTestComments, IndentsLongJavadocAnnotatedLines) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_Java); Style.ColumnLimit = 60; FormatStyle Style20 = getGoogleStyle(FormatStyle::LK_Java); Style20.ColumnLimit = 20; EXPECT_EQ( "/**\n" " * @param x long long long long long long long long long\n" " * long\n" " */\n", format("/**\n" " * @param x long long long long long long long long long long\n" " */\n", Style)); EXPECT_EQ("/**\n" " * @param x long long long long long long long long long\n" " * long long long long long long long long long long\n" " */\n", format("/**\n" " * @param x long long long long long long long long long " "long long long long long long long long long long\n" " */\n", Style)); EXPECT_EQ("/**\n" " * @param x long long long long long long long long long\n" " * long long long long long long long long long long\n" " * long\n" " */\n", format("/**\n" " * @param x long long long long long long long long long " "long long long long long long long long long long long\n" " */\n", Style)); EXPECT_EQ("/**\n" " * Sentence that\n" " * should be broken.\n" " * @param short\n" " * keep indentation\n" " */\n", format("/**\n" " * Sentence that should be broken.\n" " * @param short\n" " * keep indentation\n" " */\n", Style20)); EXPECT_EQ("/**\n" " * @param l1 long1\n" " * to break\n" " * @param l2 long2\n" " * to break\n" " */\n", format("/**\n" " * @param l1 long1 to break\n" " * @param l2 long2 to break\n" " */\n", Style20)); EXPECT_EQ("/**\n" " * @param xx to\n" " * break\n" " * no reflow\n" " */\n", format("/**\n" " * @param xx to break\n" " * no reflow\n" " */\n", Style20)); EXPECT_EQ("/**\n" " * @param xx to\n" " * break yes\n" " * reflow\n" " */\n", format("/**\n" " * @param xx to break\n" " * yes reflow\n" " */\n", Style20)); FormatStyle JSStyle20 = getGoogleStyle(FormatStyle::LK_JavaScript); JSStyle20.ColumnLimit = 20; EXPECT_EQ("/**\n" " * @param l1 long1\n" " * to break\n" " */\n", format("/**\n" " * @param l1 long1 to break\n" " */\n", JSStyle20)); EXPECT_EQ("/**\n" " * @param {l1 long1\n" " * to break}\n" " */\n", format("/**\n" " * @param {l1 long1 to break}\n" " */\n", JSStyle20)); } } // end namespace } // end namespace format } // end namespace clang