diff options
Diffstat (limited to 'unittests/Format/FormatTest.cpp')
-rw-r--r-- | unittests/Format/FormatTest.cpp | 683 |
1 files changed, 636 insertions, 47 deletions
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 2cae9dd0c547b..f234e287cf178 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -39,8 +39,8 @@ protected: std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), StatusCheck CheckComplete = SC_ExpectComplete) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -53,7 +53,7 @@ protected: ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -72,6 +72,8 @@ protected: void verifyFormat(llvm::StringRef Expected, llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { + EXPECT_EQ(Expected.str(), format(Expected, Style)) + << "Expected code is not stable"; EXPECT_EQ(Expected.str(), format(Code, Style)); if (Style.Language == FormatStyle::LK_Cpp) { // Objective-C++ is a superset of C++, so everything checked for C++ @@ -276,11 +278,12 @@ TEST_F(FormatTest, RemovesEmptyLines) { "\n" "}")); - // FIXME: This is slightly inconsistent. + // Don't remove empty lines before namespace endings. FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle(); LLVMWithNoNamespaceFix.FixNamespaceComments = false; EXPECT_EQ("namespace {\n" "int i;\n" + "\n" "}", format("namespace {\n" "int i;\n" @@ -291,6 +294,27 @@ TEST_F(FormatTest, RemovesEmptyLines) { "}", format("namespace {\n" "int i;\n" + "}", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "\n" + "};", + format("namespace {\n" + "int i;\n" + "\n" + "};", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "};", + format("namespace {\n" + "int i;\n" + "};", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "\n" + "}", + format("namespace {\n" + "int i;\n" "\n" "}")); EXPECT_EQ("namespace {\n" @@ -588,6 +612,23 @@ TEST_F(FormatTest, FormatShortBracedStatements) { AllowSimpleBracedStatements); } +TEST_F(FormatTest, ShortBlocksInMacrosDontMergeWithCodeAfterMacro) { + FormatStyle Style = getLLVMStyleWithColumns(60); + Style.AllowShortBlocksOnASingleLine = true; + Style.AllowShortIfStatementsOnASingleLine = true; + Style.BreakBeforeBraces = FormatStyle::BS_Allman; + EXPECT_EQ("#define A \\\n" + " if (HANDLEwernufrnuLwrmviferuvnierv) \\\n" + " { RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; }\n" + "X;", + format("#define A \\\n" + " if (HANDLEwernufrnuLwrmviferuvnierv) { \\\n" + " RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; \\\n" + " }\n" + "X;", + Style)); +} + TEST_F(FormatTest, ParseIfElse) { verifyFormat("if (true)\n" " if (true)\n" @@ -725,6 +766,12 @@ TEST_F(FormatTest, FormatsForLoop) { " aaaaaaaaaaaaaaaaaaaaaaaaaaa != bbbbbbbbbbbbbbbbbbbbbbb;\n" " ++aaaaaaaaaaaaaaaaaaaaaaaaaaa) {"); + // These should not be formatted as Objective-C for-in loops. + verifyFormat("for (Foo *x = 0; x != in; x++) {\n}"); + verifyFormat("Foo *x;\nfor (x = 0; x != in; x++) {\n}"); + verifyFormat("Foo *x;\nfor (x in y) {\n}"); + verifyFormat("for (const Foo<Bar> &baz = in.value(); !baz.at_end(); ++baz) {\n}"); + FormatStyle NoBinPacking = getLLVMStyle(); NoBinPacking.BinPackParameters = false; verifyFormat("for (int aaaaaaaaaaa = 1;\n" @@ -1269,15 +1316,40 @@ TEST_F(FormatTest, FormatsClasses) { verifyFormat("class ::A::B {};"); } -TEST_F(FormatTest, BreakBeforeInheritanceComma) { - FormatStyle StyleWithInheritanceBreak = getLLVMStyle(); - StyleWithInheritanceBreak.BreakBeforeInheritanceComma = true; - - verifyFormat("class MyClass : public X {};", StyleWithInheritanceBreak); +TEST_F(FormatTest, BreakInheritanceStyle) { + FormatStyle StyleWithInheritanceBreakBeforeComma = getLLVMStyle(); + StyleWithInheritanceBreakBeforeComma.BreakInheritanceList = + FormatStyle::BILS_BeforeComma; + verifyFormat("class MyClass : public X {};", + StyleWithInheritanceBreakBeforeComma); verifyFormat("class MyClass\n" " : public X\n" " , public Y {};", - StyleWithInheritanceBreak); + StyleWithInheritanceBreakBeforeComma); + verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA\n" + " : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n" + " , public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};", + StyleWithInheritanceBreakBeforeComma); + verifyFormat("struct aaaaaaaaaaaaa\n" + " : public aaaaaaaaaaaaaaaaaaa< // break\n" + " aaaaaaaaaaaaaaaa> {};", + StyleWithInheritanceBreakBeforeComma); + + FormatStyle StyleWithInheritanceBreakAfterColon = getLLVMStyle(); + StyleWithInheritanceBreakAfterColon.BreakInheritanceList = + FormatStyle::BILS_AfterColon; + verifyFormat("class MyClass : public X {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("class MyClass : public X, public Y {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA :\n" + " public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n" + " public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("struct aaaaaaaaaaaaa :\n" + " public aaaaaaaaaaaaaaaaaaa< // break\n" + " aaaaaaaaaaaaaaaa> {};", + StyleWithInheritanceBreakAfterColon); } TEST_F(FormatTest, FormatsVariableDeclarationsAfterStructOrClass) { @@ -2484,8 +2556,6 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) { "#endif", Style); // Test with include guards. - // EXPECT_EQ is used because verifyFormat() calls messUp() which incorrectly - // merges lines. verifyFormat("#ifndef HEADER_H\n" "#define HEADER_H\n" "code();\n" @@ -2532,6 +2602,20 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) { "#elif FOO\n" "#endif", Style); + // Non-identifier #define after potential include guard. + verifyFormat("#ifndef FOO\n" + "# define 1\n" + "#endif\n", + Style); + // #if closes past last non-preprocessor line. + verifyFormat("#ifndef FOO\n" + "#define FOO\n" + "#if 1\n" + "int i;\n" + "# define A 0\n" + "#endif\n" + "#endif\n", + Style); // FIXME: This doesn't handle the case where there's code between the // #ifndef and #define but all other conditions hold. This is because when // the #define line is parsed, UnwrappedLineParser::Lines doesn't hold the @@ -2580,21 +2664,85 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) { "code();\n" "#endif", Style)); - // FIXME: The comment indent corrector in TokenAnnotator gets thrown off by - // preprocessor indentation. - EXPECT_EQ("#if 1\n" - " // comment\n" - "# define A 0\n" - "// comment\n" - "# define B 0\n" - "#endif", - format("#if 1\n" - "// comment\n" - "# define A 0\n" - " // comment\n" - "# define B 0\n" - "#endif", - Style)); + // Keep comments aligned with #, otherwise indent comments normally. These + // tests cannot use verifyFormat because messUp manipulates leading + // whitespace. + { + const char *Expected = "" + "void f() {\n" + "#if 1\n" + "// Preprocessor aligned.\n" + "# define A 0\n" + " // Code. Separated by blank line.\n" + "\n" + "# define B 0\n" + " // Code. Not aligned with #\n" + "# define C 0\n" + "#endif"; + const char *ToFormat = "" + "void f() {\n" + "#if 1\n" + "// Preprocessor aligned.\n" + "# define A 0\n" + "// Code. Separated by blank line.\n" + "\n" + "# define B 0\n" + " // Code. Not aligned with #\n" + "# define C 0\n" + "#endif"; + EXPECT_EQ(Expected, format(ToFormat, Style)); + EXPECT_EQ(Expected, format(Expected, Style)); + } + // Keep block quotes aligned. + { + const char *Expected = "" + "void f() {\n" + "#if 1\n" + "/* Preprocessor aligned. */\n" + "# define A 0\n" + " /* Code. Separated by blank line. */\n" + "\n" + "# define B 0\n" + " /* Code. Not aligned with # */\n" + "# define C 0\n" + "#endif"; + const char *ToFormat = "" + "void f() {\n" + "#if 1\n" + "/* Preprocessor aligned. */\n" + "# define A 0\n" + "/* Code. Separated by blank line. */\n" + "\n" + "# define B 0\n" + " /* Code. Not aligned with # */\n" + "# define C 0\n" + "#endif"; + EXPECT_EQ(Expected, format(ToFormat, Style)); + EXPECT_EQ(Expected, format(Expected, Style)); + } + // Keep comments aligned with un-indented directives. + { + const char *Expected = "" + "void f() {\n" + "// Preprocessor aligned.\n" + "#define A 0\n" + " // Code. Separated by blank line.\n" + "\n" + "#define B 0\n" + " // Code. Not aligned with #\n" + "#define C 0\n"; + const char *ToFormat = "" + "void f() {\n" + "// Preprocessor aligned.\n" + "#define A 0\n" + "// Code. Separated by blank line.\n" + "\n" + "#define B 0\n" + " // Code. Not aligned with #\n" + "#define C 0\n"; + EXPECT_EQ(Expected, format(ToFormat, Style)); + EXPECT_EQ(Expected, format(Expected, Style)); + } // Test with tabs. Style.UseTab = FormatStyle::UT_Always; Style.IndentWidth = 8; @@ -3603,6 +3751,23 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}", Style); + + // `ConstructorInitializerIndentWidth` actually applies to InheritanceList as well + Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + verifyFormat("class SomeClass\n" + " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); + Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + verifyFormat("class SomeClass\n" + " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " , public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); + Style.BreakInheritanceList = FormatStyle::BILS_AfterColon; + verifyFormat("class SomeClass :\n" + " public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); } #ifndef EXPENSIVE_CHECKS @@ -5352,7 +5517,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { " const typename aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa);"); FormatStyle AlwaysBreak = getLLVMStyle(); - AlwaysBreak.AlwaysBreakTemplateDeclarations = true; + AlwaysBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; verifyFormat("template <typename T>\nclass C {};", AlwaysBreak); verifyFormat("template <typename T>\nvoid f();", AlwaysBreak); verifyFormat("template <typename T>\nvoid f() {}", AlwaysBreak); @@ -5370,6 +5535,83 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { "public:\n" " E *f();\n" "};"); + + FormatStyle NeverBreak = getLLVMStyle(); + NeverBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_No; + verifyFormat("template <typename T> class C {};", NeverBreak); + verifyFormat("template <typename T> void f();", NeverBreak); + verifyFormat("template <typename T> void f() {}", NeverBreak); + verifyFormat("template <typename T>\nvoid foo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}", + NeverBreak); + verifyFormat("void aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbb>(\n" + " ccccccccccccccccccccccccccccccccccccccccccccccc);", + NeverBreak); + verifyFormat("template <template <typename> class Fooooooo,\n" + " template <typename> class Baaaaaaar>\n" + "struct C {};", + NeverBreak); + verifyFormat("template <typename T> // T can be A, B or C.\n" + "struct C {};", + NeverBreak); + verifyFormat("template <enum E> class A {\n" + "public:\n" + " E *f();\n" + "};", NeverBreak); + NeverBreak.PenaltyBreakTemplateDeclaration = 100; + verifyFormat("template <typename T> void\nfoo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}", + NeverBreak); +} + +TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); + Style.ColumnLimit = 60; + EXPECT_EQ("// Baseline - no comments.\n" + "template <\n" + " typename aaaaaaaaaaaaaaaaaaaaaa<bbbbbbbbbbbb>::value>\n" + "void f() {}", + format("// Baseline - no comments.\n" + "template <\n" + " typename aaaaaaaaaaaaaaaaaaaaaa<bbbbbbbbbbbb>::value>\n" + "void f() {}", + Style)); + + EXPECT_EQ("template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + "void f() {}", + format("template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + "void f() {}", + Style)); + + EXPECT_EQ( + "template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> /* line */\n" + "void f() {}", + format("template <typename aaaaaaaaaa<bbbbbbbbbbbb>::value> /* line */\n" + "void f() {}", + Style)); + + EXPECT_EQ( + "template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + " // multiline\n" + "void f() {}", + format("template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + " // multiline\n" + "void f() {}", + Style)); + + EXPECT_EQ( + "template <typename aaaaaaaaaa<\n" + " bbbbbbbbbbbb>::value> // trailing loooong\n" + "void f() {}", + format( + "template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing loooong\n" + "void f() {}", + Style)); } TEST_F(FormatTest, WrapsTemplateParameters) { @@ -5562,6 +5804,8 @@ TEST_F(FormatTest, UnderstandsUnaryOperators) { verifyFormat("(a->f())++;"); verifyFormat("a[42]++;"); verifyFormat("if (!(a->f())) {\n}"); + verifyFormat("if (!+i) {\n}"); + verifyFormat("~&a;"); verifyFormat("a-- > b;"); verifyFormat("b ? -a : c;"); @@ -5934,6 +6178,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("delete *x;", PointerMiddle); verifyFormat("int * x;", PointerMiddle); + verifyFormat("int *[] x;", PointerMiddle); verifyFormat("template <int * y> f() {}", PointerMiddle); verifyFormat("int * f(int * a) {}", PointerMiddle); verifyFormat("int main(int argc, char ** argv) {}", PointerMiddle); @@ -5941,7 +6186,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("A<int *> a;", PointerMiddle); verifyFormat("A<int **> a;", PointerMiddle); verifyFormat("A<int *, int *> a;", PointerMiddle); - verifyFormat("A<int * []> a;", PointerMiddle); + verifyFormat("A<int *[]> a;", PointerMiddle); verifyFormat("A = new SomeType *[Length]();", PointerMiddle); verifyFormat("A = new SomeType *[Length];", PointerMiddle); verifyFormat("T ** t = new T *;", PointerMiddle); @@ -5966,6 +6211,31 @@ TEST_F(FormatTest, UnderstandsAttributes) { AfterType); } +TEST_F(FormatTest, UnderstandsSquareAttributes) { + verifyFormat("SomeType s [[unused]] (InitValue);"); + verifyFormat("SomeType s [[gnu::unused]] (InitValue);"); + verifyFormat("SomeType s [[using gnu: unused]] (InitValue);"); + verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}"); + verifyFormat("void f() [[deprecated(\"so sorry\")]];"); + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);"); + + // Make sure we do not mistake attributes for array subscripts. + verifyFormat("int a() {}\n" + "[[unused]] int b() {}\n"); + + // On the other hand, we still need to correctly find array subscripts. + verifyFormat("int a = std::vector<int>{1, 2, 3}[0];"); + + // Make sure we do not parse attributes as lambda introducers. + FormatStyle MultiLineFunctions = getLLVMStyle(); + MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + verifyFormat("[[unused]] int b() {\n" + " return 42;\n" + "}\n", + MultiLineFunctions); +} + TEST_F(FormatTest, UnderstandsEllipsis) { verifyFormat("int printf(const char *fmt, ...);"); verifyFormat("template <class... Ts> void Foo(Ts... ts) { Foo(ts...); }"); @@ -6451,6 +6721,18 @@ TEST_F(FormatTest, IncorrectCodeUnbalancedBraces) { verifyNoCrash("(/**/[:!] ?[)."); } +TEST_F(FormatTest, IncorrectUnbalancedBracesInMacrosWithUnicode) { + // Found by oss-fuzz: + // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8212 + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); + Style.ColumnLimit = 60; + verifyNoCrash( + "\x23\x47\xff\x20\x28\xff\x3c\xff\x3f\xff\x20\x2f\x7b\x7a\xff\x20" + "\xff\xff\xff\xca\xb5\xff\xff\xff\xff\x3a\x7b\x7d\xff\x20\xff\x20" + "\xff\x74\xff\x20\x7d\x7d\xff\x7b\x3a\xff\x20\x71\xff\x20\xff\x0a", + Style); +} + TEST_F(FormatTest, IncorrectCodeDoNoWhile) { verifyFormat("do {\n}"); verifyFormat("do {\n}\n" @@ -6557,6 +6839,15 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { "};"); verifyFormat("#define A {a, a},"); + // Avoid breaking between equal sign and opening brace + FormatStyle AvoidBreakingFirstArgument = getLLVMStyle(); + AvoidBreakingFirstArgument.PenaltyBreakBeforeFirstCallParameter = 200; + verifyFormat("const std::unordered_map<std::string, int> MyHashTable =\n" + " {{\"aaaaaaaaaaaaaaaaaaaaa\", 0},\n" + " {\"bbbbbbbbbbbbbbbbbbbbb\", 1},\n" + " {\"ccccccccccccccccccccc\", 2}};", + AvoidBreakingFirstArgument); + // Binpacking only if there is no trailing comma verifyFormat("const Aaaaaa aaaaa = {aaaaaaaaaa, bbbbbbbbbb,\n" " cccccccccc, dddddddddd};", @@ -6713,6 +7004,26 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { verifyFormat("vector<int> foo = { ::SomeGlobalFunction() };", ExtraSpaces); verifyFormat("const struct A a = { .a = 1, .b = 2 };", ExtraSpaces); verifyFormat("const struct A a = { [0] = 1, [1] = 2 };", ExtraSpaces); + + // Avoid breaking between initializer/equal sign and opening brace + ExtraSpaces.PenaltyBreakBeforeFirstCallParameter = 200; + verifyFormat("const std::unordered_map<std::string, int> MyHashTable = {\n" + " { \"aaaaaaaaaaaaaaaaaaaaa\", 0 },\n" + " { \"bbbbbbbbbbbbbbbbbbbbb\", 1 },\n" + " { \"ccccccccccccccccccccc\", 2 }\n" + "};", + ExtraSpaces); + verifyFormat("const std::unordered_map<std::string, int> MyHashTable{\n" + " { \"aaaaaaaaaaaaaaaaaaaaa\", 0 },\n" + " { \"bbbbbbbbbbbbbbbbbbbbb\", 1 },\n" + " { \"ccccccccccccccccccccc\", 2 }\n" + "};", + ExtraSpaces); + + FormatStyle SpaceBeforeBrace = getLLVMStyle(); + SpaceBeforeBrace.SpaceBeforeCpp11BracedList = true; + verifyFormat("vector<int> x {1, 2, 3, 4};", SpaceBeforeBrace); + verifyFormat("f({}, {{}, {}}, MyMap[{k, v}]);", SpaceBeforeBrace); } TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { @@ -7549,16 +7860,18 @@ TEST_F(FormatTest, FormatForObjectiveCMethodDecls) { // When the function name has to be wrapped. FormatStyle Style = getLLVMStyle(); + // ObjC ignores IndentWrappedFunctionNames when wrapping methods + // and always indents instead. Style.IndentWrappedFunctionNames = false; verifyFormat("- (SomeLooooooooooooooooooooongType *)\n" - "veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n" - " anotherName:(NSString)bbbbbbbbbbbbbb {\n" + " veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n" + " anotherName:(NSString)bbbbbbbbbbbbbb {\n" "}", Style); Style.IndentWrappedFunctionNames = true; verifyFormat("- (SomeLooooooooooooooooooooongType *)\n" - " veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n" - " anotherName:(NSString)bbbbbbbbbbbbbb {\n" + " veryLooooooooooongName:(NSString)cccccccccccccc\n" + " anotherName:(NSString)dddddddddddddd {\n" "}", Style); @@ -7983,6 +8296,9 @@ TEST_F(FormatTest, CountsCharactersInMultilineRawStringLiterals) { "multiline raw string literal xxxxxxxxxxxxxx\n" ")x\" + bbbbbb);", getGoogleStyleWithColumns(20))); + EXPECT_EQ("fffffffffff(R\"(single line raw string)\" + bbbbbb);", + format("fffffffffff(\n" + " R\"(single line raw string)\" + bbbbbb);")); } TEST_F(FormatTest, SkipsUnknownStringLiterals) { @@ -8704,6 +9020,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParentheses) { FormatStyle Spaces = getLLVMStyle(); Spaces.SpacesInParentheses = true; + verifyFormat("do_something( ::globalVar );", Spaces); verifyFormat("call( x, y, z );", Spaces); verifyFormat("call();", Spaces); verifyFormat("std::function<void( int, int )> callback;", Spaces); @@ -8840,6 +9157,137 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeAssignmentOperators) { verifyFormat("a or_eq 8;", Spaces); } +TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { + verifyFormat("class Foo : public Bar {};"); + verifyFormat("Foo::Foo() : foo(1) {}"); + verifyFormat("for (auto a : b) {\n}"); + verifyFormat("int x = a ? b : c;"); + verifyFormat("{\n" + "label0:\n" + " int x = 0;\n" + "}"); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}"); + + FormatStyle CtorInitializerStyle = getLLVMStyleWithColumns(30); + CtorInitializerStyle.SpaceBeforeCtorInitializerColon = false; + verifyFormat("class Foo : public Bar {};", CtorInitializerStyle); + verifyFormat("Foo::Foo(): foo(1) {}", CtorInitializerStyle); + verifyFormat("for (auto a : b) {\n}", CtorInitializerStyle); + verifyFormat("int x = a ? b : c;", CtorInitializerStyle); + verifyFormat("{\n" + "label1:\n" + " int x = 0;\n" + "}", + CtorInitializerStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + CtorInitializerStyle); + CtorInitializerStyle.BreakConstructorInitializers = + FormatStyle::BCIS_AfterColon; + verifyFormat("Fooooooooooo::Fooooooooooo():\n" + " aaaaaaaaaaaaaaaa(1),\n" + " bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + CtorInitializerStyle.BreakConstructorInitializers = + FormatStyle::BCIS_BeforeComma; + verifyFormat("Fooooooooooo::Fooooooooooo()\n" + " : aaaaaaaaaaaaaaaa(1)\n" + " , bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + CtorInitializerStyle.BreakConstructorInitializers = + FormatStyle::BCIS_BeforeColon; + verifyFormat("Fooooooooooo::Fooooooooooo()\n" + " : aaaaaaaaaaaaaaaa(1),\n" + " bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + CtorInitializerStyle.ConstructorInitializerIndentWidth = 0; + verifyFormat("Fooooooooooo::Fooooooooooo()\n" + ": aaaaaaaaaaaaaaaa(1),\n" + " bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + + FormatStyle InheritanceStyle = getLLVMStyleWithColumns(30); + InheritanceStyle.SpaceBeforeInheritanceColon = false; + verifyFormat("class Foo: public Bar {};", InheritanceStyle); + verifyFormat("Foo::Foo() : foo(1) {}", InheritanceStyle); + verifyFormat("for (auto a : b) {\n}", InheritanceStyle); + verifyFormat("int x = a ? b : c;", InheritanceStyle); + verifyFormat("{\n" + "label2:\n" + " int x = 0;\n" + "}", + InheritanceStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_AfterColon; + verifyFormat("class Foooooooooooooooooooooo:\n" + " public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + verifyFormat("class Foooooooooooooooooooooo\n" + " : public aaaaaaaaaaaaaaaaaa\n" + " , public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + verifyFormat("class Foooooooooooooooooooooo\n" + " : public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.ConstructorInitializerIndentWidth = 0; + verifyFormat("class Foooooooooooooooooooooo\n" + ": public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {}", + InheritanceStyle); + + FormatStyle ForLoopStyle = getLLVMStyle(); + ForLoopStyle.SpaceBeforeRangeBasedForLoopColon = false; + verifyFormat("class Foo : public Bar {};", ForLoopStyle); + verifyFormat("Foo::Foo() : foo(1) {}", ForLoopStyle); + verifyFormat("for (auto a: b) {\n}", ForLoopStyle); + verifyFormat("int x = a ? b : c;", ForLoopStyle); + verifyFormat("{\n" + "label2:\n" + " int x = 0;\n" + "}", + ForLoopStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + ForLoopStyle); + + FormatStyle NoSpaceStyle = getLLVMStyle(); + NoSpaceStyle.SpaceBeforeCtorInitializerColon = false; + NoSpaceStyle.SpaceBeforeInheritanceColon = false; + NoSpaceStyle.SpaceBeforeRangeBasedForLoopColon = false; + verifyFormat("class Foo: public Bar {};", NoSpaceStyle); + verifyFormat("Foo::Foo(): foo(1) {}", NoSpaceStyle); + verifyFormat("for (auto a: b) {\n}", NoSpaceStyle); + verifyFormat("int x = a ? b : c;", NoSpaceStyle); + verifyFormat("{\n" + "label3:\n" + " int x = 0;\n" + "}", + NoSpaceStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + NoSpaceStyle); +} + TEST_F(FormatTest, AlignConsecutiveAssignments) { FormatStyle Alignment = getLLVMStyle(); Alignment.AlignConsecutiveAssignments = false; @@ -10151,13 +10599,11 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine); CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine); - CHECK_PARSE_BOOL(AlwaysBreakTemplateDeclarations); CHECK_PARSE_BOOL(BinPackArguments); CHECK_PARSE_BOOL(BinPackParameters); CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations); CHECK_PARSE_BOOL(BreakBeforeTernaryOperators); CHECK_PARSE_BOOL(BreakStringLiterals); - CHECK_PARSE_BOOL(BreakBeforeInheritanceComma) CHECK_PARSE_BOOL(CompactNamespaces); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); CHECK_PARSE_BOOL(DerivePointerAlignment); @@ -10181,6 +10627,10 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(SpaceAfterCStyleCast); CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword); CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators); + CHECK_PARSE_BOOL(SpaceBeforeCpp11BracedList); + CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon); + CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon); + CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement); @@ -10214,6 +10664,8 @@ TEST_F(FormatTest, ParsesConfiguration) { PenaltyBreakAssignment, 1234u); CHECK_PARSE("PenaltyBreakBeforeFirstCallParameter: 1234", PenaltyBreakBeforeFirstCallParameter, 1234u); + CHECK_PARSE("PenaltyBreakTemplateDeclaration: 1234", + PenaltyBreakTemplateDeclaration, 1234u); CHECK_PARSE("PenaltyExcessCharacter: 1234", PenaltyExcessCharacter, 1234u); CHECK_PARSE("PenaltyReturnTypeOnItsOwnLine: 1234", PenaltyReturnTypeOnItsOwnLine, 1234u); @@ -10269,6 +10721,17 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("BreakConstructorInitializersBeforeComma: true", BreakConstructorInitializers, FormatStyle::BCIS_BeforeComma); + Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + CHECK_PARSE("BreakInheritanceList: BeforeComma", + BreakInheritanceList, FormatStyle::BILS_BeforeComma); + CHECK_PARSE("BreakInheritanceList: AfterColon", + BreakInheritanceList, FormatStyle::BILS_AfterColon); + CHECK_PARSE("BreakInheritanceList: BeforeColon", + BreakInheritanceList, FormatStyle::BILS_BeforeColon); + // For backward compatibility: + CHECK_PARSE("BreakBeforeInheritanceComma: true", + BreakInheritanceList, FormatStyle::BILS_BeforeComma); + Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; CHECK_PARSE("AlignAfterOpenBracket: Align", AlignAfterOpenBracket, FormatStyle::BAS_Align); @@ -10368,6 +10831,18 @@ TEST_F(FormatTest, ParsesConfiguration) { AlwaysBreakAfterReturnType, FormatStyle::RTBS_TopLevelDefinitions); + Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_No); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_MultiLine); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: Yes", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_Yes); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: false", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_MultiLine); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: true", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_Yes); + Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None", AlwaysBreakAfterDefinitionReturnType, FormatStyle::DRTBS_None); @@ -10397,29 +10872,52 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", ForEachMacros, BoostAndQForeach); - Style.IncludeCategories.clear(); - std::vector<FormatStyle::IncludeCategory> ExpectedCategories = {{"abc/.*", 2}, - {".*", 1}}; + Style.IncludeStyle.IncludeCategories.clear(); + std::vector<tooling::IncludeStyle::IncludeCategory> ExpectedCategories = { + {"abc/.*", 2}, {".*", 1}}; CHECK_PARSE("IncludeCategories:\n" " - Regex: abc/.*\n" " Priority: 2\n" " - Regex: .*\n" " Priority: 1", - IncludeCategories, ExpectedCategories); - CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeIsMainRegex, "abc$"); + IncludeStyle.IncludeCategories, ExpectedCategories); + CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeStyle.IncludeIsMainRegex, + "abc$"); Style.RawStringFormats.clear(); std::vector<FormatStyle::RawStringFormat> ExpectedRawStringFormats = { - {"pb", FormatStyle::LK_TextProto, "llvm"}, - {"cpp", FormatStyle::LK_Cpp, "google"}}; + { + FormatStyle::LK_TextProto, + {"pb", "proto"}, + {"PARSE_TEXT_PROTO"}, + /*CanonicalDelimiter=*/"", + "llvm", + }, + { + FormatStyle::LK_Cpp, + {"cc", "cpp"}, + {"C_CODEBLOCK", "CPPEVAL"}, + /*CanonicalDelimiter=*/"cc", + /*BasedOnStyle=*/"", + }, + }; CHECK_PARSE("RawStringFormats:\n" - " - Delimiter: 'pb'\n" - " Language: TextProto\n" + " - Language: TextProto\n" + " Delimiters:\n" + " - 'pb'\n" + " - 'proto'\n" + " EnclosingFunctions:\n" + " - 'PARSE_TEXT_PROTO'\n" " BasedOnStyle: llvm\n" - " - Delimiter: 'cpp'\n" - " Language: Cpp\n" - " BasedOnStyle: google", + " - Language: Cpp\n" + " Delimiters:\n" + " - 'cc'\n" + " - 'cpp'\n" + " EnclosingFunctions:\n" + " - 'C_CODEBLOCK'\n" + " - 'CPPEVAL'\n" + " CanonicalDelimiter: 'cc'", RawStringFormats, ExpectedRawStringFormats); } @@ -11608,6 +12106,13 @@ TEST_F(FormatTest, NoSpaceAfterSuper) { verifyFormat("__super::FooBar();"); } +TEST(FormatStyle, GetStyleWithEmptyFileName) { + vfs::InMemoryFileSystem FS; + auto Style1 = getStyle("file", "", "Google", "", &FS); + ASSERT_TRUE((bool)Style1); + ASSERT_EQ(*Style1, getGoogleStyle()); +} + TEST(FormatStyle, GetStyleOfFile) { vfs::InMemoryFileSystem FS; // Test 1: format file in the same directory. @@ -11837,6 +12342,90 @@ TEST_F(FormatTest, StructuredBindings) { verifyFormat("auto const &[ a, b ] = f();", Spaces); } +TEST_F(FormatTest, FileAndCode) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.cc", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.m", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.mm", "")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@interface Foo\n@end\n")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define TRY(x, y) @try { x; } @finally { y; }")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define AVAIL(x) @available(x, *))")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@class Foo;")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo", "@interface Foo\n@end\n")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int DoStuff(CGRect rect);\n")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", + "#define MY_POINT_MAKE(x, y) CGPointMake((x), (y));\n")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO(...) auto bar = [] __VA_ARGS__;")); +} + +TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[noreturn]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "array[[calculator getIndex]];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[noreturn, deprecated(\"so sorry\")]];")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[noreturn, deprecated(\"gone, sorry\")]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "[[noreturn foo] bar];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[clang::fallthrough]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "[[clang:fallthrough] foo];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[gsl::suppress(\"type\")]];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[using clang: fallthrough]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "[[abusing clang:fallthrough] bar];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[using gsl: suppress(\"type\")]];")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", + "[[clang::callable_when(\"unconsumed\", \"unknown\")]]")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[foo::bar, ...]]")); +} + +TEST_F(FormatTest, GuessLanguageWithCaret) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^);")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^, Bar);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^)(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo)(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[10])(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[kNumEntries])(char, float);")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);")); +} + +TEST_F(FormatTest, GuessLanguageWithChildLines) { + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO ({ std::string s; })")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define FOO ({ NSString *s; })")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO ({ foo(); ({ std::string s; }) })")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define FOO ({ foo(); ({ NSString *s; }) })")); +} + } // end namespace } // end namespace format } // end namespace clang |