| //===- unittest/Format/FormatTest.cpp - Formatting unit tests -------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Format/Format.h" |
| |
| #include "../Tooling/ReplacementTest.h" |
| #include "FormatTestUtils.h" |
| |
| #include "clang/Frontend/TextDiagnosticPrinter.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "gtest/gtest.h" |
| |
| #define DEBUG_TYPE "format-test" |
| |
| using clang::tooling::ReplacementTest; |
| using clang::tooling::toReplacements; |
| |
| namespace clang { |
| namespace format { |
| namespace { |
| |
| FormatStyle getGoogleStyle() { return getGoogleStyle(FormatStyle::LK_Cpp); } |
| |
| class FormatTest : 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<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); |
| FormattingAttemptStatus Status; |
| tooling::Replacements Replaces = |
| reformat(Style, Code, Ranges, "<stdin>", &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<bool>(Result)); |
| LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); |
| return *Result; |
| } |
| |
| FormatStyle getStyleWithColumns(FormatStyle Style, unsigned ColumnLimit) { |
| Style.ColumnLimit = ColumnLimit; |
| return Style; |
| } |
| |
| FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) { |
| return getStyleWithColumns(getLLVMStyle(), ColumnLimit); |
| } |
| |
| FormatStyle getGoogleStyleWithColumns(unsigned ColumnLimit) { |
| return getStyleWithColumns(getGoogleStyle(), ColumnLimit); |
| } |
| |
| 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++ |
| // needs to be checked for Objective-C++ as well. |
| FormatStyle ObjCStyle = Style; |
| ObjCStyle.Language = FormatStyle::LK_ObjC; |
| EXPECT_EQ(Expected.str(), format(test::messUp(Code), ObjCStyle)); |
| } |
| } |
| |
| void verifyFormat(llvm::StringRef Code, |
| const FormatStyle &Style = getLLVMStyle()) { |
| verifyFormat(Code, test::messUp(Code), Style); |
| } |
| |
| void verifyIncompleteFormat(llvm::StringRef Code, |
| const FormatStyle &Style = getLLVMStyle()) { |
| EXPECT_EQ(Code.str(), |
| format(test::messUp(Code), Style, SC_ExpectIncomplete)); |
| } |
| |
| void verifyGoogleFormat(llvm::StringRef Code) { |
| verifyFormat(Code, getGoogleStyle()); |
| } |
| |
| void verifyIndependentOfContext(llvm::StringRef text) { |
| verifyFormat(text); |
| verifyFormat(llvm::Twine("void f() { " + text + " }").str()); |
| } |
| |
| /// \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; |
| }; |
| |
| TEST_F(FormatTest, MessUp) { |
| EXPECT_EQ("1 2 3", test::messUp("1 2 3")); |
| EXPECT_EQ("1 2 3\n", test::messUp("1\n2\n3\n")); |
| EXPECT_EQ("a\n//b\nc", test::messUp("a\n//b\nc")); |
| EXPECT_EQ("a\n#b\nc", test::messUp("a\n#b\nc")); |
| EXPECT_EQ("a\n#b c d\ne", test::messUp("a\n#b\\\nc\\\nd\ne")); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Basic function tests. |
| //===----------------------------------------------------------------------===// |
| |
| TEST_F(FormatTest, DoesNotChangeCorrectlyFormattedCode) { |
| EXPECT_EQ(";", format(";")); |
| } |
| |
| TEST_F(FormatTest, FormatsGlobalStatementsAt0) { |
| EXPECT_EQ("int i;", format(" int i;")); |
| EXPECT_EQ("\nint i;", format(" \n\t \v \f int i;")); |
| EXPECT_EQ("int i;\nint j;", format(" int i; int j;")); |
| EXPECT_EQ("int i;\nint j;", format(" int i;\n int j;")); |
| } |
| |
| TEST_F(FormatTest, FormatsUnwrappedLinesAtFirstFormat) { |
| EXPECT_EQ("int i;", format("int\ni;")); |
| } |
| |
| TEST_F(FormatTest, FormatsNestedBlockStatements) { |
| EXPECT_EQ("{\n {\n {}\n }\n}", format("{{{}}}")); |
| } |
| |
| TEST_F(FormatTest, FormatsNestedCall) { |
| verifyFormat("Method(f1, f2(f3));"); |
| verifyFormat("Method(f1(f2, f3()));"); |
| verifyFormat("Method(f1(f2, (f3())));"); |
| } |
| |
| TEST_F(FormatTest, NestedNameSpecifiers) { |
| verifyFormat("vector<::Type> v;"); |
| verifyFormat("::ns::SomeFunction(::ns::SomeOtherFunction())"); |
| verifyFormat("static constexpr bool Bar = decltype(bar())::value;"); |
| verifyFormat("bool a = 2 < ::SomeFunction();"); |
| verifyFormat("ALWAYS_INLINE ::std::string getName();"); |
| verifyFormat("some::string getName();"); |
| } |
| |
| TEST_F(FormatTest, OnlyGeneratesNecessaryReplacements) { |
| EXPECT_EQ("if (a) {\n" |
| " f();\n" |
| "}", |
| format("if(a){f();}")); |
| EXPECT_EQ(4, ReplacementCount); |
| EXPECT_EQ("if (a) {\n" |
| " f();\n" |
| "}", |
| format("if (a) {\n" |
| " f();\n" |
| "}")); |
| EXPECT_EQ(0, ReplacementCount); |
| EXPECT_EQ("/*\r\n" |
| "\r\n" |
| "*/\r\n", |
| format("/*\r\n" |
| "\r\n" |
| "*/\r\n")); |
| EXPECT_EQ(0, ReplacementCount); |
| } |
| |
| TEST_F(FormatTest, RemovesEmptyLines) { |
| EXPECT_EQ("class C {\n" |
| " int i;\n" |
| "};", |
| format("class C {\n" |
| " int i;\n" |
| "\n" |
| "};")); |
| |
| // Don't remove empty lines at the start of namespaces or extern "C" blocks. |
| EXPECT_EQ("namespace N {\n" |
| "\n" |
| "int i;\n" |
| "}", |
| format("namespace N {\n" |
| "\n" |
| "int i;\n" |
| "}", |
| getGoogleStyle())); |
| EXPECT_EQ("extern /**/ \"C\" /**/ {\n" |
| "\n" |
| "int i;\n" |
| "}", |
| format("extern /**/ \"C\" /**/ {\n" |
| "\n" |
| "int i;\n" |
| "}", |
| getGoogleStyle())); |
| |
| // ...but do keep inlining and removing empty lines for non-block extern "C" |
| // functions. |
| verifyFormat("extern \"C\" int f() { return 42; }", getGoogleStyle()); |
| EXPECT_EQ("extern \"C\" int f() {\n" |
| " int i = 42;\n" |
| " return i;\n" |
| "}", |
| format("extern \"C\" int f() {\n" |
| "\n" |
| " int i = 42;\n" |
| " return i;\n" |
| "}", |
| getGoogleStyle())); |
| |
| // Remove empty lines at the beginning and end of blocks. |
| EXPECT_EQ("void f() {\n" |
| "\n" |
| " if (a) {\n" |
| "\n" |
| " f();\n" |
| " }\n" |
| "}", |
| format("void f() {\n" |
| "\n" |
| " if (a) {\n" |
| "\n" |
| " f();\n" |
| "\n" |
| " }\n" |
| "\n" |
| "}", |
| getLLVMStyle())); |
| EXPECT_EQ("void f() {\n" |
| " if (a) {\n" |
| " f();\n" |
| " }\n" |
| "}", |
| format("void f() {\n" |
| "\n" |
| " if (a) {\n" |
| "\n" |
| " f();\n" |
| "\n" |
| " }\n" |
| "\n" |
| "}", |
| getGoogleStyle())); |
| |
| // Don't remove empty lines in more complex control statements. |
| EXPECT_EQ("void f() {\n" |
| " if (a) {\n" |
| " f();\n" |
| "\n" |
| " } else if (b) {\n" |
| " f();\n" |
| " }\n" |
| "}", |
| format("void f() {\n" |
| " if (a) {\n" |
| " f();\n" |
| "\n" |
| " } else if (b) {\n" |
| " f();\n" |
| "\n" |
| " }\n" |
| "\n" |
| "}")); |
| |
| // 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" |
| "\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" |
| "};", 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" |
| "int i;\n" |
| "\n" |
| "} // namespace", |
| format("namespace {\n" |
| "int i;\n" |
| "\n" |
| "} // namespace")); |
| |
| FormatStyle Style = getLLVMStyle(); |
| Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; |
| Style.MaxEmptyLinesToKeep = 2; |
| Style.BreakBeforeBraces = FormatStyle::BS_Custom; |
| Style.BraceWrapping.AfterClass = true; |
| Style.BraceWrapping.AfterFunction = true; |
| Style.KeepEmptyLinesAtTheStartOfBlocks = false; |
| |
| EXPECT_EQ("class Foo\n" |
| "{\n" |
| " Foo() {}\n" |
| "\n" |
| " void funk() {}\n" |
| "};", |
| format("class Foo\n" |
| "{\n" |
| " Foo()\n" |
| " {\n" |
| " }\n" |
| "\n" |
| " void funk() {}\n" |
| "};", |
| Style)); |
| } |
| |
| TEST_F(FormatTest, RecognizesBinaryOperatorKeywords) { |
| verifyFormat("x = (a) and (b);"); |
| verifyFormat("x = (a) or (b);"); |
| verifyFormat("x = (a) bitand (b);"); |
| verifyFormat("x = (a) bitor (b);"); |
| verifyFormat("x = (a) not_eq (b);"); |
| verifyFormat("x = (a) and_eq (b);"); |
| verifyFormat("x = (a) or_eq (b);"); |
| verifyFormat("x = (a) xor (b);"); |
| } |
| |
| TEST_F(FormatTest, RecognizesUnaryOperatorKeywords) { |
| verifyFormat("x = compl(a);"); |
| verifyFormat("x = not(a);"); |
| verifyFormat("x = bitand(a);"); |
| // Unary operator must not be merged with the next identifier |
| verifyFormat("x = compl a;"); |
| verifyFormat("x = not a;"); |
| verifyFormat("x = bitand a;"); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Tests for control statements. |
| //===----------------------------------------------------------------------===// |
| |
| TEST_F(FormatTest, FormatIfWithoutCompoundStatement) { |
| verifyFormat("if (true)\n f();\ng();"); |
| verifyFormat("if (a)\n if (b)\n if (c)\n g();\nh();"); |
| verifyFormat("if (a)\n if (b) {\n f();\n }\ng();"); |
| verifyFormat("if constexpr (true)\n" |
| " f();\ng();"); |
| verifyFormat("if constexpr (a)\n" |
| " if constexpr (b)\n" |
| " if constexpr (c)\n" |
| " g();\n" |
| "h();"); |
| verifyFormat("if constexpr (a)\n" |
| " if constexpr (b) {\n" |
| " f();\n" |
| " }\n" |
| "g();"); |
| |
| FormatStyle AllowsMergedIf = getLLVMStyle(); |
| AllowsMergedIf.AlignEscapedNewlines = FormatStyle::ENAS_Left; |
| AllowsMergedIf.AllowShortIfStatementsOnASingleLine = true; |
| verifyFormat("if (a)\n" |
| " // comment\n" |
| " f();", |
| AllowsMergedIf); |
| verifyFormat("{\n" |
| " if (a)\n" |
| " label:\n" |
| " f();\n" |
| "}", |
| AllowsMergedIf); |
| verifyFormat("#define A \\\n" |
| " if (a) \\\n" |
| " label: \\\n" |
| " f()", |
| AllowsMergedIf); |
| verifyFormat("if (a)\n" |
| " ;", |
| AllowsMergedIf); |
| verifyFormat("if (a)\n" |
| " if (b) return;", |
| AllowsMergedIf); |
| |
| verifyFormat("if (a) // Can't merge this\n" |
| " f();\n", |
| AllowsMergedIf); |
| verifyFormat("if (a) /* still don't merge */\n" |
| " f();", |
| AllowsMergedIf); |
| verifyFormat("if (a) { // Never merge this\n" |
| " f();\n" |
| "}", |
| AllowsMergedIf); |
| verifyFormat("if (a) { /* Never merge this */\n" |
| " f();\n" |
| "}", |
| AllowsMergedIf); |
| |
| AllowsMergedIf.ColumnLimit = 14; |
| verifyFormat("if (a) return;", AllowsMergedIf); |
| verifyFormat("if (aaaaaaaaa)\n" |
| " return;", |
| AllowsMergedIf); |
| |
| AllowsMergedIf.ColumnLimit = 13; |
| verifyFormat("if (a)\n return;", AllowsMergedIf); |
| } |
| |
| TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) { |
| FormatStyle AllowsMergedLoops = getLLVMStyle(); |
| AllowsMergedLoops.AllowShortLoopsOnASingleLine = true; |
| verifyFormat("while (true) continue;", AllowsMergedLoops); |
| verifyFormat("for (;;) continue;", AllowsMergedLoops); |
| verifyFormat("for (int &v : vec) v *= 2;", AllowsMergedLoops); |
| verifyFormat("while (true)\n" |
| " ;", |
| AllowsMergedLoops); |
| verifyFormat("for (;;)\n" |
| " ;", |
| AllowsMergedLoops); |
| verifyFormat("for (;;)\n" |
| " for (;;) continue;", |
| AllowsMergedLoops); |
| verifyFormat("for (;;) // Can't merge this\n" |
| " continue;", |
| AllowsMergedLoops); |
| verifyFormat("for (;;) /* still don't merge */\n" |
| " continue;", |
| AllowsMergedLoops); |
| } |
| |
| TEST_F(FormatTest, FormatShortBracedStatements) { |
| FormatStyle AllowSimpleBracedStatements = getLLVMStyle(); |
| AllowSimpleBracedStatements.ColumnLimit = 40; |
| AllowSimpleBracedStatements.AllowShortBlocksOnASingleLine = true; |
| |
| AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = true; |
| AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = true; |
| |
| AllowSimpleBracedStatements.BreakBeforeBraces = FormatStyle::BS_Custom; |
| AllowSimpleBracedStatements.BraceWrapping.AfterFunction = true; |
| AllowSimpleBracedStatements.BraceWrapping.SplitEmptyRecord = false; |
| |
| verifyFormat("if (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("while (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("for (;;) {}", AllowSimpleBracedStatements); |
| verifyFormat("if (true) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("if constexpr (true) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("while (true) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("for (;;) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("if (true) {\n" |
| " ffffffffffffffffffffffffffffffffffffffffffffffffffffff();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true) { //\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true) {\n" |
| " f();\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true) {\n" |
| " f();\n" |
| "} else {\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| |
| verifyFormat("struct A2 {\n" |
| " int X;\n" |
| "};", |
| AllowSimpleBracedStatements); |
| verifyFormat("typedef struct A2 {\n" |
| " int X;\n" |
| "} A2_t;", |
| AllowSimpleBracedStatements); |
| verifyFormat("template <int> struct A2 {\n" |
| " struct B {};\n" |
| "};", |
| AllowSimpleBracedStatements); |
| |
| AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = false; |
| verifyFormat("if (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("if (true) {\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true) {\n" |
| " f();\n" |
| "} else {\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| |
| AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = false; |
| verifyFormat("while (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("while (true) {\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("for (;;) {}", AllowSimpleBracedStatements); |
| verifyFormat("for (;;) {\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| |
| AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = true; |
| AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = true; |
| AllowSimpleBracedStatements.BraceWrapping.AfterControlStatement = true; |
| |
| verifyFormat("if (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("while (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("for (;;) {}", AllowSimpleBracedStatements); |
| verifyFormat("if (true) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("if constexpr (true) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("while (true) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("for (;;) { f(); }", AllowSimpleBracedStatements); |
| verifyFormat("if (true)\n" |
| "{\n" |
| " ffffffffffffffffffffffffffffffffffffffffffffffffffffff();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true)\n" |
| "{ //\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true)\n" |
| "{\n" |
| " f();\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true)\n" |
| "{\n" |
| " f();\n" |
| "} else\n" |
| "{\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| |
| AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = false; |
| verifyFormat("if (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("if (true)\n" |
| "{\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("if (true)\n" |
| "{\n" |
| " f();\n" |
| "} else\n" |
| "{\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| |
| AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = false; |
| verifyFormat("while (true) {}", AllowSimpleBracedStatements); |
| verifyFormat("while (true)\n" |
| "{\n" |
| " f();\n" |
| "}", |
| AllowSimpleBracedStatements); |
| verifyFormat("for (;;) {}", AllowSimpleBracedStatements); |
| verifyFormat("for (;;)\n" |
| "{\n" |
| " f();\n" |
| "}", |
| 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" |
| " if (true)\n" |
| " f();\n" |
| " else\n" |
| " g();\n" |
| " else\n" |
| " h();\n" |
| "else\n" |
| " i();"); |
| verifyFormat("if (true)\n" |
| " if (true)\n" |
| " if (true) {\n" |
| " if (true)\n" |
| " f();\n" |
| " } else {\n" |
| " g();\n" |
| " }\n" |
| " else\n" |
| " h();\n" |
| "else {\n" |
| " i();\n" |
| "}"); |
| verifyFormat("if (true)\n" |
| " if constexpr (true)\n" |
| " if (true) {\n" |
| " if constexpr (true)\n" |
| " f();\n" |
| " } else {\n" |
| " g();\n" |
| " }\n" |
| " else\n" |
| " h();\n" |
| "else {\n" |
| " i();\n" |
| "}"); |
| verifyFormat("void f() {\n" |
| " if (a) {\n" |
| " } else {\n" |
| " }\n" |
| "}"); |
| } |
| |
| TEST_F(FormatTest, ElseIf) { |
| verifyFormat("if (a) {\n} else if (b) {\n}"); |
| verifyFormat("if (a)\n" |
| " f();\n" |
| "else if (b)\n" |
| " g();\n" |
| "else\n" |
| " h();"); |
| verifyFormat("if constexpr (a)\n" |
| " f();\n" |
| "else if constexpr (b)\n" |
| " g();\n" |
| "else\n" |
| " h();"); |
| verifyFormat("if (a) {\n" |
| " f();\n" |
| "}\n" |
| "// or else ..\n" |
| "else {\n" |
| " g()\n" |
| "}"); |
| |
| verifyFormat("if (a) {\n" |
| "} else if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaa)) {\n" |
| "}"); |
| verifyFormat("if (a) {\n" |
| "} else if (\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n" |
| "}", |
| getLLVMStyleWithColumns(62)); |
| verifyFormat("if (a) {\n" |
| "} else if constexpr (\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n" |
| "}", |
| getLLVMStyleWithColumns(62)); |
| } |
| |
| TEST_F(FormatTest, FormatsForLoop) { |
| verifyFormat( |
| "for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n" |
| " ++VeryVeryLongLoopVariable)\n" |
| " ;"); |
| verifyFormat("for (;;)\n" |
| " f();"); |
| verifyFormat("for (;;) {\n}"); |
| verifyFormat("for (;;) {\n" |
| " f();\n" |
| "}"); |
| verifyFormat("for (int i = 0; (i < 10); ++i) {\n}"); |
| |
| verifyFormat( |
| "for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),\n" |
| " E = UnwrappedLines.end();\n" |
| " I != E; ++I) {\n}"); |
| |
| verifyFormat( |
| "for (MachineFun::iterator IIII = PrevIt, EEEE = F.end(); IIII != EEEE;\n" |
| " ++IIIII) {\n}"); |
| verifyFormat("for (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaa =\n" |
| " aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa;\n" |
| " aaaaaaaaaaa != aaaaaaaaaaaaaaaaaaa; ++aaaaaaaaaaa) {\n}"); |
| verifyFormat("for (llvm::ArrayRef<NamedDecl *>::iterator\n" |
| " I = FD->getDeclsInPrototypeScope().begin(),\n" |
| " E = FD->getDeclsInPrototypeScope().end();\n" |
| " I != E; ++I) {\n}"); |
| verifyFormat("for (SmallVectorImpl<TemplateIdAnnotationn *>::iterator\n" |
| " I = Container.begin(),\n" |
| " E = Container.end();\n" |
| " I != E; ++I) {\n}", |
| getLLVMStyleWithColumns(76)); |
| |
| verifyFormat( |
| "for (aaaaaaaaaaaaaaaaa aaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa !=\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n" |
| " ++aaaaaaaaaaa) {\n}"); |
| verifyFormat("for (int i = 0; i < aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" |
| " bbbbbbbbbbbbbbbbbbbb < ccccccccccccccc;\n" |
| " ++i) {\n}"); |
| verifyFormat("for (int aaaaaaaaaaa = 1; aaaaaaaaaaa <= bbbbbbbbbbbbbbb;\n" |
| " aaaaaaaaaaa++, bbbbbbbbbbbbbbbbb++) {\n" |
| "}"); |
| verifyFormat("for (some_namespace::SomeIterator iter( // force break\n" |
| " aaaaaaaaaa);\n" |
| " iter; ++iter) {\n" |
| "}"); |
| verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n" |
| " 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" |
| " aaaaaaaaaaa <= aaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa,\n" |
| " aaaaaaaaaaaaaaaa,\n" |
| " aaaaaaaaaaaaaaaa,\n" |
| " aaaaaaaaaaaaaaaa);\n" |
| " aaaaaaaaaaa++, bbbbbbbbbbbbbbbbb++) {\n" |
| "}", |
| NoBinPacking); |
| verifyFormat( |
| "for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),\n" |
| " E = UnwrappedLines.end();\n" |
| " I != E;\n" |
| " ++I) {\n}", |
| NoBinPacking); |
| |
| FormatStyle AlignLeft = getLLVMStyle(); |
| AlignLeft.PointerAlignment = FormatStyle::PAS_Left; |
| verifyFormat("for (A* a = start; a < end; ++a, ++value) {\n}", AlignLeft); |
| } |
| |
| TEST_F(FormatTest, RangeBasedForLoops) { |
| verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}"); |
| verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaa :\n" |
| " aaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa, aaaaaaaaaaaaa)) {\n}"); |
| verifyFormat("for (const aaaaaaaaaaaaaaaaaaaaa &aaaaaaaaa :\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}"); |
| verifyFormat("for (aaaaaaaaa aaaaaaaaaaaaaaaaaaaaa :\n" |
| " aaaaaaaaaaaa.aaaaaaaaaaaa().aaaaaaaaa().a()) {\n}"); |
| } |
| |
| TEST_F(FormatTest, ForEachLoops) { |
| verifyFormat("void f() {\n" |
| " foreach (Item *item, itemlist) {}\n" |
| " Q_FOREACH (Item *item, itemlist) {}\n" |
| " BOOST_FOREACH (Item *item, itemlist) {}\n" |
| " UNKNOWN_FORACH(Item * item, itemlist) {}\n" |
| "}"); |
| |
| // As function-like macros. |
| verifyFormat("#define foreach(x, y)\n" |
| "#define Q_FOREACH(x, y)\n" |
| "#define BOOST_FOREACH(x, y)\n" |
| "#define UNKNOWN_FOREACH(x, y)\n"); |
| |
| // Not as function-like macros. |
| verifyFormat("#define foreach (x, y)\n" |
| "#define Q_FOREACH (x, y)\n" |
| "#define BOOST_FOREACH (x, y)\n" |
| "#define UNKNOWN_FOREACH (x, y)\n"); |
| } |
| |
| TEST_F(FormatTest, FormatsWhileLoop) { |
| verifyFormat("while (true) {\n}"); |
| verifyFormat("while (true)\n" |
| " f();"); |
| verifyFormat("while () {\n}"); |
| verifyFormat("while () {\n" |
| " f();\n" |
| "}"); |
| } |
| |
| TEST_F(FormatTest, FormatsDoWhile) { |
| verifyFormat("do {\n" |
| " do_something();\n" |
| "} while (something());"); |
| verifyFormat("do\n" |
| " do_something();\n" |
| "while (something());"); |
| } |
| |
| TEST_F(FormatTest, FormatsSwitchStatement) { |
| verifyFormat("switch (x) {\n" |
| "case 1:\n" |
| " f();\n" |
| " break;\n" |
| "case kFoo:\n" |
| "case ns::kBar:\n" |
| "case kBaz:\n" |
| " break;\n" |
| "default:\n" |
| " g();\n" |
| " break;\n" |
| "}"); |
| verifyFormat("switch (x) {\n" |
| "case 1: {\n" |
| " f();\n" |
| " break;\n" |
| "}\n" |
| "case 2: {\n" |
| " break;\n" |
| "}\n" |
| "}"); |
| verifyFormat("switch (x) {\n" |
| "case 1: {\n" |
| " f();\n" |
| " {\n" |
| " g();\n" |
| " h();\n" |
| " }\n" |
| " break;\n" |
| "}\n" |
| "}"); |
| verifyFormat("switch (x) {\n" |
| "case 1: {\n" |
| " f();\n" |
| " if (foo) {\n" |
| " g();\n" |
| " h();\n" |
| " }\n" |
| " break;\n" |
| "}\n" |
| "}"); |
| verifyFormat("switch (x) {\n" |
| "case 1: {\n" |
| " f();\n" |
| " g();\n" |
| "} break;\n" |
| "}"); |
| verifyFormat("switch (test)\n" |
| " ;"); |
| verifyFormat("switch (x) {\n" |
| "default: {\n" |
| " // Do nothing.\n" |
| "}\n" |
| "}"); |
| verifyFormat("switch (x) {\n" |
| "// comment\n" |
| "// if 1, do f()\n" |
| "case 1:\n" |
| " f();\n" |
| "}"); |
| verifyFormat("switch (x) {\n" |
| "case 1:\n" |
| " // Do amazing stuff\n" |
| " {\n" |
| " f();\n" |
| " g();\n" |
| " }\n" |
| " break;\n" |
| "}"); |
| verifyFormat("#define A \\\n" |
| " switch (x) { \\\n" |
| " case a: \\\n" |
| " foo = b; \\\n" |
| " }", |
| getLLVMStyleWithColumns(20)); |
| verifyFormat("#define OPERATION_CASE(name) \\\n" |
| " case OP_name: \\\n" |
| " return operations::Operation##name\n", |
| getLLVMStyleWithColumns(40)); |
| verifyFormat("switch (x) {\n" |
| "case 1:;\n" |
| "default:;\n" |
| " int i;\n" |
| "}"); |
| |
| verifyGoogleFormat("switch (x) {\n" |
| " case 1:\n" |
| " f();\n" |
| " break;\n" |
| " case kFoo:\n" |
| " case ns::kBar:\n" |
| " case kBaz:\n" |
| " break;\n" |
| " default:\n" |
| " g();\n" |
| " break;\n" |
| "}"); |
| verifyGoogleFormat("switch (x) {\n" |
| " case 1: {\n" |
| " f();\n" |
| " break;\n" |
| " }\n" |
| "}"); |
| verifyGoogleFormat("switch (test)\n" |
| " ;"); |
| |
| verifyGoogleFormat("#define OPERATION_CASE(name) \\\n" |
| " case OP_name: \\\n" |
| " return operations::Operation##name\n"); |
| verifyGoogleFormat("Operation codeToOperation(OperationCode OpCode) {\n" |
| " // Get the correction operation class.\n" |
| " switch (OpCode) {\n" |
| " CASE(Add);\n" |
| " CASE(Subtract);\n" |
| " default:\n" |
| " return operations::Unknown;\n" |
| " }\n" |
| "#undef OPERATION_CASE\n" |
| "}"); |
| verifyFormat("DEBUG({\n" |
| " switch (x) {\n" |
| " case A:\n" |
| " f();\n" |
| " break;\n" |
| " // fallthrough\n" |
| " case B:\n" |
| " g();\n" |
| " break;\n" |
| " }\n" |
| "});"); |
| EXPECT_EQ("DEBUG({\n" |
| " switch (x) {\n" |
| " case A:\n" |
| " f();\n" |
| " break;\n" |
| " // On B:\n" |
| " case B:\n" |
| " g();\n" |
| " break;\n" |
| " }\n" |
| "});", |
| format("DEBUG({\n" |
| " switch (x) {\n" |
| " case A:\n" |
| " f();\n" |
| " break;\n" |
| " // On B:\n" |
| " case B:\n" |
| " g();\n" |
| " break;\n" |
| " }\n" |
| "});", |
| getLLVMStyle())); |
| verifyFormat("switch (a) {\n" |
| "case (b):\n" |
| " return;\n" |
| "}"); |
| |
| verifyFormat("switch (a) {\n" |
| "case some_namespace::\n" |
| " some_constant:\n" |
| " return;\n" |
| "}", |
| getLLVMStyleWithColumns(34)); |
| } |
| |
| TEST_F(FormatTest, CaseRanges) { |
| verifyFormat("switch (x) {\n" |
| "case 'A' ... 'Z':\n" |
| "case 1 ... 5:\n" |
| "case a ... b:\n" |
| " break;\n" |
| "}"); |
| } |
| |
| TEST_F(FormatTest, ShortCaseLabels) { |
| FormatStyle Style = getLLVMStyle(); |
| Style.AllowShortCaseLabelsOnASingleLine = true; |
| verifyFormat("switch (a) {\n" |
| "case 1: x = 1; break;\n" |
| "case 2: return;\n" |
| "case 3:\n" |
| "case 4:\n" |
| "case 5: return;\n" |
| "case 6: // comment\n" |
| " return;\n" |
| "case 7:\n" |
| " // comment\n" |
| " return;\n" |
| "case 8:\n" |
| " x = 8; // comment\n" |
| " break;\n" |
| "default: y = 1; break;\n" |
| "}", |
| Style); |
| verifyFormat("switch (a) {\n" |
| "case 0: return; // comment\n" |
| "case 1: break; // comment\n" |
| "case 2: return;\n" |
| "// comment\n" |
| "case 3: return;\n" |
| "// comment 1\n" |
| "// comment 2\n" |
| "// comment 3\n" |
| "case 4: break; /* comment */\n" |
| "case 5:\n" |
| " // comment\n" |
| " break;\n" |
| "case 6: /* comment */ x = 1; break;\n" |
| "case 7: x = /* comment */ 1; break;\n" |
| "case 8:\n" |
| " x = 1; /* comment */\n" |
| " break;\n" |
| "case 9:\n" |
| " break; // comment line 1\n" |
| " // comment line 2\n" |
| "}", |
| Style); |
| EXPECT_EQ("switch (a) {\n" |
| "case 1:\n" |
| " x = 8;\n" |
| " // fall through\n" |
| "case 2: x = 8;\n" |
| "// comment\n" |
| "case 3:\n" |
| " return; /* comment line 1\n" |
| " * comment line 2 */\n" |
| "case 4: i = 8;\n" |
| "// something else\n" |
| "#if FOO\n" |
| "case 5: break;\n" |
| "#endif\n" |
| "}", |
| format("switch (a) {\n" |
| "case 1: x = 8;\n" |
| " // fall through\n" |
| "case 2:\n" |
| " x = 8;\n" |
| "// comment\n" |
| "case 3:\n" |
| " return; /* comment line 1\n" |
| " * comment line 2 */\n" |
| "case 4:\n" |
| " i = 8;\n" |
| "// something else\n" |
| "#if FOO\n" |
| "case 5: break;\n" |
| "#endif\n" |
| "}", |
| Style)); |
| EXPECT_EQ("switch (a) {\n" "case 0:\n" |
| " return; // long long long long long long long long long long long long comment\n" |
| " // line\n" "}", |
| format("switch (a) {\n" |
| "case 0: return; // long long long long long long long long long long long long comment line\n" |
| "}", |
| Style)); |
| EXPECT_EQ("switch (a) {\n" |
| "case 0:\n" |
| " return; /* long long long long long long long long long long long long comment\n" |
| " line */\n" |
| "}", |
| format("switch (a) {\n" |
| "case 0: return; /* long long long long long long long long long long long long comment line */\n" |
| "}", |
| Style)); |
| verifyFormat("switch (a) {\n" |
| "#if FOO\n" |
| "case 0: return 0;\n" |
| "#endif\n" |
| "}", |
| Style); |
| verifyFormat("switch (a) {\n" |
| "case 1: {\n" |
| "}\n" |
| "case 2: {\n" |
| " return;\n" |
| "}\n" |
| "case 3: {\n" |
| " x = 1;\n" |
| " return;\n" |
| "}\n" |
| "case 4:\n" |
| " if (x)\n" |
| " return;\n" |
| "}", |
| Style); |
| Style.ColumnLimit = 21; |
| verifyFormat("switch (a) {\n" |
| "case 1: x = 1; break;\n" |
| "case 2: return;\n" |
| "case 3:\n" |
| "case 4:\n" |
| "case 5: return;\n" |
| "default:\n" |
| " y = 1;\n" |
| " break;\n" |
| "}", |
| Style); |
| } |
| |
| TEST_F(FormatTest, FormatsLabels) { |
| verifyFormat("void f() {\n" |
| " some_code();\n" |
| "test_label:\n" |
| " some_other_code();\n" |
| " {\n" |
| " some_more_code();\n" |
| " another_label:\n" |
| " some_more_code();\n" |
| " }\n" |
| "}"); |
| verifyFormat("{\n" |
| " some_code();\n" |
| "test_label:\n" |
| " some_other_code();\n" |
| "}"); |
| verifyFormat("{\n" |
| " some_code();\n" |
| "test_label:;\n" |
| " int i = 0;\n" |
| "}"); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Tests for classes, namespaces, etc. |
| //===----------------------------------------------------------------------===// |
| |
| TEST_F(FormatTest, DoesNotBreakSemiAfterClassDecl) { |
| verifyFormat("class A {};"); |
| } |
| |
| TEST_F(FormatTest, UnderstandsAccessSpecifiers) { |
| verifyFormat("class A {\n" |
| "public:\n" |
| "public: // comment\n" |
| "protected:\n" |
| "private:\n" |
| " void f() {}\n" |
| "};"); |
| verifyGoogleFormat("class A {\n" |
| " public:\n" |
| " protected:\n" |
| " private:\n" |
| " void f() {}\n" |
| "};"); |
| verifyFormat("class A {\n" |
| "public slots:\n" |
| " void f1() {}\n" |
| "public Q_SLOTS:\n" |
| " void f2() {}\n" |
| "protected slots:\n" |
| " void f3() {}\n" |
| "protected Q_SLOTS:\n" |
| " void f4() {}\n" |
| "private slots:\n" |
| " void f5() {}\n" |
| "private Q_SLOTS:\n" |
| " void f6() {}\n" |
| "signals:\n" |
| " void g1();\n" |
| "Q_SIGNALS:\n" |
| " void g2();\n" |
| "};"); |
| |
| // Don't interpret 'signals' the wrong way. |
| verifyFormat("signals.set();"); |
| verifyFormat("for (Signals signals : f()) {\n}"); |
| verifyFormat("{\n" |
| " signals.set(); // This needs indentation.\n" |
| "}"); |
| verifyFormat("void f() {\n" |
| "label:\n" |
| " signals.baz();\n" |
| "}"); |
| } |
| |
| TEST_F(FormatTest, SeparatesLogicalBlocks) { |
| EXPECT_EQ("class A {\n" |
| "public:\n" |
| " void f();\n" |
| "\n" |
| "private:\n" |
| " void g() {}\n" |
| " // test\n" |
| "protected:\n" |
| " int h;\n" |
| "};", |
| format("class A {\n" |
| "public:\n" |
| "void f();\n" |
| "private:\n" |
| "void g() {}\n" |
| "// test\n" |
| "protected:\n" |
| "int h;\n" |
| "};")); |
| EXPECT_EQ("class A {\n" |
| "protected:\n" |
| "public:\n" |
| " void f();\n" |
| "};", |
| format("class A {\n" |
| "protected:\n" |
| "\n" |
| "public:\n" |
| "\n" |
| " void f();\n" |
| "};")); |
| |
| // Even ensure proper spacing inside macros. |
| EXPECT_EQ("#define B \\\n" |
| " class A { \\\n" |
| " protected: \\\n" |
| " public: \\\n" |
| " void f(); \\\n" |
| " };", |
| format("#define B \\\n" |
| " class A { \\\n" |
| " protected: \\\n" |
| " \\\n" |
| " public: \\\n" |
| " \\\n" |
| " void f(); \\\n" |
| " };", |
| getGoogleStyle())); |
| // But don't remove empty lines after macros ending in access specifiers. |
| EXPECT_EQ("#define A private:\n" |
| "\n" |
| "int i;", |
| format("#define A private:\n" |
| "\n" |
| "int i;")); |
| } |
| |
| TEST_F(FormatTest, FormatsClasses) { |
| verifyFormat("class A : public B {};"); |
| verifyFormat("class A : public ::B {};"); |
| |
| verifyFormat( |
| "class AAAAAAAAAAAAAAAAAAAA : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n" |
| " public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};"); |
| verifyFormat("class AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" |
| " : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n" |
| " public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};"); |
| verifyFormat( |
| "class A : public B, public C, public D, public E, public F {};"); |
| verifyFormat("class AAAAAAAAAAAA : public B,\n" |
| " public C,\n" |
| " public D,\n" |
| " public E,\n" |
| " public F,\n" |
| " public G {};"); |
| |
| verifyFormat("class\n" |
| " ReallyReallyLongClassName {\n" |
| " int i;\n" |
| "};", |
| getLLVMStyleWithColumns(32)); |
| verifyFormat("struct aaaaaaaaaaaaa : public aaaaaaaaaaaaaaaaaaa< // break\n" |
| " aaaaaaaaaaaaaaaa> {};"); |
| verifyFormat("struct aaaaaaaaaaaaaaaaaaaa\n" |
| " : public aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaa,\n" |
| " aaaaaaaaaaaaaaaaaaaaaa> {};"); |
| verifyFormat("template <class R, class C>\n" |
| "struct Aaaaaaaaaaaaaaaaa<R (C::*)(int) const>\n" |
| " : Aaaaaaaaaaaaaaaaa<R (C::*)(int)> {};"); |
| verifyFormat("class ::A::B {};"); |
| } |
| |
| 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 {};", |
| 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) { |
| verifyFormat("class A {\n} a, b;"); |
| verifyFormat("struct A {\n} a, b;"); |
| verifyFormat("union A {\n} a;"); |
| } |
| |
| TEST_F(FormatTest, FormatsEnum) { |
| verifyFormat("enum {\n" |
| " Zero,\n" |
| " One = 1,\n" |
| " Two = One + 1,\n" |
| " Three = (One + Two),\n" |
| " Four = (Zero && (One ^ Two)) | (One << Two),\n" |
| " Five = (One, Two, Three, Four, 5)\n" |
| "};"); |
| verifyGoogleFormat("enum {\n" |
| " Zero,\n" |
| " One = 1,\n" |
| " Two = One + 1,\n" |
| " Three = (One + Two),\n" |
| " Four = (Zero && (One ^ Two)) | (One << Two),\n" |
| " Five = (One, Two, Three, Four, 5)\n" |
| "};"); |
| verifyFormat("enum Enum {};"); |
| verifyFormat("enum {};"); |
| verifyFormat("enum X E {} d;"); |
| verifyFormat("enum __attribute__((...)) E {} d;"); |
| verifyFormat("enum __declspec__((...)) E {} d;"); |
| verifyFormat("enum {\n" |
| " Bar = Foo<int, int>::value\n" |
| "};", |
| getLLVMStyleWithColumns(30)); |
| |
| verifyFormat("enum ShortEnum { A, B, C };"); |
| verifyGoogleFormat("enum ShortEnum { A, B, C };"); |
| |
| EXPECT_EQ("enum KeepEmptyLines {\n" |
| " ONE,\n" |
| "\n" |
| " TWO,\n" |
| "\n" |
| " THREE\n" |
| "}", |
| format("enum KeepEmptyLines {\n" |
| " ONE,\n" |
| "\n" |
| " TWO,\n" |
| "\n" |
| "\n" |
| " THREE\n" |
| "}")); |
| verifyFormat("enum E { // comment\n" |
| " ONE,\n" |
| " TWO\n" |
| "};\n" |
| "int i;"); |
| // Not enums. |
| verifyFormat("enum X f() {\n" |
| " a();\n" |
| " return 42;\n" |
| "}"); |
| verifyFormat("enum X Type::f() {\n" |
| " a();\n" |
| " return 42;\n" |
| "}"); |
| verifyFormat("enum ::X f() {\n" |
| " a();\n" |
| " return 42;\n" |
| "}"); |
| verifyFormat("enum ns::X f() {\n" |
| " a();\n" |
| " return 42;\n" |
| "}"); |
| } |
| |
| TEST_F(FormatTest, FormatsEnumsWithErrors) { |
| verifyFormat("enum Type {\n" |
| " One = 0; // These semicolons should be commas.\n" |
| " Two = 1;\n" |
| "};"); |
| verifyFormat("namespace n {\n" |
| "enum Type {\n" |
| " One,\n" |
| " Two, // missing };\n" |
| " int i;\n" |
| "}\n" |
| "void g() {}"); |
| } |
| |
| TEST_F(FormatTest, FormatsEnumStruct) { |
| verifyFormat("enum struct {\n" |
| " Zero,\n" |
| " One = 1,\n" |
| " Two = One + 1,\n" |
| " Three = (One + Two),\n" |
| " Four = (Zero && (One ^ Two)) | (One << Two),\n" |
| " Five = (One, Two, Three, Four, 5)\n" |
| "};"); |
| verifyFormat("enum struct Enum {};"); |
| verifyFormat("enum struct {};"); |
| verifyFormat("enum struct X E {} d;"); |
| verifyFormat("enum struct __attribute__((...)) E {} d;"); |
| verifyFormat("enum struct __declspec__((...)) E {} d;"); |
| verifyFormat("enum struct X f() {\n a();\n return 42;\n}"); |
| } |
| |
| TEST_F(FormatTest, FormatsEnumClass) { |
| verifyFormat("enum class {\n" |
| " Zero,\n" |
| " One = 1,\n" |
| " Two = One + 1,\n" |
| " Three = (One + Two),\n" |
| " Four = (Zero && (One ^ Two)) | (One << Two),\n" |
| " Five = (One, Two, Three, Four, 5)\n" |
| "};"); |
| verifyFormat("enum class Enum {};"); |
| verifyFormat("enum class {};"); |
| verifyFormat("enum class X E {} d;"); |
| verifyFormat("enum class __attribute__((...)) E {} d;"); |
| verifyFormat("enum class __declspec__((...)) E {} d;"); |
| verifyFormat("enum class X f() {\n a();\n return 42;\n}"); |
| } |
| |
| TEST_F(FormatTest, FormatsEnumTypes) { |
| verifyFormat("enum X : int {\n" |
| " A, // Force multiple lines.\n" |
| " B\n" |
| "};"); |
| verifyFormat("enum X : int { A, B };"); |
| verifyFormat("enum X : std::uint32_t { A, B };"); |
| } |
| |
| TEST_F(FormatTest, FormatsTypedefEnum) { |
| FormatStyle Style = getLLVMStyle(); |
| Style.ColumnLimit = 40; |
| verifyFormat("typedef enum {} EmptyEnum;"); |
| verifyFormat("typedef enum { A, B, C } ShortEnum;"); |
| verifyFormat("typedef enum {\n" |
| " ZERO = 0,\n" |
| " ONE = 1,\n" |
| " TWO = 2,\n" |
| " THREE = 3\n" |
| "} LongEnum;", |
| Style); |
| Style.BreakBeforeBraces = FormatStyle::BS_Custom; |
| Style.BraceWrapping.AfterEnum = true; |
| verifyFormat("typedef enum {} EmptyEnum;"); |
| verifyFormat("typedef enum { A, B, C } ShortEnum;"); |
| verifyFormat("typedef enum\n" |
| "{\n" |
| " ZERO = 0,\n" |
| " ONE = 1,\n" |
| " TWO = 2,\n" |
| " THREE = 3\n" |
| "} LongEnum;", |
| Style); |
| } |
| |
| TEST_F(FormatTest, FormatsNSEnums) { |
| verifyGoogleFormat("typedef NS_ENUM(NSInteger, SomeName) { AAA, BBB }"); |
| verifyGoogleFormat("typedef NS_ENUM(NSInteger, MyType) {\n" |
| " // Information about someDecentlyLongValue.\n" |
| " someDecentlyLongValue,\n" |
| " // Information about anotherDecentlyLongValue.\n" |
| " anotherDecentlyLongValue,\n" |
| " // Information about aThirdDecentlyLongValue.\n" |
| " aThirdDecentlyLongValue\n" |
| "};"); |
| verifyGoogleFormat("typedef NS_OPTIONS(NSInteger, MyType) {\n" |
| " a = 1,\n" |
| " b = 2,\n" |
| " c = 3,\n" |
| "};"); |
| verifyGoogleFormat("typedef CF_ENUM(NSInteger, MyType) {\n" |
| " a = 1,\n" |
| " b = 2,\n" |
| " c = 3,\n" |
| "};"); |
| verifyGoogleFormat("typedef CF_OPTIONS(NSInteger, MyType) {\n" |
| " a = 1,\n" |
| " b = 2,\n" |
| " c = 3,\n" |
| "};"); |
| } |
| |
| TEST_F(FormatTest, FormatsBitfields) { |
| verifyFormat("struct Bitfields {\n" |
| " unsigned sClass : 8;\n" |
| " unsigned ValueKind : 2;\n" |
| "};"); |
| verifyFormat("struct A {\n" |
| " int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa : 1,\n" |
| " bbbbbbbbbbbbbbbbbbbbbbbbb;\n" |
| "};"); |
| verifyFormat("struct MyStruct {\n" |
| " uchar data;\n" |
| " uchar : 8;\n" |
| " uchar : 8;\n" |
| " uchar other;\n" |
| "};"); |
| } |
| |
| TEST_F(FormatTest, FormatsNamespaces) { |
| FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle(); |
| LLVMWithNoNamespaceFix.FixNamespaceComments = false; |
| |
| verifyFormat("namespace some_namespace {\n" |
| "class A {};\n" |
| "void f() { f(); }\n" |
| "}", |
| LLVMWithNoNamespaceFix); |
| verifyFormat("namespace {\n" |
| "class A {};\n" |
| "void f() { f(); }\n" |
| "}", |
| LLVMWithNoNamespaceFix); |
| verifyFormat("inline namespace X {\n" |
| "class A {};\n" |
| "void f() { f(); }\n" |
| "}", |
| LLVMWithNoNamespaceFix); |
| verifyFormat("using namespace some_namespace;\n" |
| "class A {};\n" |
| "void f() { f(); }", |
| LLVMWithNoNamespaceFix); |
| |
| // This code is more common than we thought; if we |
| // layout this correctly the semicolon will go into |
| // its own line, which is undesirable. |
| verifyFormat("namespace {};", |
| LLVMWithNoNamespaceFix); |
| verifyFormat("namespace {\n" |
| "class A {};\n" |
| "};", |
| LLVMWithNoNamespaceFix); |
| |
| verifyFormat("namespace {\n" |
| "int SomeVariable = 0; // comment\n" |
| "} // namespace", |
| LLVMWithNoNamespaceFix); |
| EXPECT_EQ("#ifndef HEADER_GUARD\n" |
| "#define HEADER_GUARD\n" |
| "namespace my_namespace {\n" |
| "int i;\n" |
| "} // my_namespace\n" |
| "#endif // HEADER_GUARD", |
| format("#ifndef HEADER_GUARD\n" |
| " #define HEADER_GUARD\n" |
| " namespace my_namespace {\n" |
| "int i;\n" |
| "} // my_namespace\n" |
| "#endif // HEADER_GUARD", |
| LLVMWithNoNamespaceFix)); |
| |
| EXPECT_EQ("namespace A::B {\n" |
| "class C {};\n" |
| "}", |
| format("namespace A::B {\n" |
| "class C {};\n" |
| "}", |
| LLVMWithNoNamespaceFix)); |
| |
| FormatStyle Style = getLLVMStyle(); |
| Style.NamespaceIndentation = FormatStyle::NI_All; |
| EXPECT_EQ("namespace out {\n" |
| " int i;\n" |
| " namespace in {\n" |
| " int i;\n" |
| " } // namespace in\n" |
| "} // namespace out", |
| format("namespace out {\n" |
| "int i;\n" |
| "namespace in {\n" |
| "int i;\n" |
| "} // namespace in\n" |
| "} // namespace out", |
| Style)); |
| |
| Style.NamespaceIndentation = FormatStyle::NI_Inner; |
| EXPECT_EQ("namespace out {\n" |
| "int i;\n" |
| "namespace in {\n" |
| " int i;\n" |
| "} // namespace in\n" |
| "} // namespace out", |
| format("namespace out {\n" |
| "int i;\n" |
| "namespace in {\n" |
| "int i;\n" |
| "} // namespace in\n" |
| "} // namespace out", |
| Style)); |
| } |
| |
| TEST_F(FormatTest, FormatsCompactNamespaces) { |
| FormatStyle Style = getLLVMStyle(); |
| Style.CompactNamespaces = true; |
| |
| verifyFormat("namespace A { namespace B {\n" |
| "}} // namespace A::B", |
| Style); |
| |
| EXPECT_EQ("namespace out { namespace in {\n" |
| "}} // namespace out::in", |
| format("namespace out {\n" |
| "namespace in {\n" |
| "} // namespace in\n" |
| "} // namespace out", |
| Style)); |
| |
| // Only namespaces which have both consecutive opening and end get compacted |
| EXPECT_EQ("namespace out {\n" |
| "namespace in1 {\n" |
| "} // namespace in1\n" |
| "namespace in2 {\n" |
| "} // namespace in2\n" |
| "} // namespace out", |
| format("namespace out {\n" |
| "namespace in1 {\n" |
| "} // namespace in1\n" |
| "namespace in2 {\n" |
| "} // namespace in2\n" |
| "} // namespace out", |
| Style)); |
| |
| EXPECT_EQ("namespace out {\n" |
| "int i;\n" |
| "namespace in {\n" |
| "int j;\n" |
| "} // namespace in\n" |
| "int k;\n" |
| "} // namespace out", |
| format("namespace out { int i;\n" |
| "namespace in { int j; } // namespace in\n" |
| "int k; } // namespace out", |
| Style)); |
| |
| EXPECT_EQ("namespace A { namespace B { namespace C {\n" |
| "}}} // namespace A::B::C\n", |
| format("namespace A { namespace B {\n" |
| "namespace C {\n" |
| "}} // namespace B::C\n" |
| "} // namespace A\n", |
| Style)); |
| |
| Style.ColumnLimit = 40; |
| EXPECT_EQ("namespace aaaaaaaaaa {\n" |
| "namespace bbbbbbbbbb {\n" |
| "}} // namespace aaaaaaaaaa::bbbbbbbbbb", |
| format("namespace aaaaaaaaaa {\n" |
| "namespace bbbbbbbbbb {\n" |
| "} // namespace bbbbbbbbbb\n" |
| "} // namespace aaaaaaaaaa", |
| Style)); |
| |
| EXPECT_EQ("namespace aaaaaa { namespace bbbbbb {\n" |
| "namespace cccccc {\n" |
| "}}} // namespace aaaaaa::bbbbbb::cccccc", |
| format("namespace aaaaaa {\n" |
| "namespace bbbbbb {\n" |
| "namespace cccccc {\n" |
| "} // namespace cccccc\n" |
| "} // namespace bbbbbb\n" |
| "} // namespace aaaaaa", |
| Style)); |
| Style.ColumnLimit = 80; |
| |
| // Extra semicolon after 'inner' closing brace prevents merging |
| EXPECT_EQ("namespace out { namespace in {\n" |
| "}; } // namespace out::in", |
| format("namespace out {\n" |
| "namespace in {\n" |
| "}; // namespace in\n" |
| "} // namespace out", |
| Style)); |
| |
| // Extra semicolon after 'outer' closing brace is conserved |
| EXPECT_EQ("namespace out { namespace in {\n" |
| "}}; // namespace out::in", |
| format("namespace out {\n" |
| "namespace in {\n" |
| "} // namespace in\n" |
| "}; // namespace out", |
| Style)); |
| |
| Style.NamespaceIndentation = FormatStyle::NI_All; |
| EXPECT_EQ("namespace out { namespace in {\n" |
| " int i;\n" |
| "}} // namespace out::in", |
| format("namespace out {\n" |
| "namespace in {\n" |
| "int i;\n" |
| "} // namespace in\n" |
| "} // namespace out", |
| Style)); |
| EXPECT_EQ("namespace out { namespace mid {\n" |
| " namespace in {\n" |
| " int j;\n" |
| " } // namespace in\n" |
| " int k;\n" |
| "}} // namespace out::mid", |
| format("namespace out { namespace mid {\n" |
| "namespace in { int j; } // namespace in\n" |
| "int k; }} // namespace out::mid", |
| Style)); |
| |
| Style.NamespaceIndentation = FormatStyle::NI_Inner; |
| EXPECT_EQ("namespace out { namespace in {\n" |
| " int i;\n" |
| "}} // namespace out::in", |
| format("namespace out {\n" |
| "namespace in {\n" |
| "int i;\n" |
| "} // namespace in\n" |
| "} // namespace out", |
| Style)); |
| EXPECT_EQ("namespace out { namespace mid { namespace in {\n" |
| " int i;\n" |
| "}}} // namespace out::mid::in", |
| format("namespace out {\n" |
| "namespace mid {\n" |
| "namespace in {\n" |
| "int i;\n" |
| "} // namespace in\n" |
| "} // namespace mid\n" |
| "} // namespace out", |
| Style)); |
| } |
| |
| TEST_F(FormatTest, FormatsExternC) { |
| verifyFormat("extern \"C\" {\nint a;"); |
| verifyFormat("extern \"C\" {}"); |
| verifyFormat("extern \"C\" {\n" |
| "int foo();\n" |
| "}"); |
| verifyFormat("extern \"C\" int foo() {}"); |
| verifyFormat("extern \"C\" int foo();"); |
| verifyFormat("extern \"C\" int foo() {\n" |
| " int i = 42;\n" |
| " return i;\n" |
| "}"); |
| |
| FormatStyle Style = getLLVMStyle(); |
| Style.BreakBeforeBraces = FormatStyle::BS_Custom; |
| Style.BraceWrapping.AfterFunction = true; |
| verifyFormat("extern \"C\" int foo() {}", Style); |
| verifyFormat("extern \"C\" int foo();", Style); |
| verifyFormat("extern \"C\" int foo()\n" |
| "{\n" |
| " int i = 42;\n" |
| " return i;\n" |
| "}", |
| Style); |
| |
| Style.BraceWrapping.AfterExternBlock = true; |
| Style.BraceWrapping.SplitEmptyRecord = false; |
| verifyFormat("extern \"C\"\n" |
| "{}", |
| Style); |
| verifyFormat("extern \"C\"\n" |
| "{\n" |
| " int foo();\n" |
| "}", |
| Style); |
| } |
| |
| TEST_F(FormatTest, FormatsInlineASM) { |
| verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"); |
| verifyFormat("asm(\"nop\" ::: \"memory\");"); |
| verifyFormat( |
| "asm(\"movq\\t%%rbx, %%rsi\\n\\t\"\n" |
| " \"cpuid\\n\\t\"\n" |
| " \"xchgq\\t%%rbx, %%rsi\\n\\t\"\n" |
| " : \"=a\"(*rEAX), \"=S\"(*rEBX), \"=c\"(*rECX), \"=d\"(*rEDX)\n" |
| " : \"a\"(value));"); |
| EXPECT_EQ( |
| "void NS_InvokeByIndex(void *that, unsigned int methodIndex) {\n" |
| " __asm {\n" |
| " mov edx,[that] // vtable in edx\n" |
| " mov eax,methodIndex\n" |
| " call [edx][eax*4] // stdcall\n" |
| " }\n" |
| "}", |
| format("void NS_InvokeByIndex(void *that, unsigned int methodIndex) {\n" |
| " __asm {\n" |
| " mov edx,[that] // vtable in edx\n" |
| " mov eax,methodIndex\n" |
| " call [edx][eax*4] // stdcall\n" |
| " }\n" |
| "}")); |
| EXPECT_EQ("_asm {\n" |
| " xor eax, eax;\n" |
| " cpuid;\n" |
| "}", |
| format("_asm {\n" |
| " xor eax, eax;\n" |
| " cpuid;\n" |
| "}")); |
| verifyFormat("void function() {\n" |
| " // comment\n" |
| " asm(\"\");\n" |
| "}"); |
| EXPECT_EQ("__asm {\n" |
| "}\n" |
| "int i;", |
| format("__asm {\n" |
| "}\n" |
| "int i;")); |
| } |
| |
| TEST_F(FormatTest, FormatTryCatch) { |
| verifyFormat("try {\n" |
| " throw a * b;\n" |
| "} catch (int a) {\n" |
| " // Do nothing.\n" |
| "} catch (...) {\n" |
| " exit(42);\n" |
| "}"); |
| |
| // Function-level try statements. |
| verifyFormat("int f() try { return 4; } catch (...) {\n" |
| " return 5;\n" |
| "}"); |
| verifyFormat("class A {\n" |
| " int a;\n" |
| " A() try : a(0) {\n" |
| " } catch (...) {\n" |
| " throw;\n" |
| " }\n" |
| "};\n"); |
| |
| // Incomplete try-catch blocks. |
| verifyIncompleteFormat("try {} catch ("); |
| } |
| |
| TEST_F(FormatTest, FormatSEHTryCatch) { |
| verifyFormat("__try {\n" |
| " int a = b * c;\n" |
| "} __except (EXCEPTION_EXECUTE_HANDLER) {\n" |
| " // Do nothing.\n" |
| "}"); |
| |
| verifyFormat("__try {\n" |
| " int a = b * c;\n" |
| "} __finally {\n" |
| " // Do nothing.\n" |
| "}"); |
| |
| verifyFormat("DEBUG({\n" |
| " __try {\n" |
| " } __finally {\n" |
| " }\n" |
| "});\n"); |
| } |
| |
| TEST_F(FormatTest, IncompleteTryCatchBlocks) { |
| verifyFormat("try {\n" |
| " f();\n" |
| "} catch {\n" |
| " g();\n" |
| "}"); |
| verifyFormat("try {\n" |
| " f();\n" |
| "} catch (A a) MACRO(x) {\n" |
| " g();\n" |
| "} catch (B b) MACRO(x) {\n" |
| " g();\n" |
| "}"); |
| } |
| |
| TEST_F(FormatTest, FormatTryCatchBraceStyles) { |
| FormatStyle Style = getLLVMStyle(); |
| for (auto BraceStyle : {FormatStyle::BS_Attach, FormatStyle::BS_Mozilla, |
| FormatStyle::BS_WebKit}) { |
| Style.BreakBeforeBraces = BraceStyle; |
| verifyFormat("try {\n" |
| " // something\n" |
| "} catch (...) {\n" |
| " // something\n" |
| "}", |
| Style); |
| } |
| Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; |
| verifyFormat("try {\n" |
| " // something\n" |
| "}\n" |
| "catch (...) {\n" |
| " // something\n" |
| "}", |
| Style); |
| verifyFormat("__try {\n" |
| " // something\n" |
| "}\n" |
| "__finally {\n" |
| " // something\n" |
| "}", |
| Style); |
| verifyFormat("@try {\n" |
| " // something\n" |
| "}\n" |
| "@finally {\n" |
| " // something\n" |
| "}", |
| Style); |
| Style.BreakBeforeBraces = FormatStyle::BS_Allman; |
| verifyFormat("try\n" |
| "{\n" |
| " // something\n" |
| "}\n" |
| "catch (...)\n" |
| "{\n" |
| " // something\n" |
| "}", |
| Style); |
| Style.BreakBeforeBraces = FormatStyle::BS_GNU; |
| verifyFormat("try\n" |
| " {\n" |
| " // something\n" |
| " }\n" |
| "catch (...)\n" |
| " {\n" |
| " // something\n" |
| " }", |
| Style); |
| Style.BreakBeforeBraces = FormatStyle::BS_Custom; |
| Style.BraceWrapping.BeforeCatch = true; |
| verifyFormat("try {\n" |
| " // something\n" |
| "}\n" |
| "catch (...) {\n" |
| " // something\n" |
| "}", |
| Style); |
| } |
| |
| TEST_F(FormatTest, StaticInitializers) { |
| verifyFormat("static SomeClass SC = {1, 'a'};"); |
| |
| verifyFormat("static SomeClass WithALoooooooooooooooooooongName = {\n" |
| " 100000000, " |
| "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};"); |
| |
| // Here, everything other than the "}" would fit on a line. |
| verifyFormat("static int LooooooooooooooooooooooooongVariable[1] = {\n" |
| " 10000000000000000000000000};"); |
| EXPECT_EQ("S s = {a,\n" |
| "\n" |
| " b};", |
| format("S s = {\n" |
| " a,\n" |
| "\n" |
| " b\n" |
| "};")); |
| |
| // FIXME: This would fit into the column limit if we'd fit "{ {" on the first |
| // line. However, the formatting looks a bit off and this probably doesn't |
| // happen often in practice. |
| verifyFormat("static int Variable[1] = {\n" |
| " {1000000000000000000000000000000000000}};", |
| getLLVMStyleWithColumns(40)); |
| } |
| |
| TEST_F(FormatTest, DesignatedInitializers) { |
| verifyFormat("const struct A a = {.a = 1, .b = 2};"); |
| verifyFormat("const struct A a = {.aaaaaaaaaa = 1,\n" |
| " .bbbbbbbbbb = 2,\n" |
| " .cccccccccc = 3,\n" |
| " .dddddddddd = 4,\n" |
| " .eeeeeeeeee = 5};"); |
| verifyFormat("const struct Aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa = {\n" |
| " .aaaaaaaaaaaaaaaaaaaaaaaaaaa = 1,\n" |
| " .bbbbbbbbbbbbbbbbbbbbbbbbbbb = 2,\n" |
| " .ccccccccccccccccccccccccccc = 3,\n" |
| " .ddddddddddddddddddddddddddd = 4,\n" |
| " .eeeeeeeeeeeeeeeeeeeeeeeeeee = 5};"); |
| |
| verifyGoogleFormat("const struct A a = {.a = 1, .b = 2};"); |
| |
| verifyFormat("const struct A a = {[0] = 1, [1] = 2};"); |
| verifyFormat("const struct A a = {[1] = aaaaaaaaaa,\n" |
| " [2] = bbbbbbbbbb,\n" |
| " [3] = cccccccccc,\n" |
| " [4] = dddddddddd,\n" |
| " [5] = eeeeeeeeee};"); |
| verifyFormat("const struct Aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa = {\n" |
| " [1] = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" |
| " [2] = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,\n" |
| " [3] = cccccccccccccccccccccccccccccccccccccc,\n" |
| " [4] = dddddddddddddddddddddddddddddddddddddd,\n" |
| " [5] = eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee};"); |
| } |
| |
| TEST_F(FormatTest, NestedStaticInitializers) { |
| verifyFormat("static A x = {{{}}};\n"); |
| verifyFormat("static A x = {{{init1, init2, init3, init4},\n" |
| " {init1, init2, init3, init4}}};", |
| getLLVMStyleWithColumns(50)); |
| |
| verifyFormat("somes Status::global_reps[3] = {\n" |
| " {kGlobalRef, OK_CODE, NULL, NULL, NULL},\n" |
| " {kGlobalRef, CANCELLED_CODE, NULL, NULL, NULL},\n" |
| " {kGlobalRef, UNKNOWN_CODE, NULL, NULL, NULL}};", |
| getLLVMStyleWithColumns(60)); |
| verifyGoogleFormat("SomeType Status::global_reps[3] = {\n" |
| " {kGlobalRef, OK_CODE, NULL, NULL, NULL},\n" |
| " {kGlobalRef, CANCELLED_CODE, NULL, NULL, NULL},\n" |
| " {kGlobalRef, UNKNOWN_CODE, NULL, NULL, NULL}};"); |
| verifyFormat("CGRect cg_rect = {{rect.fLeft, rect.fTop},\n" |
| " {rect.fRight - rect.fLeft, rect.fBottom - " |
| "rect.fTop}};"); |
| |
| verifyFormat( |
| "SomeArrayOfSomeType a = {\n" |
| " {{1, 2, 3},\n" |
| " {1, 2, 3},\n" |
| " {111111111111111111111111111111, 222222222222222222222222222222,\n" |
| " 333333333333333333333333333333},\n" |
| " {1, 2, 3},\n" |
| " {1, 2, 3}}};"); |
| verifyFormat( |
| "SomeArrayOfSomeType a = {\n" |
| " {{1, 2, 3}},\n" |
| " {{1, 2, 3}},\n" |
| " {{111111111111111111111111111111, 222222222222222222222222222222,\n" |
| " 333333333333333333333333333333}},\n" |
| " {{1, 2, 3}},\n" |
| " {{1, 2, 3}}};"); |
| |
| verifyFormat("struct {\n" |
| " unsigned bit;\n" |
| " const char *const name;\n" |
| "} kBitsToOs[] = {{kOsMac, \"Mac\"},\n" |
| " {kOsWin, \"Windows\"},\n" |
| " {kOsLinux, \"Linux\"},\n" |
| " {kOsCrOS, \"Chrome OS\"}};"); |
| verifyFormat("struct {\n" |
| " unsigned bit;\n" |
| " const char *const name;\n" |
| "} kBitsToOs[] = {\n" |
| " {kOsMac, \"Mac\"},\n" |
| " {kOsWin, \"Windows\"},\n" |
| " {kOsLinux, \"Linux\"},\n" |
| " {kOsCrOS, \"Chrome OS\"},\n" |
| "};"); |
| } |
| |
| TEST_F(FormatTest, FormatsSmallMacroDefinitionsInSingleLine) { |
| verifyFormat("#define ALooooooooooooooooooooooooooooooooooooooongMacro(" |
| " \\\n" |
| " aLoooooooooooooooooooooooongFuuuuuuuuuuuuuunctiooooooooo)"); |
| } |
| |
| TEST_F(FormatTest, DoesNotBreakPureVirtualFunctionDefinition) { |
| verifyFormat("virtual void write(ELFWriter *writerrr,\n" |
| " OwningPtr<FileOutputBuffer> &buffer) = 0;"); |
| |
| // Do break defaulted and deleted functions. |
| verifyFormat("virtual void ~Deeeeeeeestructor() =\n" |
| " default;", |
| getLLVMStyleWithColumns(40)); |
| verifyFormat("virtual void ~Deeeeeeeestructor() =\n" |
| " delete;", |
| getLLVMStyleWithColumns(40)); |
| } |
| |
| TEST_F(FormatTest, BreaksStringLiteralsOnlyInDefine) { |
| verifyFormat("# 1111 \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/aaaaaaaa.cpp\" 2 3", |
| getLLVMStyleWithColumns(40)); |
| verifyFormat("#line 11111 \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/aaaaaaaa.cpp\"", |
| getLLVMStyleWithColumns(40)); |
| EXPECT_EQ("#define Q \\\n" |
| " \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/\" \\\n" |
| " \"aaaaaaaa.cpp\"", |
| format("#define Q \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/aaaaaaaa.cpp\"", |
| getLLVMStyleWithColumns(40))); |
| } |
| |
| TEST_F(FormatTest, UnderstandsLinePPDirective) { |
| EXPECT_EQ("# 123 \"A string literal\"", |
| format(" # 123 \"A string literal\"")); |
| } |
| |
| TEST_F(FormatTest, LayoutUnknownPPDirective) { |
| EXPECT_EQ("#;", format("#;")); |
| verifyFormat("#\n;\n;\n;"); |
| } |
| |
| TEST_F(FormatTest, UnescapedEndOfLineEndsPPDirective) { |
| EXPECT_EQ("#line 42 \"test\"\n", |
| format("# \\\n line \\\n 42 \\\n \"test\"\n")); |
| EXPECT_EQ("#define A B\n", format("# \\\n define \\\n A \\\n B\n", |
| getLLVMStyleWithColumns(12))); |
| } |
| |
| TEST_F(FormatTest, EndOfFileEndsPPDirective) { |
| EXPECT_EQ("#line 42 \"test\"", |
| format("# \\\n line \\\n 42 \\\n \"test\"")); |
| EXPECT_EQ("#define A B", format("# \\\n define \\\n A \\\n B")); |
| } |
| |
| TEST_F(FormatTest, DoesntRemoveUnknownTokens) { |
| verifyFormat("#define A \\x20"); |
| verifyFormat("#define A \\ x20"); |
| EXPECT_EQ("#define A \\ x20", format("#define A \\ x20")); |
| verifyFormat("#define A ''"); |
| verifyFormat("#define A ''qqq"); |
| verifyFormat("#define A `qqq"); |
| verifyFormat("f(\"aaaa, bbbb, \"\\\"ccccc\\\"\");"); |
| EXPECT_EQ("const char *c = STRINGIFY(\n" |
| "\\na : b);", |
| format("const char * c = STRINGIFY(\n" |
| "\\na : b);")); |
| |
| verifyFormat("a\r\\"); |
| verifyFormat("a\v\\"); |
| verifyFormat("a\f\\"); |
| } |
| |
| TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) { |
| verifyFormat("#define A(BB)", getLLVMStyleWithColumns(13)); |
| verifyFormat("#define A( \\\n BB)", getLLVMStyleWithColumns(12)); |
| verifyFormat("#define A( \\\n A, B)", getLLVMStyleWithColumns(12)); |
| // FIXME: We never break before the macro name. |
| verifyFormat("#define AA( \\\n B)", getLLVMStyleWithColumns(12)); |
| |
| verifyFormat("#define A A\n#define A A"); |
| verifyFormat("#define A(X) A\n#define A A"); |
| |
| verifyFormat("#define Something Other", getLLVMStyleWithColumns(23)); |
| verifyFormat("#define Something \\\n Other", getLLVMStyleWithColumns(22)); |
| } |
| |
| TEST_F(FormatTest, HandlePreprocessorDirectiveContext) { |
| EXPECT_EQ("// somecomment\n" |
| "#include \"a.h\"\n" |
| "#define A( \\\n" |
| " A, B)\n" |
| "#include \"b.h\"\n" |
| "// somecomment\n", |
| format(" // somecomment\n" |
| " #include \"a.h\"\n" |
| "#define A(A,\\\n" |
| " B)\n" |
| " #include \"b.h\"\n" |
| " // somecomment\n", |
| getLLVMStyleWithColumns(13))); |
| } |
| |
| TEST_F(FormatTest, LayoutSingleHash) { EXPECT_EQ("#\na;", format("#\na;")); } |
| |
| TEST_F(FormatTest, LayoutCodeInMacroDefinitions) { |
| EXPECT_EQ("#define A \\\n" |
| " c; \\\n" |
| " e;\n" |
| "f;", |
| format("#define A c; e;\n" |
| "f;", |
| getLLVMStyleWithColumns(14))); |
| } |
| |
| TEST_F(FormatTest, LayoutRemainingTokens) { EXPECT_EQ("{}", format("{}")); } |
| |
| TEST_F(FormatTest, MacroDefinitionInsideStatement) { |
| EXPECT_EQ("int x,\n" |
| "#define A\n" |
| " y;", |
| format("int x,\n#define A\ny;")); |
| } |
| |
| TEST_F(FormatTest, HashInMacroDefinition) { |
| EXPECT_EQ("#define A(c) L#c", format("#define A(c) L#c", getLLVMStyle())); |
| verifyFormat("#define A \\\n b #c;", getLLVMStyleWithColumns(11)); |
| verifyFormat("#define A \\\n" |
| " { \\\n" |
| " f(#c); \\\n" |
| " }", |
| getLLVMStyleWithColumns(11)); |
| |
| verifyFormat("#define A(X) \\\n" |
| " void function##X()", |
| getLLVMStyleWithColumns(22)); |
| |
| verifyFormat("#define A(a, b, c) \\\n" |
| " void a##b##c()", |
| getLLVMStyleWithColumns(22)); |
| |
| verifyFormat("#define A void # ## #", getLLVMStyleWithColumns(22)); |
| } |
| |
| TEST_F(FormatTest, RespectWhitespaceInMacroDefinitions) { |
| EXPECT_EQ("#define A (x)", format("#define A (x)")); |
| EXPECT_EQ("#define A(x)", format("#define A(x)")); |
| } |
| |
| TEST_F(FormatTest, EmptyLinesInMacroDefinitions) { |
| EXPECT_EQ("#define A b;", format("#define A \\\n" |
| " \\\n" |
| " b;", |
| getLLVMStyleWithColumns(25))); |
| EXPECT_EQ("#define A \\\n" |
| " \\\n" |
| " a; \\\n" |
| " b;", |
| format("#define A \\\n" |
| " \\\n" |
| " a; \\\n" |
| " b;", |
| getLLVMStyleWithColumns(11))); |
| EXPECT_EQ("#define A \\\n" |
| " a; \\\n" |
| " \\\n" |
| " b;", |
| format("#define A \\\n" |
| " a; \\\n" |
| " \\\n" |
| " b;", |
| getLLVMStyleWithColumns(11))); |
| } |
| |
| TEST_F(FormatTest, MacroDefinitionsWithIncompleteCode) { |
| verifyIncompleteFormat("#define A :"); |
| verifyFormat("#define SOMECASES \\\n" |
| " case 1: \\\n" |
| " case 2\n", |
| getLLVMStyleWithColumns(20)); |
| verifyFormat("#define MACRO(a) \\\n" |
| " if (a) \\\n" |
| " f(); \\\n" |
| " else \\\n" |
| " g()", |
| getLLVMStyleWithColumns(18)); |
| verifyFormat("#define A template <typename T>"); |
| verifyIncompleteFormat("#define STR(x) #x\n" |
| "f(STR(this_is_a_string_literal{));"); |
| verifyFormat("#pragma omp threadprivate( \\\n" |
| " y)), // expected-warning", |
| getLLVMStyleWithColumns(28)); |
| verifyFormat("#d, = };"); |
| verifyFormat("#if \"a"); |
| verifyIncompleteFormat("({\n" |
| "#define b \\\n" |
| " } \\\n" |
| " a\n" |
| "a", |
| getLLVMStyleWithColumns(15)); |
| verifyFormat("#define A \\\n" |
| " { \\\n" |
| " {\n" |
| "#define B \\\n" |
| " } \\\n" |
| " }", |
| getLLVMStyleWithColumns(15)); |
| verifyNoCrash("#if a\na(\n#else\n#endif\n{a"); |
| verifyNoCrash("a={0,1\n#if a\n#else\n;\n#endif\n}"); |
| verifyNoCrash("#if a\na(\n#else\n#endif\n) a {a,b,c,d,f,g};"); |
| verifyNoCrash("#ifdef A\n a(\n #else\n #endif\n) = []() { \n)}"); |
| } |
| |
| TEST_F(FormatTest, MacrosWithoutTrailingSemicolon) { |
| verifyFormat("SOME_TYPE_NAME abc;"); // Gated on the newline. |
| EXPECT_EQ("class A : public QObject {\n" |
| " Q_OBJECT\n" |
| "\n" |
| " A() {}\n" |
| "};", |
| format("class A : public QObject {\n" |
| " Q_OBJECT\n" |
| "\n" |
| " A() {\n}\n" |
| "} ;")); |
| EXPECT_EQ("MACRO\n" |
| "/*static*/ int i;", |
| format("MACRO\n" |
| " /*static*/ int i;")); |
| EXPECT_EQ("SOME_MACRO\n" |
| "namespace {\n" |
| "void f();\n" |
| "} // namespace", |
| format("SOME_MACRO\n" |
| " namespace {\n" |
| "void f( );\n" |
| "} // namespace")); |
| // Only if the identifier contains at least 5 characters. |
| EXPECT_EQ("HTTP f();", format("HTTP\nf();")); |
| EXPECT_EQ("MACRO\nf();", format("MACRO\nf();")); |
| // Only if everything is upper case. |
| EXPECT_EQ("class A : public QObject {\n" |
| " Q_Object A() {}\n" |
| "};", |
| format("class A : public QObject {\n" |
| " Q_Object\n" |
| " A() {\n}\n" |
| "} ;")); |
| |
| // Only if the next line can actually start an unwrapped line. |
| EXPECT_EQ("SOME_WEIRD_LOG_MACRO << SomeThing;", |
| format("SOME_WEIRD_LOG_MACRO\n" |
| "<< SomeThing;")); |
| |
| verifyFormat("VISIT_GL_CALL(GenBuffers, void, (GLsizei n, GLuint* buffers), " |
| "(n, buffers))\n", |
| getChromiumStyle(FormatStyle::LK_Cpp)); |
| } |
| |
| TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) { |
| EXPECT_EQ("INITIALIZE_PASS_BEGIN(ScopDetection, \"polly-detect\")\n" |
| "INITIALIZE_AG_DEPENDENCY(AliasAnalysis)\n" |
| "INITIALIZE_PASS_DEPENDENCY(DominatorTree)\n" |
| "class X {};\n" |
| "INITIALIZE_PASS_END(ScopDetection, \"polly-detect\")\n" |
| "int *createScopDetectionPass() { return 0; }", |
| format(" INITIALIZE_PASS_BEGIN(ScopDetection, \"polly-detect\")\n" |
| " INITIALIZE_AG_DEPENDENCY(AliasAnalysis)\n" |
| " INITIALIZE_PASS_DEPENDENCY(DominatorTree)\n" |
| " class X {};\n" |
| " INITIALIZE_PASS_END(ScopDetection, \"polly-detect\")\n" |
| " int *createScopDetectionPass() { return 0; }")); |
| // FIXME: We could probably treat IPC_BEGIN_MESSAGE_MAP/IPC_END_MESSAGE_MAP as |
| // braces, so that inner block is indented one level more. |
| EXPECT_EQ("int q() {\n" |
| " IPC_BEGIN_MESSAGE_MAP(WebKitTestController, message)\n" |
| " IPC_MESSAGE_HANDLER(xxx, qqq)\n" |
| " IPC_END_MESSAGE_MAP()\n" |
| "}", |
| format("int q() {\n" |
| " IPC_BEGIN_MESSAGE_MAP(WebKitTestController, message)\n" |
| " IPC_MESSAGE_HANDLER(xxx, qqq)\n" |
| " IPC_END_MESSAGE_MAP()\n" |
| "}")); |
| |
| // Same inside macros. |
| EXPECT_EQ("#define LIST(L) \\\n" |
| " L(A) \\\n" |
| " L(B) \\\n" |
| " L(C)", |
| format("#define LIST(L) \\\n" |
| " L(A) \\\n" |
| " L(B) \\\n" |
| " L(C)", |
| getGoogleStyle())); |
| |
| // These must not be recognized as macros. |
| EXPECT_EQ("int q() {\n" |
| " f(x);\n" |
| " f(x) {}\n" |
| " f(x)->g();\n" |
| " f(x)->*g();\n" |
| " f(x).g();\n" |
| " f(x) = x;\n" |
| " f(x) += x;\n" |
| " f(x) -= x;\n" |
| " f(x) *= x;\n" |
| " f(x) /= x;\n" |
| " f(x) %= x;\n" |
| " f(x) &= x;\n" |
| " f(x) |= x;\n" |
| " f(x) ^= x;\n" |
| " f(x) >>= x;\n" |
| " f(x) <<= x;\n" |
| " f(x)[y].z();\n" |
| " LOG(INFO) << x;\n" |
| " ifstream(x) >> x;\n" |
| "}\n", |
| format("int q() {\n" |
| " f(x)\n;\n" |
| " f(x)\n {}\n" |
| " f(x)\n->g();\n" |
| " f(x)\n->*g();\n" |
| " f(x)\n.g();\n" |
| " f(x)\n = x;\n" |
| " f(x)\n += x;\n" |
| " f(x)\n -= x;\n" |
| " f(x)\n *= x;\n" |
| " f(x)\n /= x;\n" |
| " f(x)\n %= x;\n" |
| " f(x)\n &= x;\n" |
| " f(x)\n |= x;\n" |
| " f(x)\n ^= x;\n" |
| " f(x)\n >>= x;\n" |
| " f(x)\n <<= x;\n" |
| " f(x)\n[y].z();\n" |
| " LOG(INFO)\n << x;\n" |
| " ifstream(x)\n >> x;\n" |
| "}\n")); |
| EXPECT_EQ("int q() {\n" |
| " F(x)\n" |
| " if (1) {\n" |
| " }\n" |
| " F(x)\n" |
| " while (1) {\n" |
| " }\n" |
| " F(x)\n" |
| " G(x);\n" |
| " F(x)\n" |
| " try {\n" |
| " Q();\n" |
| " } catch (...) {\n" |
| " }\n" |
| "}\n", |
| format("int q() {\n" |
| "F(x)\n" |
| "if (1) {}\n" |
| "F(x)\n" |
| "while (1) {}\n" |
| "F(x)\n" |
| "G(x);\n" |
| "F(x)\n" |
| "try { Q(); } catch (...) {}\n" |
| "}\n")); |
| EXPECT_EQ("class A {\n" |
| " A() : t(0) {}\n" |
| " A(int i) noexcept() : {}\n" |
| " A(X x)\n" // FIXME: function-level try blocks are broken. |
| " try : t(0) {\n" |
| " } catch (...) {\n" |
| " }\n" |
| "};", |
| format("class A {\n" |
| " A()\n : t(0) {}\n" |
| " A(int i)\n noexcept() : {}\n" |
| " A(X x)\n" |
| " try : t(0) {} catch (...) {}\n" |
| "};")); |
| EXPECT_EQ("class SomeClass {\n" |
| "public:\n" |
| " SomeClass() EXCLUSIVE_LOCK_FUNCTION(mu_);\n" |
| "};", |
| format("class SomeClass {\n" |
| "public:\n" |
| " SomeClass()\n" |
| " EXCLUSIVE_LOCK_FUNCTION(mu_);\n" |
| "};")); |
| EXPECT_EQ("class SomeClass {\n" |
| "public:\n" |
| " SomeClass()\n" |
| " EXCLUSIVE_LOCK_FUNCTION(mu_);\n" |
| "};", |
| format("class SomeClass {\n" |
| "public:\n" |
| " SomeClass()\n" |
| " EXCLUSIVE_LOCK_FUNCTION(mu_);\n" |
| "};", |
| getLLVMStyleWithColumns(40))); |
| |
| verifyFormat("MACRO(>)"); |
| } |
| |
| TEST_F(FormatTest, LayoutMacroDefinitionsStatementsSpanningBlocks) { |
| verifyFormat("#define A \\\n" |
| " f({ \\\n" |
| " g(); \\\n" |
| " });", |
| getLLVMStyleWithColumns(11)); |
| } |
| |
| TEST_F(FormatTest, IndentPreprocessorDirectives) { |
| FormatStyle Style = getLLVMStyle(); |
| Style.IndentPPDirectives = FormatStyle::PPDIS_None; |
| Style.ColumnLimit = 40; |
| verifyFormat("#ifdef _WIN32\n" |
| "#define A 0\n" |
| "#ifdef VAR2\n" |
| "#define B 1\n" |
| "#include <someheader.h>\n" |
| "#define MACRO \\\n" |
| " some_very_long_func_aaaaaaaaaa();\n" |
| "#endif\n" |
| "#else\n" |
| "#define A 1\n" |
| "#endif", |
| Style); |
| Style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash; |
| verifyFormat("#ifdef _WIN32\n" |
| "# define A 0\n" |
| "# ifdef VAR2\n" |
| "# define B 1\n" |
| "# include <someheader.h>\n" |
| "# define MACRO \\\n" |
| " some_very_long_func_aaaaaaaaaa();\n" |
| "# endif\n" |
| "#else\n" |
| "# define A 1\n" |
| "#endif", |
| Style); |
| verifyFormat("#if A\n" |
| "# define MACRO \\\n" |
| " void a(int x) { \\\n" |
| " b(); \\\n" |
| " c(); \\\n" |
| " d(); \\\n" |
| " e(); \\\n" |
| " f(); \\\n" |
| " }\n" |
| "#endif", |
| Style); |
| // Comments before include guard. |
| verifyFormat("// file comment\n" |
| "// file comment\n" |
| "#ifndef HEADER_H\n" |
| "#define HEADER_H\n" |
| "code();\n" |
| "#endif", |
| Style); |
| // Test with include guards. |
| verifyFormat("#ifndef HEADER_H\n" |
| "#define HEADER_H\n" |
| "code();\n" |
| "#endif", |
| Style); |
| // Include guards must have a #define with the same variable immediately |
| // after #ifndef. |
| verifyFormat("#ifndef NOT_GUARD\n" |
| "# define FOO\n" |
| "code();\n" |
| "#endif", |
| Style); |
| |
| // Include guards must cover the entire file. |
| verifyFormat("code();\n" |
| "code();\n" |
| "#ifndef NOT_GUARD\n" |
| "# define NOT_GUARD\n" |
| "code();\n" |
| "#endif", |
| Style); |
| verifyFormat("#ifndef NOT_GUARD\n" |
| "# define NOT_GUARD\n" |
| "code();\n" |
| "#endif\n" |
| "code();", |
| Style); |
| // Test with trailing blank lines. |
| verifyFormat("#ifndef HEADER_H\n" |
| "#define HEADER_H\n" |
| "code();\n" |
| "#endif\n", |
| Style); |
| // Include guards don't have #else. |
| verifyFormat("#ifndef NOT_GUARD\n" |
| "# define NOT_GUARD\n" |
| "code();\n" |
| "#else\n" |
| "#endif", |
| Style); |
| verifyFormat("#ifndef NOT_GUARD\n" |
| "# define NOT_GUARD\n" |
| "code();\n" |
| "#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 |
| // previous code line yet, so we can't detect it. |
| EXPECT_EQ("#ifndef NOT_GUARD\n" |
| "code();\n" |
| "#define NOT_GUARD\n" |
| "code();\n" |
| "#endif", |
| format("#ifndef NOT_GUARD\n" |
| "code();\n" |
| "# define NOT_GUARD\n" |
| "code();\n" |
| "#endif", |
| Style)); |
| // FIXME: This doesn't handle cases where legitimate preprocessor lines may |
| // be outside an include guard. Examples are #pragma once and |
| // #pragma GCC diagnostic, or anything else that does not change the meaning |
| // of the file if it's included multiple times. |
| EXPECT_EQ("#ifdef WIN32\n" |
| "# pragma once\n" |
| "#endif\n" |
| "#ifndef HEADER_H\n" |
| "# define HEADER_H\n" |
| "code();\n" |
| "#endif", |
| format("#ifdef WIN32\n" |
| "# pragma once\n" |
| "#endif\n" |
| "#ifndef HEADER_H\n" |
| "#define HEADER_H\n" |
| "code();\n" |
| "#endif", |
| Style)); |
| // FIXME: This does not detect when there is a single non-preprocessor line |
| // in front of an include-guard-like structure where other conditions hold |
| // because ScopedLineState hides the line. |
| EXPECT_EQ("code();\n" |
| "#ifndef HEADER_H\n" |
| "#define HEADER_H\n" |
| "code();\n" |
| "#endif", |
| format("code();\n" |
| "#ifndef HEADER_H\n" |
| "# define HEADER_H\n" |
| "code();\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; |
| Style.TabWidth = 8; |
| verifyFormat("#ifdef _WIN32\n" |
| "#\tdefine A 0\n" |
| "#\tifdef VAR2\n" |
| "#\t\tdefine B 1\n" |
| "#\t\tinclude <someheader.h>\n" |
| "#\t\tdefine MACRO \\\n" |
| "\t\t\tsome_very_long_func_aaaaaaaaaa();\n" |
| "#\tendif\n" |
| "#else\n" |
| "#\tdefine A 1\n" |
| "#endif", |
| Style); |
| |
| // Regression test: Multiline-macro inside include guards. |
| verifyFormat("#ifndef HEADER_H\n" |
| "#define HEADER_H\n" |
| "#define A() \\\n" |
| " int i; \\\n" |
| " int j;\n" |
| "#endif // HEADER_H", |
| getLLVMStyleWithColumns(20)); |
| } |
| |
| TEST_F(FormatTest, FormatHashIfNotAtStartOfLine) { |
| verifyFormat("{\n { a #c; }\n}"); |
| } |
| |
| TEST_F(FormatTest, FormatUnbalancedStructuralElements) { |
| EXPECT_EQ("#define A \\\n { \\\n {\nint i;", |
| format("#define A { {\nint i;", getLLVMStyleWithColumns(11))); |
| EXPECT_EQ("#define A \\\n } \\\n }\nint i;", |
| format("#define A } }\nint i;", getLLVMStyleWithColumns(11))); |
| } |
| |
| TEST_F(FormatTest, EscapedNewlines) { |
| FormatStyle Narrow = getLLVMStyleWithColumns(11); |
| EXPECT_EQ("#define A \\\n int i; \\\n int j;", |
| format("#define A \\\nint i;\\\n int j;", Narrow)); |
| EXPECT_EQ("#define A\n\nint i;", format("#define A \\\n\n int i;")); |
| EXPECT_EQ("template <class T> f();", format("\\\ntemplate <class T> f();")); |
| EXPECT_EQ("/* \\ \\ \\\n */", format("\\\n/* \\ \\ \\\n */")); |
| EXPECT_EQ("<a\n\\\\\n>", format("<a\n\\\\\n>")); |
| |
| FormatStyle AlignLeft = getLLVMStyle(); |
| AlignLeft.AlignEscapedNewlines = FormatStyle::ENAS_Left; |
| EXPECT_EQ("#define MACRO(x) \\\n" |
| "private: \\\n" |
| " int x(int a);\n", |
| format("#define MACRO(x) \\\n" |
| "private: \\\n" |
| " int x(int a);\n", |
| AlignLeft)); |
| |
| // CRLF line endings |
| EXPECT_EQ("#define A \\\r\n int i; \\\r\n int j;", |
| format("#define A \\\r\nint i;\\\r\n int j;", Narrow)); |
| EXPECT_EQ("#define A\r\n\r\nint i;", format("#define A \\\r\n\r\n int i;")); |
| EXPECT_EQ("template <class T> f();", format("\\\ntemplate <class T> f();")); |
| EXPECT_EQ("/* \\ \\ \\\r\n */", format("\\\r\n/* \\ \\ \\\r\n */")); |
| EXPECT_EQ("<a\r\n\\\\\r\n>", format("<a\r\n\\\\\r\n>")); |
| EXPECT_EQ("#define MACRO(x) \\\r\n" |
| "private: \\\r\n" |
| " int x(int a);\r\n", |
| format("#define MACRO(x) \\\r\n" |
| "private: \\\r\n" |
| " int x(int a);\r\n", |
| AlignLeft)); |
| |
| FormatStyle DontAlign = getLLVMStyle(); |
| DontAlign.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; |
| DontAlign.MaxEmptyLinesToKeep = 3; |
| // FIXME: can't use verifyFormat here because the newline before |
| // "public:" is not inserted the first time it's reformatted |
| EXPECT_EQ("#define A \\\n" |
| " class Foo { \\\n" |
| " void bar(); \\\n" |
| "\\\n" |
| "\\\n" |
| "\\\n" |
| " public: \\\n" |
| " void baz(); \\\n" |
| " };", |
| format("#define A \\\n" |
| " class Foo { \\\n" |
| " void bar(); \\\n" |
| "\\\n" |
| "\\\n" |
| "\\\n" |
| " public: \\\n" |
| " void baz(); \\\n" |
| " };", |
| DontAlign)); |
| } |
| |
| TEST_F(FormatTest, CalculateSpaceOnConsecutiveLinesInMacro) { |
| verifyFormat("#define A \\\n" |
| " int v( \\\n" |
| " a); \\\n" |
| " int i;", |
| getLLVMStyleWithColumns(11)); |
| } |
| |
| TEST_F(FormatTest, MixingPreprocessorDirectivesAndNormalCode) { |
| EXPECT_EQ( |
| "#define ALooooooooooooooooooooooooooooooooooooooongMacro(" |
| " \\\n" |
| " aLoooooooooooooooooooooooongFuuuuuuuuuuuuuunctiooooooooo)\n" |
| "\n" |
| "AlooooooooooooooooooooooooooooooooooooooongCaaaaaaaaaal(\n" |
| " aLooooooooooooooooooooooonPaaaaaaaaaaaaaaaaaaaaarmmmm);\n", |
| format(" #define ALooooooooooooooooooooooooooooooooooooooongMacro(" |
| "\\\n" |
| "aLoooooooooooooooooooooooongFuuuuuuuuuuuuuunctiooooooooo)\n" |
| " \n" |
| " AlooooooooooooooooooooooooooooooooooooooongCaaaaaaaaaal(\n" |
| " aLooooooooooooooooooooooonPaaaaaaaaaaaaaaaaaaaaarmmmm);\n")); |
| } |
| |
| TEST_F(FormatTest, LayoutStatementsAroundPreprocessorDirectives) { |
| EXPECT_EQ("int\n" |
| "#define A\n" |
| " a;", |
| format("int\n#define A\na;")); |
| verifyFormat("functionCallTo(\n" |
| " someOtherFunction(\n" |
| " withSomeParameters, whichInSequence,\n" |
| " areLongerThanALine(andAnotherCall,\n" |
| "#define A B\n" |
| " withMoreParamters,\n" |
| " whichStronglyInfluenceTheLayout),\n" |
| " andMoreParameters),\n" |
| " trailing);", |
| getLLVMStyleWithColumns(69)); |
| verifyFormat("Foo::Foo()\n" |
| "#ifdef BAR\n" |
| " : baz(0)\n" |
| "#endif\n" |
| "{\n" |
| "}"); |
| verifyFormat("void f() {\n" |
| " if (true)\n" |
| "#ifdef A\n" |
| " f(42);\n" |
| " x();\n" |
| "#else\n" |
| " g();\n" |
| " x();\n" |
| "#endif\n" |
| "}"); |
| verifyFormat("void f(param1, param2,\n" |
| " param3,\n" |
| "#ifdef A\n" |
| " param4(param5,\n" |
| "#ifdef A1\n" |
| " param6,\n" |
| "#ifdef A2\n" |
| " param7),\n" |
| "#else\n" |
| " param8),\n" |
| " param9,\n" |
| "#endif\n" |
| " param10,\n" |
| "#endif\n" |
| " param11)\n" |
| "#else\n" |
| " param12)\n" |
| "#endif\n" |
| "{\n" |
| " x();\n" |
| "}", |
| getLLVMStyleWithColumns(28)); |
| verifyFormat("#if 1\n" |
| "int i;"); |
| verifyFormat("#if 1\n" |
| "#endif\n" |
| "#if 1\n" |
| "#else\n" |
| "#endif\n"); |
| verifyFormat("DEBUG({\n" |
| " return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n" |
| "});\n" |
| "#if a\n" |
| "#else\n" |
| "#endif"); |
| |
| verifyIncompleteFormat("void f(\n" |
| "#if A\n" |
| ");\n" |
| "#else\n" |
| "#endif"); |
| } |
| |
| TEST_F(FormatTest, GraciouslyHandleIncorrectPreprocessorConditions) { |
| verifyFormat("#endif\n" |
| "#if B"); |
| } |
| |
| TEST_F(FormatTest, FormatsJoinedLinesOnSubsequentRuns) { |
| FormatStyle SingleLine = getLLVMStyle(); |
| SingleLine.AllowShortIfStatementsOnASingleLine = true; |
| verifyFormat("#if 0\n" |
| "#elif 1\n" |
| "#endif\n" |
| "void foo() {\n" |
| " if (test) foo2();\n" |
| "}", |
| SingleLine); |
| } |
| |
| TEST_F(FormatTest, LayoutBlockInsideParens) { |
| verifyFormat("functionCall({ int i; });"); |
| verifyFormat("functionCall({\n" |
| " int i;\n" |
| " int j;\n" |
| "});"); |
| verifyFormat("functionCall(\n" |
| " {\n" |
| " int i;\n" |
| " int j;\n" |
| " },\n" |
| " aaaa, bbbb, cccc);"); |
| verifyFormat("functionA(functionB({\n" |
| " int i;\n" |
| " int j;\n" |
| " }),\n" |
| " aaaa, bbbb, cccc);"); |
| verifyFormat("functionCall(\n" |
| " {\n" |
| " int i;\n" |
| " int j;\n" |
| " },\n" |
| " aaaa, bbbb, // comment\n" |
| " cccc);"); |
| verifyFormat("functionA(functionB({\n" |
| " int i;\n" |
| " int j;\n" |
| " }),\n" |
| " aaaa, bbbb, // comment\n" |
| " cccc);"); |
| verifyFormat("functionCall(aaaa, bbbb, { int i; });"); |
| verifyFormat("functionCall(aaaa, bbbb, {\n" |
| " int i;\n" |
| " int j;\n" |
| "});"); |
| verifyFormat( |
| "Aaa(\n" // FIXME: There shouldn't be a linebreak here. |
| " {\n" |
| " int i; // break\n" |
| " },\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,\n" |
| " ccccccccccccccccc));"); |
| verifyFormat("DEBUG({\n" |
| " if (a)\n" |
| " f();\n" |
| "});"); |
| } |
| |
| TEST_F(FormatTest, LayoutBlockInsideStatement) { |
| EXPECT_EQ("SOME_MACRO { int i; }\n" |
| "int i;", |
| format(" SOME_MACRO {int i;} int i;")); |
| } |
| |
| TEST_F(FormatTest, LayoutNestedBlocks) { |
| verifyFormat("void AddOsStrings(unsigned bitmask) {\n" |
| " struct s {\n" |
| " int i;\n" |
| " };\n" |
| " s kBitsToOs[] = {{10}};\n" |
| " for (int i = 0; i < 10; ++i)\n" |
| " return;\n" |
| "}"); |
| verifyFormat("call(parameter, {\n" |
| " something();\n" |
| " // Comment using all columns.\n" |
| " somethingelse();\n" |
| "});", |
| getLLVMStyleWithColumns(40)); |
| verifyFormat("DEBUG( //\n" |
| " { f(); }, a);"); |
| verifyFormat("DEBUG( //\n" |
| " {\n" |
| " f(); //\n" |
| " },\n" |
| " a);"); |
| |
| EXPECT_EQ("call(parameter, {\n" |
| " something();\n" |
| " // Comment too\n" |
| " // looooooooooong.\n" |
| " somethingElse();\n" |
| "});", |
| format("call(parameter, {\n" |
| " something();\n" |
| " // Comment too looooooooooong.\n" |
| " somethingElse();\n" |
| "});", |
| getLLVMStyleWithColumns(29))); |
| EXPECT_EQ("DEBUG({ int i; });", format("DEBUG({ int i; });")); |
| EXPECT_EQ("DEBUG({ // comment\n" |
| " int i;\n" |
| "});", |
| format("DEBUG({ // comment\n" |
| "int i;\n" |
| "});")); |
| EXPECT_EQ("DEBUG({\n" |
| " int i;\n" |
| "\n" |
| " // comment\n" |
| " int j;\n" |
| "});", |
| format("DEBUG({\n" |
| " int i;\n" |
| "\n" |
| " // comment\n" |
| " int j;\n" |
| "});")); |
| |
| verifyFormat("DEBUG({\n" |
| " if (a)\n" |
| " return;\n" |
| "});"); |
| verifyGoogleFormat("DEBUG({\n" |
| " if (a) return;\n" |
| "});"); |
| FormatStyle Style = getGoogleStyle(); |
| Style.ColumnLimit = 45; |
| verifyFormat("Debug(aaaaa,\n" |
| " {\n" |
| " if (aaaaaaaaaaaaaaaaaaaaaaaa) return;\n" |
| " },\n" |
| " a);", |
| Style); |
| |
| verifyFormat("SomeFunction({MACRO({ return output; }), b});"); |
| |
| verifyNoCrash("^{v^{a}}"); |
| } |
| |
| TEST_F(FormatTest, FormatNestedBlocksInMacros) { |
| EXPECT_EQ("#define MACRO() \\\n" |
| " Debug(aaa, /* force line break */ \\\n" |
| " { \\\n" |
| " int i; \\\n" |
| " int j; \\\n" |
| " })", |
| format("#define MACRO() Debug(aaa, /* force line break */ \\\n" |
| " { int i; int j; })", |
| getGoogleStyle())); |
| |
| EXPECT_EQ("#define A \\\n" |
| " [] { \\\n" |
| " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( \\\n" |
| " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx); \\\n" |
| " }", |
| format("#define A [] { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( \\\n" |
| "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx); }", |
| getGoogleStyle())); |
| } |
| |
| TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { |
| EXPECT_EQ("{}", format("{}")); |
| verifyFormat("enum E {};"); |
| verifyFormat("enum E {}"); |
| } |
| |
| TEST_F(FormatTest, FormatBeginBlockEndMacros) { |
| FormatStyle Style = getLLVMStyle(); |
| Style.MacroBlockBegin = "^[A-Z_]+_BEGIN$"; |
| Style.MacroBlockEnd = "^[A-Z_]+_END$"; |
| verifyFormat("FOO_BEGIN\n" |
| " FOO_ENTRY\n" |
| "FOO_END", Style); |
| verifyFormat("FOO_BEGIN\n" |
| " NESTED_FOO_BEGIN\n" |
| " NESTED_FOO_ENTRY\n" |
| " NESTED_FOO_END\n" |
| "FOO_END", Style); |
| verifyFormat("FOO_BEGIN(Foo, Bar)\n" |
| " int x;\n" |
| " x = 1;\n" |
| "FOO_END(Baz)", Style); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Line break tests. |
| //===----------------------------------------------------------------------===// |
| |
| TEST_F(FormatTest, PreventConfusingIndents) { |
| verifyFormat( |
| "void f() {\n" |
| " SomeLongMethodName(SomeReallyLongMethod(CallOtherReallyLongMethod(\n" |
| " parameter, parameter, parameter)),\n" |
| " SecondLongCall(parameter));\n" |
| "}"); |
| verifyFormat( |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaa);"); |
| verifyFormat( |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " [aaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]\n" |
| " [aaaaaaaaaaaaaaaaaaaaaaaa]];"); |
| verifyFormat( |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaa<\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>,\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaa>;"); |
| verifyFormat("int a = bbbb && ccc &&\n" |
| " fffff(\n" |
| "#define A Just forcing a new line\n" |
| " ddd);"); |
| } |
| |
| TEST_F(FormatTest, LineBreakingInBinaryExpressions) { |
| verifyFormat( |
| "bool aaaaaaa =\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaa).aaaaaaaaaaaaaaaaaaa() ||\n" |
| " bbbbbbbb();"); |
| verifyFormat( |
| "bool aaaaaaa =\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaa).aaaaaaaaaaaaaaaaaaa() or\n" |
| " bbbbbbbb();"); |
| |
| verifyFormat("bool aaaaaaaaaaaaaaaaaaaaa =\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa != bbbbbbbbbbbbbbbbbb &&\n" |
| " ccccccccc == ddddddddddd;"); |
| verifyFormat("bool aaaaaaaaaaaaaaaaaaaaa =\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa != bbbbbbbbbbbbbbbbbb and\n" |
| " ccccccccc == ddddddddddd;"); |
| verifyFormat( |
| "bool aaaaaaaaaaaaaaaaaaaaa =\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa not_eq bbbbbbbbbbbbbbbbbb and\n" |
| " ccccccccc == ddddddddddd;"); |
| |
| verifyFormat("aaaaaa = aaaaaaa(aaaaaaa, // break\n" |
| " aaaaaa) &&\n" |
| " bbbbbb && cccccc;"); |
| verifyFormat("aaaaaa = aaaaaaa(aaaaaaa, // break\n" |
| " aaaaaa) >>\n" |
| " bbbbbb;"); |
| verifyFormat("aa = Whitespaces.addUntouchableComment(\n" |
| " SourceMgr.getSpellingColumnNumber(\n" |
| " TheLine.Last->FormatTok.Tok.getLocation()) -\n" |
| " 1);"); |
| |
| verifyFormat("if ((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" |
| " bbbbbbbbbbbbbbbbbb) && // aaaaaaaaaaaaaaaa\n" |
| " cccccc) {\n}"); |
| verifyFormat("if constexpr ((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" |
| " bbbbbbbbbbbbbbbbbb) && // aaaaaaaaaaa\n" |
| " cccccc) {\n}"); |
| verifyFormat("b = a &&\n" |
| " // Comment\n" |
| " b.c && d;"); |
| |
| // If the LHS of a comparison is not a binary expression itself, the |
| // additional linebreak confuses many people. |
| verifyFormat( |
| "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) > 5) {\n" |
| "}"); |
| verifyFormat( |
| "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) == 5) {\n" |
| "}"); |
| verifyFormat( |
| "if (aaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) == 5) {\n" |
| "}"); |
| verifyFormat( |
| "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) <=> 5) {\n" |
| "}"); |
| // Even explicit parentheses stress the precedence enough to make the |
| // additional break unnecessary. |
| verifyFormat("if ((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) == 5) {\n" |
| "}"); |
| // This cases is borderline, but with the indentation it is still readable. |
| verifyFormat( |
| "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" |
| " aaaaaaaaaaaaaaa) > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n" |
| "}", |
| getLLVMStyleWithColumns(75)); |
| |
| // If the LHS is a binary expression, we should still use the additional break |
| // as otherwise the formatting hides the operator precedence. |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==\n" |
| " 5) {\n" |
| "}"); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa <=>\n" |
| " 5) {\n" |
| "}"); |
| |
| FormatStyle OnePerLine = getLLVMStyle(); |
| OnePerLine.BinPackParameters = false; |
| verifyFormat( |
| "if (aaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}", |
| OnePerLine); |
| |
| verifyFormat("int i = someFunction(aaaaaaa, 0)\n" |
| " .aaa(aaaaaaaaaaaaa) *\n" |
| " aaaaaaa +\n" |
| " aaaaaaa;", |
| getLLVMStyleWithColumns(40)); |
| } |
| |
| TEST_F(FormatTest, ExpressionIndentation) { |
| verifyFormat("bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *\n" |
| " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +\n" |
| " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb &&\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >\n" |
| " ccccccccccccccccccccccccccccccccccccccccc;"); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==\n" |
| " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}"); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==\n" |
| " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}"); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}"); |
| verifyFormat("if () {\n" |
| "} else if (aaaaa && bbbbb > // break\n" |
| " ccccc) {\n" |
| "}"); |
| verifyFormat("if () {\n" |
| "} else if (aaaaa &&\n" |
| " bbbbb > // break\n" |
| " ccccc &&\n" |
| " ddddd) {\n" |
| "}"); |
| |
| // Presence of a trailing comment used to change indentation of b. |
| verifyFormat("return aaaaaaaaaaaaaaaaaaa +\n" |
| " b;\n" |
| "return aaaaaaaaaaaaaaaaaaa +\n" |
| " b; //", |
| getLLVMStyleWithColumns(30)); |
| } |
| |
| TEST_F(FormatTest, ExpressionIndentationBreakingBeforeOperators) { |
| // Not sure what the best system is here. Like this, the LHS can be found |
| // immediately above an operator (everything with the same or a higher |
| // indent). The RHS is aligned right of the operator and so compasses |
| // everything until something with the same indent as the operator is found. |
| // FIXME: Is this a good system? |
| FormatStyle Style = getLLVMStyle(); |
| Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; |
| verifyFormat( |
| "bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " > ccccccccccccccccccccccccccccccccccccccccc;", |
| Style); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " == bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}", |
| Style); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " == bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}", |
| Style); |
| verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}", |
| Style); |
| verifyFormat("if () {\n" |
| "} else if (aaaaa\n" |
| " && bbbbb // break\n" |
| " > ccccc) {\n" |
| "}", |
| Style); |
| verifyFormat("return (a)\n" |
| " // comment\n" |
| " + b;", |
| Style); |
| verifyFormat( |
| "int aaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " + cc;", |
| Style); |
| |
| verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " = aaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaa;", |
| Style); |
| |
| // Forced by comments. |
| verifyFormat( |
| "unsigned ContentSize =\n" |
| " sizeof(int16_t) // DWARF ARange version number\n" |
| " + sizeof(int32_t) // Offset of CU in the .debug_info section\n" |
| " + sizeof(int8_t) // Pointer Size (in bytes)\n" |
| " + sizeof(int8_t); // Segment Size (in bytes)"); |
| |
| verifyFormat("return boost::fusion::at_c<0>(iiii).second\n" |
| " == boost::fusion::at_c<1>(iiii).second;", |
| Style); |
| |
| Style.ColumnLimit = 60; |
| verifyFormat("zzzzzzzzzz\n" |
| " = bbbbbbbbbbbbbbbbb\n" |
| " >> aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaa);", |
| Style); |
| } |
| |
| TEST_F(FormatTest, EnforcedOperatorWraps) { |
| // Here we'd like to wrap after the || operators, but a comment is forcing an |
| // earlier wrap. |
| verifyFormat("bool x = aaaaa //\n" |
| " || bbbbb\n" |
| " //\n" |
| " || cccc;"); |
| } |
| |
| TEST_F(FormatTest, NoOperandAlignment) { |
| FormatStyle Style = getLLVMStyle(); |
| Style.AlignOperands = false; |
| verifyFormat("aaaaaaaaaaaaaa(aaaaaaaaaaaa,\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n" |
| " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);", |
| Style); |
| Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; |
| verifyFormat("bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " > ccccccccccccccccccccccccccccccccccccccccc;", |
| Style); |
| |
| verifyFormat("int aaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" |
| " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " + cc;", |
| Style); |
| verifyFormat("int a = aa\n" |
| " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" |
| " * cccccccccccccccccccccccccccccccccccc;\n", |
| Style); |
| |
| Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; |
| verifyFormat("return (a > b\n" |
| " // comment1\n" |
| " // comment2\n" |
| " || c);", |
| Style); |
|