diff options
Diffstat (limited to 'unittests/Format')
-rw-r--r-- | unittests/Format/CleanupTest.cpp | 513 | ||||
-rw-r--r-- | unittests/Format/FormatTest.cpp | 683 | ||||
-rw-r--r-- | unittests/Format/FormatTestComments.cpp | 22 | ||||
-rw-r--r-- | unittests/Format/FormatTestJS.cpp | 32 | ||||
-rw-r--r-- | unittests/Format/FormatTestJava.cpp | 8 | ||||
-rw-r--r-- | unittests/Format/FormatTestObjC.cpp | 513 | ||||
-rw-r--r-- | unittests/Format/FormatTestProto.cpp | 289 | ||||
-rw-r--r-- | unittests/Format/FormatTestRawStrings.cpp | 269 | ||||
-rw-r--r-- | unittests/Format/FormatTestSelective.cpp | 74 | ||||
-rw-r--r-- | unittests/Format/FormatTestTextProto.cpp | 577 | ||||
-rw-r--r-- | unittests/Format/NamespaceEndCommentsFixerTest.cpp | 6 | ||||
-rw-r--r-- | unittests/Format/SortIncludesTest.cpp | 44 | ||||
-rw-r--r-- | unittests/Format/UsingDeclarationsSorterTest.cpp | 6 |
13 files changed, 2292 insertions, 744 deletions
diff --git a/unittests/Format/CleanupTest.cpp b/unittests/Format/CleanupTest.cpp index 708fdf896890c..f4a36d8e1f717 100644 --- a/unittests/Format/CleanupTest.cpp +++ b/unittests/Format/CleanupTest.cpp @@ -358,156 +358,27 @@ TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) { EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); } -TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) { - std::string Code = "int main() {}"; - std::string Expected = "#include \"a.h\"\n" - "int main() {}"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"a.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) { - std::string Code = "#ifndef A_H\n" - "#define A_H\n" - "class A {};\n" - "#define MMM 123\n" - "#endif"; - std::string Expected = "#ifndef A_H\n" - "#define A_H\n" - "#include \"b.h\"\n" - "class A {};\n" - "#define MMM 123\n" - "#endif"; - - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"b.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) { - std::string Code = "#ifndef A_H\n" - "#define A_H\n" - "\n" - "\n" - "\n" - "#include <vector>\n" - "class A {};\n" - "#define MMM 123\n" - "#endif"; - std::string Expected = "#ifndef A_H\n" - "#define A_H\n" - "\n" - "\n" - "\n" - "#include \"a.h\"\n" - "#include <vector>\n" - "class A {};\n" - "#define MMM 123\n" - "#endif"; - - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"a.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) { - std::string Code = "#include \"fix.h\"\n" - "\n" - "int main() {}"; - std::string Expected = "#include \"fix.h\"\n" - "#include <a>\n" - "\n" - "int main() {}"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <a>")}); - Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) { - std::string Code = "#include <memory>\n" - "\n" - "int main() {}"; - std::string Expected = "#include \"z.h\"\n" - "#include <memory>\n" - "\n" - "int main() {}"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"z.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) { - std::string Code = "#include <memory>\n" - "\n" - "int main() {}"; - std::string Expected = "#include <memory>\n" - "#include \"z.h\"\n" - "\n" - "int main() {}"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"z.h\"")}); - Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) { - std::string Code = "#include \"x/fix.h\"\n" - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"clang/Format/Format.h\"\n" - "#include <memory>\n"; - std::string Expected = "#include \"x/fix.h\"\n" - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"d.h\"\n" - "#include \"clang/Format/Format.h\"\n" - "#include \"llvm/x/y.h\"\n" - "#include <memory>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"d.h\""), - createInsertion("#include \"llvm/x/y.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) { std::string Code = "#include \"x/fix.h\"\n" "#include \"a.h\"\n" "#include \"b.h\"\n" + "#include \"z.h\"\n" "#include \"clang/Format/Format.h\"\n" "#include <memory>\n"; std::string Expected = "#include \"x/fix.h\"\n" "#include \"a.h\"\n" "#include \"b.h\"\n" "#include \"new/new.h\"\n" + "#include \"z.h\"\n" "#include \"clang/Format/Format.h\"\n" - "#include <memory>\n" - "#include <list>\n"; + "#include <list>\n" + "#include <memory>\n"; tooling::Replacements Replaces = toReplacements({createInsertion("#include <list>"), createInsertion("#include \"new/new.h\"")}); EXPECT_EQ(Expected, apply(Code, Replaces)); } -TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) { - std::string Code = "#include \"x/fix.h\"\n" - "\n" - "#include \"y/a.h\"\n" - "#include \"z/b.h\"\n"; - // FIXME: inserting after the empty line following the main header might be - // prefered. - std::string Expected = "#include \"x/fix.h\"\n" - "#include <vector>\n" - "\n" - "#include \"y/a.h\"\n" - "#include \"z/b.h\"\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) { std::string Code = "#include \"x/fix.h\"\n" "\n" @@ -517,12 +388,12 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) { "#include \"z/b.h\"\n"; std::string Expected = "#include \"x/fix.h\"\n" "\n" - "#include <vector>\n" "#include <list>\n" + "#include <vector>\n" "\n" + "#include \"x/x.h\"\n" "#include \"y/a.h\"\n" - "#include \"z/b.h\"\n" - "#include \"x/x.h\"\n"; + "#include \"z/b.h\"\n"; tooling::Replacements Replaces = toReplacements({createInsertion("#include <list>"), createInsertion("#include \"x/x.h\"")}); @@ -565,6 +436,19 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) { EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); } +TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) { + std::string Code = "#include <map>"; + // FIXME: a better behavior is to only append on newline to Code, but this + // case should be rare in practice. + std::string Expected = + "#include <map>\n#include <string>\n\n#include <vector>\n"; + tooling::Replacements Replaces = + toReplacements({createInsertion("#include <string>"), + createInsertion("#include <vector>")}); + EXPECT_EQ(Expected, apply(Code, Replaces)); +} + + TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) { std::string Code = "\n" "int x;\n" @@ -590,225 +474,6 @@ TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) { EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); } -TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) { - std::string Code = "void f() {}\n" - "#define A \\\n" - " int i;"; - std::string Expected = "#include <vector>\n" - "void f() {}\n" - "#define A \\\n" - " int i;"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, SkippedTopComment) { - std::string Code = "// comment\n" - "\n" - " // comment\n"; - std::string Expected = "// comment\n" - "\n" - " // comment\n" - "#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, SkippedMixedComments) { - std::string Code = "// comment\n" - "// comment \\\n" - " comment continued\n" - "/*\n" - "* comment\n" - "*/\n"; - std::string Expected = "// comment\n" - "// comment \\\n" - " comment continued\n" - "/*\n" - "* comment\n" - "*/\n" - "#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) { - std::string Code = "/*\n" - "* comment\n" - "*/ /* comment\n" - "*/\n" - "\n\n" - "/* c1 */ /*c2 */\n"; - std::string Expected = "/*\n" - "* comment\n" - "*/ /* comment\n" - "*/\n" - "\n\n" - "/* c1 */ /*c2 */\n" - "#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, CodeAfterComments) { - std::string Code = "/*\n" - "* comment\n" - "*/ /* comment\n" - "*/\n" - "\n\n" - "/* c1 */ /*c2 */\n" - "\n" - "int x;\n"; - std::string Expected = "/*\n" - "* comment\n" - "*/ /* comment\n" - "*/\n" - "\n\n" - "/* c1 */ /*c2 */\n" - "\n" - "#include <vector>\n" - "int x;\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) { - std::string Code = "// comment \n" - "#ifdef X\n" - "#define X\n"; - std::string Expected = "// comment \n" - "#include <vector>\n" - "#ifdef X\n" - "#define X\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) { - std::string Code = "// comment \n" - "#ifndef X\n" - "#define X\n" - "int x;\n" - "#define Y 1\n"; - std::string Expected = "// comment \n" - "#ifndef X\n" - "#define X\n" - "#include <vector>\n" - "int x;\n" - "#define Y 1\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) { - std::string Code = "// comment \n" - "#ifndef X\n" - "int x;\n" - "#define Y 1\n"; - std::string Expected = "// comment \n" - "#include <vector>\n" - "#ifndef X\n" - "int x;\n" - "#define Y 1\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, FakeHeaderGuard) { - std::string Code = "// comment \n" - "#ifndef X\n" - "#define 1\n"; - std::string Expected = "// comment \n" - "#include <vector>\n" - "#ifndef X\n" - "#define 1\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) { - std::string Code = "// comment \n" - "#ifndef X // comment\n" - "// comment\n" - "/* comment\n" - "*/\n" - "/* comment */ #define X\n" - "int x;\n" - "#define Y 1\n"; - std::string Expected = "// comment \n" - "#ifndef X // comment\n" - "// comment\n" - "/* comment\n" - "*/\n" - "/* comment */ #define X\n" - "#include <vector>\n" - "int x;\n" - "#define Y 1\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, EmptyCode) { - std::string Code = ""; - std::string Expected = "#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) { - std::string Code = "#include <map>"; - std::string Expected = "#include <map>\n#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) { - std::string Code = "#include <map>"; - std::string Expected = - "#include <map>\n#include <string>\n#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <string>"), - createInsertion("#include <vector>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) { - std::string Code = "#include \"a.h\"\n" - "#include <vector>\n"; - std::string Expected = "#include \"a.h\"\n" - "#include <vector>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <vector>"), - createInsertion("#include \"a.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) { - std::string Code = "#include \"a.h\"\n" - "#include <vector>\n"; - // FIXME: this might not be the best behavior. - std::string Expected = "#include \"a.h\"\n" - "#include \"vector\"\n" - "#include <vector>\n" - "#include <a.h>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"vector\""), - createInsertion("#include <a.h>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) { std::string Code = "#include \"abc.h\"\n" "#include \"xyz.h\" // comment\n" @@ -821,33 +486,6 @@ TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) { EXPECT_EQ(Expected, apply(Code, Replaces)); } -TEST_F(CleanUpReplacementsTest, DeleteAllCode) { - std::string Code = "#include \"xyz.h\"\n" - "#include <xyz.h>"; - std::string Expected = ""; - tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) { - std::string Code = "#include \"xyz.h\"\n" - "#include \"xyz\"\n" - "#include <xyz.h>\n"; - std::string Expected = "#include \"xyz\"\n"; - tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) { - std::string Code = "#include \"xyz.h\"\n" - "#include \"xyz\"\n" - "#include <xyz.h>"; - std::string Expected = "#include \"xyz.h\"\n" - "#include \"xyz\"\n"; - tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) { std::string Code = "#include \"a.h\"\n" "\n" @@ -860,117 +498,6 @@ TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) { EXPECT_EQ(Expected, apply(Code, Replaces)); } -TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) { - std::string Code = "#include \"a.h\"\n" - "void f() {}\n" - "#include \"b.h\"\n"; - std::string Expected = "#include \"a.h\"\n" - "#include \"c.h\"\n" - "void f() {}\n" - "#include \"b.h\"\n"; - tooling::Replacements Replaces = toReplacements( - {createInsertion("#include \"c.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) { - std::string Code = "#include \"a.h\"\n" - "const char[] = R\"(\n" - "#include \"b.h\"\n" - ")\";\n"; - std::string Expected = "#include \"a.h\"\n" - "#include \"c.h\"\n" - "const char[] = R\"(\n" - "#include \"b.h\"\n" - ")\";\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"c.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) { - std::string Code = "#include \"a.h\"\n" - "#ifdef X\n" - "#include \"b.h\"\n" - "#endif\n"; - std::string Expected = "#include \"a.h\"\n" - "#include \"c.h\"\n" - "#ifdef X\n" - "#include \"b.h\"\n" - "#endif\n"; - tooling::Replacements Replaces = toReplacements( - {createInsertion("#include \"c.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) { - std::string Code = "#include \"a.h\"\n" - "// comment\n\n" - "#include <a/b/c/d/e.h>\n"; - std::string Expected = "#include \"a.h\"\n" - "// comment\n\n" - "#include <a/b/c/d/e.h>\n" - "#include <x.h>\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include <x.h>")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) { - std::string Code = "#include \"a.h\"\n" - "// Comment\n" - "\n" - "/* Comment */\n" - "// Comment\n" - "\n" - "#include \"b.h\"\n"; - std::string Expected = "#include \"a.h\"\n" - "// Comment\n" - "\n" - "/* Comment */\n" - "// Comment\n" - "\n" - "#include \"b.h\"\n" - "#include \"c.h\"\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"c.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, LongCommentsInTheBeginningOfFile) { - std::string Code = "// Loooooooooooooooooooooooooong comment\n" - "// Loooooooooooooooooooooooooong comment\n" - "// Loooooooooooooooooooooooooong comment\n" - "#include <string>\n" - "#include <vector>\n" - "\n" - "#include \"a.h\"\n" - "#include \"b.h\"\n"; - std::string Expected = "// Loooooooooooooooooooooooooong comment\n" - "// Loooooooooooooooooooooooooong comment\n" - "// Loooooooooooooooooooooooooong comment\n" - "#include <string>\n" - "#include <vector>\n" - "\n" - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"third.h\"\n"; - tooling::Replacements Replaces = - toReplacements({createInsertion("#include \"third.h\"")}); - Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - -TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) { - std::string Code = "#include \"a.h\"\n" - "void f() {}\n" - "#include \"b.h\"\n"; - std::string Expected = "#include \"a.h\"\n" - "void f() {}\n"; - tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")}); - EXPECT_EQ(Expected, apply(Code, Replaces)); -} - } // end namespace } // end namespace format } // end namespace clang diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 2cae9dd0c547b..f234e287cf178 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -39,8 +39,8 @@ protected: std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), StatusCheck CheckComplete = SC_ExpectComplete) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -53,7 +53,7 @@ protected: ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -72,6 +72,8 @@ protected: void verifyFormat(llvm::StringRef Expected, llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { + EXPECT_EQ(Expected.str(), format(Expected, Style)) + << "Expected code is not stable"; EXPECT_EQ(Expected.str(), format(Code, Style)); if (Style.Language == FormatStyle::LK_Cpp) { // Objective-C++ is a superset of C++, so everything checked for C++ @@ -276,11 +278,12 @@ TEST_F(FormatTest, RemovesEmptyLines) { "\n" "}")); - // FIXME: This is slightly inconsistent. + // Don't remove empty lines before namespace endings. FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle(); LLVMWithNoNamespaceFix.FixNamespaceComments = false; EXPECT_EQ("namespace {\n" "int i;\n" + "\n" "}", format("namespace {\n" "int i;\n" @@ -291,6 +294,27 @@ TEST_F(FormatTest, RemovesEmptyLines) { "}", format("namespace {\n" "int i;\n" + "}", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "\n" + "};", + format("namespace {\n" + "int i;\n" + "\n" + "};", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "};", + format("namespace {\n" + "int i;\n" + "};", LLVMWithNoNamespaceFix)); + EXPECT_EQ("namespace {\n" + "int i;\n" + "\n" + "}", + format("namespace {\n" + "int i;\n" "\n" "}")); EXPECT_EQ("namespace {\n" @@ -588,6 +612,23 @@ TEST_F(FormatTest, FormatShortBracedStatements) { AllowSimpleBracedStatements); } +TEST_F(FormatTest, ShortBlocksInMacrosDontMergeWithCodeAfterMacro) { + FormatStyle Style = getLLVMStyleWithColumns(60); + Style.AllowShortBlocksOnASingleLine = true; + Style.AllowShortIfStatementsOnASingleLine = true; + Style.BreakBeforeBraces = FormatStyle::BS_Allman; + EXPECT_EQ("#define A \\\n" + " if (HANDLEwernufrnuLwrmviferuvnierv) \\\n" + " { RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; }\n" + "X;", + format("#define A \\\n" + " if (HANDLEwernufrnuLwrmviferuvnierv) { \\\n" + " RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; \\\n" + " }\n" + "X;", + Style)); +} + TEST_F(FormatTest, ParseIfElse) { verifyFormat("if (true)\n" " if (true)\n" @@ -725,6 +766,12 @@ TEST_F(FormatTest, FormatsForLoop) { " aaaaaaaaaaaaaaaaaaaaaaaaaaa != bbbbbbbbbbbbbbbbbbbbbbb;\n" " ++aaaaaaaaaaaaaaaaaaaaaaaaaaa) {"); + // These should not be formatted as Objective-C for-in loops. + verifyFormat("for (Foo *x = 0; x != in; x++) {\n}"); + verifyFormat("Foo *x;\nfor (x = 0; x != in; x++) {\n}"); + verifyFormat("Foo *x;\nfor (x in y) {\n}"); + verifyFormat("for (const Foo<Bar> &baz = in.value(); !baz.at_end(); ++baz) {\n}"); + FormatStyle NoBinPacking = getLLVMStyle(); NoBinPacking.BinPackParameters = false; verifyFormat("for (int aaaaaaaaaaa = 1;\n" @@ -1269,15 +1316,40 @@ TEST_F(FormatTest, FormatsClasses) { verifyFormat("class ::A::B {};"); } -TEST_F(FormatTest, BreakBeforeInheritanceComma) { - FormatStyle StyleWithInheritanceBreak = getLLVMStyle(); - StyleWithInheritanceBreak.BreakBeforeInheritanceComma = true; - - verifyFormat("class MyClass : public X {};", StyleWithInheritanceBreak); +TEST_F(FormatTest, BreakInheritanceStyle) { + FormatStyle StyleWithInheritanceBreakBeforeComma = getLLVMStyle(); + StyleWithInheritanceBreakBeforeComma.BreakInheritanceList = + FormatStyle::BILS_BeforeComma; + verifyFormat("class MyClass : public X {};", + StyleWithInheritanceBreakBeforeComma); verifyFormat("class MyClass\n" " : public X\n" " , public Y {};", - StyleWithInheritanceBreak); + StyleWithInheritanceBreakBeforeComma); + verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA\n" + " : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n" + " , public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};", + StyleWithInheritanceBreakBeforeComma); + verifyFormat("struct aaaaaaaaaaaaa\n" + " : public aaaaaaaaaaaaaaaaaaa< // break\n" + " aaaaaaaaaaaaaaaa> {};", + StyleWithInheritanceBreakBeforeComma); + + FormatStyle StyleWithInheritanceBreakAfterColon = getLLVMStyle(); + StyleWithInheritanceBreakAfterColon.BreakInheritanceList = + FormatStyle::BILS_AfterColon; + verifyFormat("class MyClass : public X {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("class MyClass : public X, public Y {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA :\n" + " public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n" + " public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("struct aaaaaaaaaaaaa :\n" + " public aaaaaaaaaaaaaaaaaaa< // break\n" + " aaaaaaaaaaaaaaaa> {};", + StyleWithInheritanceBreakAfterColon); } TEST_F(FormatTest, FormatsVariableDeclarationsAfterStructOrClass) { @@ -2484,8 +2556,6 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) { "#endif", Style); // Test with include guards. - // EXPECT_EQ is used because verifyFormat() calls messUp() which incorrectly - // merges lines. verifyFormat("#ifndef HEADER_H\n" "#define HEADER_H\n" "code();\n" @@ -2532,6 +2602,20 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) { "#elif FOO\n" "#endif", Style); + // Non-identifier #define after potential include guard. + verifyFormat("#ifndef FOO\n" + "# define 1\n" + "#endif\n", + Style); + // #if closes past last non-preprocessor line. + verifyFormat("#ifndef FOO\n" + "#define FOO\n" + "#if 1\n" + "int i;\n" + "# define A 0\n" + "#endif\n" + "#endif\n", + Style); // FIXME: This doesn't handle the case where there's code between the // #ifndef and #define but all other conditions hold. This is because when // the #define line is parsed, UnwrappedLineParser::Lines doesn't hold the @@ -2580,21 +2664,85 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) { "code();\n" "#endif", Style)); - // FIXME: The comment indent corrector in TokenAnnotator gets thrown off by - // preprocessor indentation. - EXPECT_EQ("#if 1\n" - " // comment\n" - "# define A 0\n" - "// comment\n" - "# define B 0\n" - "#endif", - format("#if 1\n" - "// comment\n" - "# define A 0\n" - " // comment\n" - "# define B 0\n" - "#endif", - Style)); + // Keep comments aligned with #, otherwise indent comments normally. These + // tests cannot use verifyFormat because messUp manipulates leading + // whitespace. + { + const char *Expected = "" + "void f() {\n" + "#if 1\n" + "// Preprocessor aligned.\n" + "# define A 0\n" + " // Code. Separated by blank line.\n" + "\n" + "# define B 0\n" + " // Code. Not aligned with #\n" + "# define C 0\n" + "#endif"; + const char *ToFormat = "" + "void f() {\n" + "#if 1\n" + "// Preprocessor aligned.\n" + "# define A 0\n" + "// Code. Separated by blank line.\n" + "\n" + "# define B 0\n" + " // Code. Not aligned with #\n" + "# define C 0\n" + "#endif"; + EXPECT_EQ(Expected, format(ToFormat, Style)); + EXPECT_EQ(Expected, format(Expected, Style)); + } + // Keep block quotes aligned. + { + const char *Expected = "" + "void f() {\n" + "#if 1\n" + "/* Preprocessor aligned. */\n" + "# define A 0\n" + " /* Code. Separated by blank line. */\n" + "\n" + "# define B 0\n" + " /* Code. Not aligned with # */\n" + "# define C 0\n" + "#endif"; + const char *ToFormat = "" + "void f() {\n" + "#if 1\n" + "/* Preprocessor aligned. */\n" + "# define A 0\n" + "/* Code. Separated by blank line. */\n" + "\n" + "# define B 0\n" + " /* Code. Not aligned with # */\n" + "# define C 0\n" + "#endif"; + EXPECT_EQ(Expected, format(ToFormat, Style)); + EXPECT_EQ(Expected, format(Expected, Style)); + } + // Keep comments aligned with un-indented directives. + { + const char *Expected = "" + "void f() {\n" + "// Preprocessor aligned.\n" + "#define A 0\n" + " // Code. Separated by blank line.\n" + "\n" + "#define B 0\n" + " // Code. Not aligned with #\n" + "#define C 0\n"; + const char *ToFormat = "" + "void f() {\n" + "// Preprocessor aligned.\n" + "#define A 0\n" + "// Code. Separated by blank line.\n" + "\n" + "#define B 0\n" + " // Code. Not aligned with #\n" + "#define C 0\n"; + EXPECT_EQ(Expected, format(ToFormat, Style)); + EXPECT_EQ(Expected, format(Expected, Style)); + } // Test with tabs. Style.UseTab = FormatStyle::UT_Always; Style.IndentWidth = 8; @@ -3603,6 +3751,23 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}", Style); + + // `ConstructorInitializerIndentWidth` actually applies to InheritanceList as well + Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + verifyFormat("class SomeClass\n" + " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); + Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + verifyFormat("class SomeClass\n" + " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " , public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); + Style.BreakInheritanceList = FormatStyle::BILS_AfterColon; + verifyFormat("class SomeClass :\n" + " public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); } #ifndef EXPENSIVE_CHECKS @@ -5352,7 +5517,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { " const typename aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa);"); FormatStyle AlwaysBreak = getLLVMStyle(); - AlwaysBreak.AlwaysBreakTemplateDeclarations = true; + AlwaysBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; verifyFormat("template <typename T>\nclass C {};", AlwaysBreak); verifyFormat("template <typename T>\nvoid f();", AlwaysBreak); verifyFormat("template <typename T>\nvoid f() {}", AlwaysBreak); @@ -5370,6 +5535,83 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { "public:\n" " E *f();\n" "};"); + + FormatStyle NeverBreak = getLLVMStyle(); + NeverBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_No; + verifyFormat("template <typename T> class C {};", NeverBreak); + verifyFormat("template <typename T> void f();", NeverBreak); + verifyFormat("template <typename T> void f() {}", NeverBreak); + verifyFormat("template <typename T>\nvoid foo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}", + NeverBreak); + verifyFormat("void aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbb>(\n" + " ccccccccccccccccccccccccccccccccccccccccccccccc);", + NeverBreak); + verifyFormat("template <template <typename> class Fooooooo,\n" + " template <typename> class Baaaaaaar>\n" + "struct C {};", + NeverBreak); + verifyFormat("template <typename T> // T can be A, B or C.\n" + "struct C {};", + NeverBreak); + verifyFormat("template <enum E> class A {\n" + "public:\n" + " E *f();\n" + "};", NeverBreak); + NeverBreak.PenaltyBreakTemplateDeclaration = 100; + verifyFormat("template <typename T> void\nfoo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}", + NeverBreak); +} + +TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); + Style.ColumnLimit = 60; + EXPECT_EQ("// Baseline - no comments.\n" + "template <\n" + " typename aaaaaaaaaaaaaaaaaaaaaa<bbbbbbbbbbbb>::value>\n" + "void f() {}", + format("// Baseline - no comments.\n" + "template <\n" + " typename aaaaaaaaaaaaaaaaaaaaaa<bbbbbbbbbbbb>::value>\n" + "void f() {}", + Style)); + + EXPECT_EQ("template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + "void f() {}", + format("template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + "void f() {}", + Style)); + + EXPECT_EQ( + "template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> /* line */\n" + "void f() {}", + format("template <typename aaaaaaaaaa<bbbbbbbbbbbb>::value> /* line */\n" + "void f() {}", + Style)); + + EXPECT_EQ( + "template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + " // multiline\n" + "void f() {}", + format("template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing\n" + " // multiline\n" + "void f() {}", + Style)); + + EXPECT_EQ( + "template <typename aaaaaaaaaa<\n" + " bbbbbbbbbbbb>::value> // trailing loooong\n" + "void f() {}", + format( + "template <\n" + " typename aaaaaaaaaa<bbbbbbbbbbbb>::value> // trailing loooong\n" + "void f() {}", + Style)); } TEST_F(FormatTest, WrapsTemplateParameters) { @@ -5562,6 +5804,8 @@ TEST_F(FormatTest, UnderstandsUnaryOperators) { verifyFormat("(a->f())++;"); verifyFormat("a[42]++;"); verifyFormat("if (!(a->f())) {\n}"); + verifyFormat("if (!+i) {\n}"); + verifyFormat("~&a;"); verifyFormat("a-- > b;"); verifyFormat("b ? -a : c;"); @@ -5934,6 +6178,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("delete *x;", PointerMiddle); verifyFormat("int * x;", PointerMiddle); + verifyFormat("int *[] x;", PointerMiddle); verifyFormat("template <int * y> f() {}", PointerMiddle); verifyFormat("int * f(int * a) {}", PointerMiddle); verifyFormat("int main(int argc, char ** argv) {}", PointerMiddle); @@ -5941,7 +6186,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("A<int *> a;", PointerMiddle); verifyFormat("A<int **> a;", PointerMiddle); verifyFormat("A<int *, int *> a;", PointerMiddle); - verifyFormat("A<int * []> a;", PointerMiddle); + verifyFormat("A<int *[]> a;", PointerMiddle); verifyFormat("A = new SomeType *[Length]();", PointerMiddle); verifyFormat("A = new SomeType *[Length];", PointerMiddle); verifyFormat("T ** t = new T *;", PointerMiddle); @@ -5966,6 +6211,31 @@ TEST_F(FormatTest, UnderstandsAttributes) { AfterType); } +TEST_F(FormatTest, UnderstandsSquareAttributes) { + verifyFormat("SomeType s [[unused]] (InitValue);"); + verifyFormat("SomeType s [[gnu::unused]] (InitValue);"); + verifyFormat("SomeType s [[using gnu: unused]] (InitValue);"); + verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}"); + verifyFormat("void f() [[deprecated(\"so sorry\")]];"); + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);"); + + // Make sure we do not mistake attributes for array subscripts. + verifyFormat("int a() {}\n" + "[[unused]] int b() {}\n"); + + // On the other hand, we still need to correctly find array subscripts. + verifyFormat("int a = std::vector<int>{1, 2, 3}[0];"); + + // Make sure we do not parse attributes as lambda introducers. + FormatStyle MultiLineFunctions = getLLVMStyle(); + MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + verifyFormat("[[unused]] int b() {\n" + " return 42;\n" + "}\n", + MultiLineFunctions); +} + TEST_F(FormatTest, UnderstandsEllipsis) { verifyFormat("int printf(const char *fmt, ...);"); verifyFormat("template <class... Ts> void Foo(Ts... ts) { Foo(ts...); }"); @@ -6451,6 +6721,18 @@ TEST_F(FormatTest, IncorrectCodeUnbalancedBraces) { verifyNoCrash("(/**/[:!] ?[)."); } +TEST_F(FormatTest, IncorrectUnbalancedBracesInMacrosWithUnicode) { + // Found by oss-fuzz: + // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8212 + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); + Style.ColumnLimit = 60; + verifyNoCrash( + "\x23\x47\xff\x20\x28\xff\x3c\xff\x3f\xff\x20\x2f\x7b\x7a\xff\x20" + "\xff\xff\xff\xca\xb5\xff\xff\xff\xff\x3a\x7b\x7d\xff\x20\xff\x20" + "\xff\x74\xff\x20\x7d\x7d\xff\x7b\x3a\xff\x20\x71\xff\x20\xff\x0a", + Style); +} + TEST_F(FormatTest, IncorrectCodeDoNoWhile) { verifyFormat("do {\n}"); verifyFormat("do {\n}\n" @@ -6557,6 +6839,15 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { "};"); verifyFormat("#define A {a, a},"); + // Avoid breaking between equal sign and opening brace + FormatStyle AvoidBreakingFirstArgument = getLLVMStyle(); + AvoidBreakingFirstArgument.PenaltyBreakBeforeFirstCallParameter = 200; + verifyFormat("const std::unordered_map<std::string, int> MyHashTable =\n" + " {{\"aaaaaaaaaaaaaaaaaaaaa\", 0},\n" + " {\"bbbbbbbbbbbbbbbbbbbbb\", 1},\n" + " {\"ccccccccccccccccccccc\", 2}};", + AvoidBreakingFirstArgument); + // Binpacking only if there is no trailing comma verifyFormat("const Aaaaaa aaaaa = {aaaaaaaaaa, bbbbbbbbbb,\n" " cccccccccc, dddddddddd};", @@ -6713,6 +7004,26 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { verifyFormat("vector<int> foo = { ::SomeGlobalFunction() };", ExtraSpaces); verifyFormat("const struct A a = { .a = 1, .b = 2 };", ExtraSpaces); verifyFormat("const struct A a = { [0] = 1, [1] = 2 };", ExtraSpaces); + + // Avoid breaking between initializer/equal sign and opening brace + ExtraSpaces.PenaltyBreakBeforeFirstCallParameter = 200; + verifyFormat("const std::unordered_map<std::string, int> MyHashTable = {\n" + " { \"aaaaaaaaaaaaaaaaaaaaa\", 0 },\n" + " { \"bbbbbbbbbbbbbbbbbbbbb\", 1 },\n" + " { \"ccccccccccccccccccccc\", 2 }\n" + "};", + ExtraSpaces); + verifyFormat("const std::unordered_map<std::string, int> MyHashTable{\n" + " { \"aaaaaaaaaaaaaaaaaaaaa\", 0 },\n" + " { \"bbbbbbbbbbbbbbbbbbbbb\", 1 },\n" + " { \"ccccccccccccccccccccc\", 2 }\n" + "};", + ExtraSpaces); + + FormatStyle SpaceBeforeBrace = getLLVMStyle(); + SpaceBeforeBrace.SpaceBeforeCpp11BracedList = true; + verifyFormat("vector<int> x {1, 2, 3, 4};", SpaceBeforeBrace); + verifyFormat("f({}, {{}, {}}, MyMap[{k, v}]);", SpaceBeforeBrace); } TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { @@ -7549,16 +7860,18 @@ TEST_F(FormatTest, FormatForObjectiveCMethodDecls) { // When the function name has to be wrapped. FormatStyle Style = getLLVMStyle(); + // ObjC ignores IndentWrappedFunctionNames when wrapping methods + // and always indents instead. Style.IndentWrappedFunctionNames = false; verifyFormat("- (SomeLooooooooooooooooooooongType *)\n" - "veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n" - " anotherName:(NSString)bbbbbbbbbbbbbb {\n" + " veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n" + " anotherName:(NSString)bbbbbbbbbbbbbb {\n" "}", Style); Style.IndentWrappedFunctionNames = true; verifyFormat("- (SomeLooooooooooooooooooooongType *)\n" - " veryLooooooooooongName:(NSString)aaaaaaaaaaaaaa\n" - " anotherName:(NSString)bbbbbbbbbbbbbb {\n" + " veryLooooooooooongName:(NSString)cccccccccccccc\n" + " anotherName:(NSString)dddddddddddddd {\n" "}", Style); @@ -7983,6 +8296,9 @@ TEST_F(FormatTest, CountsCharactersInMultilineRawStringLiterals) { "multiline raw string literal xxxxxxxxxxxxxx\n" ")x\" + bbbbbb);", getGoogleStyleWithColumns(20))); + EXPECT_EQ("fffffffffff(R\"(single line raw string)\" + bbbbbb);", + format("fffffffffff(\n" + " R\"(single line raw string)\" + bbbbbb);")); } TEST_F(FormatTest, SkipsUnknownStringLiterals) { @@ -8704,6 +9020,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParentheses) { FormatStyle Spaces = getLLVMStyle(); Spaces.SpacesInParentheses = true; + verifyFormat("do_something( ::globalVar );", Spaces); verifyFormat("call( x, y, z );", Spaces); verifyFormat("call();", Spaces); verifyFormat("std::function<void( int, int )> callback;", Spaces); @@ -8840,6 +9157,137 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeAssignmentOperators) { verifyFormat("a or_eq 8;", Spaces); } +TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { + verifyFormat("class Foo : public Bar {};"); + verifyFormat("Foo::Foo() : foo(1) {}"); + verifyFormat("for (auto a : b) {\n}"); + verifyFormat("int x = a ? b : c;"); + verifyFormat("{\n" + "label0:\n" + " int x = 0;\n" + "}"); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}"); + + FormatStyle CtorInitializerStyle = getLLVMStyleWithColumns(30); + CtorInitializerStyle.SpaceBeforeCtorInitializerColon = false; + verifyFormat("class Foo : public Bar {};", CtorInitializerStyle); + verifyFormat("Foo::Foo(): foo(1) {}", CtorInitializerStyle); + verifyFormat("for (auto a : b) {\n}", CtorInitializerStyle); + verifyFormat("int x = a ? b : c;", CtorInitializerStyle); + verifyFormat("{\n" + "label1:\n" + " int x = 0;\n" + "}", + CtorInitializerStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + CtorInitializerStyle); + CtorInitializerStyle.BreakConstructorInitializers = + FormatStyle::BCIS_AfterColon; + verifyFormat("Fooooooooooo::Fooooooooooo():\n" + " aaaaaaaaaaaaaaaa(1),\n" + " bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + CtorInitializerStyle.BreakConstructorInitializers = + FormatStyle::BCIS_BeforeComma; + verifyFormat("Fooooooooooo::Fooooooooooo()\n" + " : aaaaaaaaaaaaaaaa(1)\n" + " , bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + CtorInitializerStyle.BreakConstructorInitializers = + FormatStyle::BCIS_BeforeColon; + verifyFormat("Fooooooooooo::Fooooooooooo()\n" + " : aaaaaaaaaaaaaaaa(1),\n" + " bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + CtorInitializerStyle.ConstructorInitializerIndentWidth = 0; + verifyFormat("Fooooooooooo::Fooooooooooo()\n" + ": aaaaaaaaaaaaaaaa(1),\n" + " bbbbbbbbbbbbbbbb(2) {}", + CtorInitializerStyle); + + FormatStyle InheritanceStyle = getLLVMStyleWithColumns(30); + InheritanceStyle.SpaceBeforeInheritanceColon = false; + verifyFormat("class Foo: public Bar {};", InheritanceStyle); + verifyFormat("Foo::Foo() : foo(1) {}", InheritanceStyle); + verifyFormat("for (auto a : b) {\n}", InheritanceStyle); + verifyFormat("int x = a ? b : c;", InheritanceStyle); + verifyFormat("{\n" + "label2:\n" + " int x = 0;\n" + "}", + InheritanceStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_AfterColon; + verifyFormat("class Foooooooooooooooooooooo:\n" + " public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + verifyFormat("class Foooooooooooooooooooooo\n" + " : public aaaaaaaaaaaaaaaaaa\n" + " , public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + verifyFormat("class Foooooooooooooooooooooo\n" + " : public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.ConstructorInitializerIndentWidth = 0; + verifyFormat("class Foooooooooooooooooooooo\n" + ": public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {}", + InheritanceStyle); + + FormatStyle ForLoopStyle = getLLVMStyle(); + ForLoopStyle.SpaceBeforeRangeBasedForLoopColon = false; + verifyFormat("class Foo : public Bar {};", ForLoopStyle); + verifyFormat("Foo::Foo() : foo(1) {}", ForLoopStyle); + verifyFormat("for (auto a: b) {\n}", ForLoopStyle); + verifyFormat("int x = a ? b : c;", ForLoopStyle); + verifyFormat("{\n" + "label2:\n" + " int x = 0;\n" + "}", + ForLoopStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + ForLoopStyle); + + FormatStyle NoSpaceStyle = getLLVMStyle(); + NoSpaceStyle.SpaceBeforeCtorInitializerColon = false; + NoSpaceStyle.SpaceBeforeInheritanceColon = false; + NoSpaceStyle.SpaceBeforeRangeBasedForLoopColon = false; + verifyFormat("class Foo: public Bar {};", NoSpaceStyle); + verifyFormat("Foo::Foo(): foo(1) {}", NoSpaceStyle); + verifyFormat("for (auto a: b) {\n}", NoSpaceStyle); + verifyFormat("int x = a ? b : c;", NoSpaceStyle); + verifyFormat("{\n" + "label3:\n" + " int x = 0;\n" + "}", + NoSpaceStyle); + verifyFormat("switch (x) {\n" + "case 1:\n" + "default:\n" + "}", + NoSpaceStyle); +} + TEST_F(FormatTest, AlignConsecutiveAssignments) { FormatStyle Alignment = getLLVMStyle(); Alignment.AlignConsecutiveAssignments = false; @@ -10151,13 +10599,11 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine); CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine); - CHECK_PARSE_BOOL(AlwaysBreakTemplateDeclarations); CHECK_PARSE_BOOL(BinPackArguments); CHECK_PARSE_BOOL(BinPackParameters); CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations); CHECK_PARSE_BOOL(BreakBeforeTernaryOperators); CHECK_PARSE_BOOL(BreakStringLiterals); - CHECK_PARSE_BOOL(BreakBeforeInheritanceComma) CHECK_PARSE_BOOL(CompactNamespaces); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); CHECK_PARSE_BOOL(DerivePointerAlignment); @@ -10181,6 +10627,10 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(SpaceAfterCStyleCast); CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword); CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators); + CHECK_PARSE_BOOL(SpaceBeforeCpp11BracedList); + CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon); + CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon); + CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement); @@ -10214,6 +10664,8 @@ TEST_F(FormatTest, ParsesConfiguration) { PenaltyBreakAssignment, 1234u); CHECK_PARSE("PenaltyBreakBeforeFirstCallParameter: 1234", PenaltyBreakBeforeFirstCallParameter, 1234u); + CHECK_PARSE("PenaltyBreakTemplateDeclaration: 1234", + PenaltyBreakTemplateDeclaration, 1234u); CHECK_PARSE("PenaltyExcessCharacter: 1234", PenaltyExcessCharacter, 1234u); CHECK_PARSE("PenaltyReturnTypeOnItsOwnLine: 1234", PenaltyReturnTypeOnItsOwnLine, 1234u); @@ -10269,6 +10721,17 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("BreakConstructorInitializersBeforeComma: true", BreakConstructorInitializers, FormatStyle::BCIS_BeforeComma); + Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + CHECK_PARSE("BreakInheritanceList: BeforeComma", + BreakInheritanceList, FormatStyle::BILS_BeforeComma); + CHECK_PARSE("BreakInheritanceList: AfterColon", + BreakInheritanceList, FormatStyle::BILS_AfterColon); + CHECK_PARSE("BreakInheritanceList: BeforeColon", + BreakInheritanceList, FormatStyle::BILS_BeforeColon); + // For backward compatibility: + CHECK_PARSE("BreakBeforeInheritanceComma: true", + BreakInheritanceList, FormatStyle::BILS_BeforeComma); + Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; CHECK_PARSE("AlignAfterOpenBracket: Align", AlignAfterOpenBracket, FormatStyle::BAS_Align); @@ -10368,6 +10831,18 @@ TEST_F(FormatTest, ParsesConfiguration) { AlwaysBreakAfterReturnType, FormatStyle::RTBS_TopLevelDefinitions); + Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_No); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_MultiLine); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: Yes", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_Yes); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: false", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_MultiLine); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: true", AlwaysBreakTemplateDeclarations, + FormatStyle::BTDS_Yes); + Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None", AlwaysBreakAfterDefinitionReturnType, FormatStyle::DRTBS_None); @@ -10397,29 +10872,52 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", ForEachMacros, BoostAndQForeach); - Style.IncludeCategories.clear(); - std::vector<FormatStyle::IncludeCategory> ExpectedCategories = {{"abc/.*", 2}, - {".*", 1}}; + Style.IncludeStyle.IncludeCategories.clear(); + std::vector<tooling::IncludeStyle::IncludeCategory> ExpectedCategories = { + {"abc/.*", 2}, {".*", 1}}; CHECK_PARSE("IncludeCategories:\n" " - Regex: abc/.*\n" " Priority: 2\n" " - Regex: .*\n" " Priority: 1", - IncludeCategories, ExpectedCategories); - CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeIsMainRegex, "abc$"); + IncludeStyle.IncludeCategories, ExpectedCategories); + CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeStyle.IncludeIsMainRegex, + "abc$"); Style.RawStringFormats.clear(); std::vector<FormatStyle::RawStringFormat> ExpectedRawStringFormats = { - {"pb", FormatStyle::LK_TextProto, "llvm"}, - {"cpp", FormatStyle::LK_Cpp, "google"}}; + { + FormatStyle::LK_TextProto, + {"pb", "proto"}, + {"PARSE_TEXT_PROTO"}, + /*CanonicalDelimiter=*/"", + "llvm", + }, + { + FormatStyle::LK_Cpp, + {"cc", "cpp"}, + {"C_CODEBLOCK", "CPPEVAL"}, + /*CanonicalDelimiter=*/"cc", + /*BasedOnStyle=*/"", + }, + }; CHECK_PARSE("RawStringFormats:\n" - " - Delimiter: 'pb'\n" - " Language: TextProto\n" + " - Language: TextProto\n" + " Delimiters:\n" + " - 'pb'\n" + " - 'proto'\n" + " EnclosingFunctions:\n" + " - 'PARSE_TEXT_PROTO'\n" " BasedOnStyle: llvm\n" - " - Delimiter: 'cpp'\n" - " Language: Cpp\n" - " BasedOnStyle: google", + " - Language: Cpp\n" + " Delimiters:\n" + " - 'cc'\n" + " - 'cpp'\n" + " EnclosingFunctions:\n" + " - 'C_CODEBLOCK'\n" + " - 'CPPEVAL'\n" + " CanonicalDelimiter: 'cc'", RawStringFormats, ExpectedRawStringFormats); } @@ -11608,6 +12106,13 @@ TEST_F(FormatTest, NoSpaceAfterSuper) { verifyFormat("__super::FooBar();"); } +TEST(FormatStyle, GetStyleWithEmptyFileName) { + vfs::InMemoryFileSystem FS; + auto Style1 = getStyle("file", "", "Google", "", &FS); + ASSERT_TRUE((bool)Style1); + ASSERT_EQ(*Style1, getGoogleStyle()); +} + TEST(FormatStyle, GetStyleOfFile) { vfs::InMemoryFileSystem FS; // Test 1: format file in the same directory. @@ -11837,6 +12342,90 @@ TEST_F(FormatTest, StructuredBindings) { verifyFormat("auto const &[ a, b ] = f();", Spaces); } +TEST_F(FormatTest, FileAndCode) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.cc", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.m", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.mm", "")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@interface Foo\n@end\n")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define TRY(x, y) @try { x; } @finally { y; }")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define AVAIL(x) @available(x, *))")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo.h", "@class Foo;")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo", "")); + EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo", "@interface Foo\n@end\n")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int DoStuff(CGRect rect);\n")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", + "#define MY_POINT_MAKE(x, y) CGPointMake((x), (y));\n")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO(...) auto bar = [] __VA_ARGS__;")); +} + +TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[noreturn]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "array[[calculator getIndex]];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[noreturn, deprecated(\"so sorry\")]];")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[noreturn, deprecated(\"gone, sorry\")]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "[[noreturn foo] bar];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[clang::fallthrough]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "[[clang:fallthrough] foo];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[gsl::suppress(\"type\")]];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[using clang: fallthrough]];")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "[[abusing clang:fallthrough] bar];")); + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "[[using gsl: suppress(\"type\")]];")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", + "[[clang::callable_when(\"unconsumed\", \"unknown\")]]")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[foo::bar, ...]]")); +} + +TEST_F(FormatTest, GuessLanguageWithCaret) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^);")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^, Bar);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^)(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo)(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[10])(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[kNumEntries])(char, float);")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);")); +} + +TEST_F(FormatTest, GuessLanguageWithChildLines) { + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO ({ std::string s; })")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define FOO ({ NSString *s; })")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO ({ foo(); ({ std::string s; }) })")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define FOO ({ foo(); ({ NSString *s; }) })")); +} + } // end namespace } // end namespace format } // end namespace clang diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp index ed11fbdb1fc0d..cacd2024fef3a 100644 --- a/unittests/Format/FormatTestComments.cpp +++ b/unittests/Format/FormatTestComments.cpp @@ -38,8 +38,8 @@ protected: std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), StatusCheck CheckComplete = SC_ExpectComplete) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -52,7 +52,7 @@ protected: ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -70,6 +70,7 @@ protected: void verifyFormat(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { + EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable"; EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); } @@ -3089,6 +3090,21 @@ TEST_F(FormatTestComments, BreaksBeforeTrailingUnbreakableSequence) { getLLVMStyleWithColumns(23)); } +TEST_F(FormatTestComments, ReflowBackslashCrash) { +// clang-format off + EXPECT_EQ( +"// How to run:\n" +"// bbbbb run \\\n" +"// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n" +"// \\ <log_file> -- --output_directory=\"<output_directory>\"", + format( +"// How to run:\n" +"// bbbbb run \\\n" +"// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr \\\n" +"// <log_file> -- --output_directory=\"<output_directory>\"")); +// clang-format on +} + } // end namespace } // end namespace format } // end namespace clang diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 2a929563f7544..9975b7d311253 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -21,8 +21,8 @@ class FormatTestJS : public ::testing::Test { protected: static std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length, const FormatStyle &Style) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -30,7 +30,7 @@ protected: EXPECT_TRUE(Status.FormatComplete); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -49,6 +49,8 @@ protected: static void verifyFormat( llvm::StringRef Code, const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) { + EXPECT_EQ(Code.str(), format(Code, Style)) + << "Expected code is not stable"; std::string Result = format(test::messUp(Code), Style); EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result; } @@ -57,6 +59,8 @@ protected: llvm::StringRef Expected, llvm::StringRef Code, const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) { + EXPECT_EQ(Expected.str(), format(Expected, Style)) + << "Expected code is not stable"; std::string Result = format(Code, Style); EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result; } @@ -294,6 +298,7 @@ TEST_F(FormatTestJS, ReservedWords) { verifyFormat("x.for = 1;"); verifyFormat("x.of();"); verifyFormat("of(null);"); + verifyFormat("return of(null);"); verifyFormat("import {of} from 'x';"); verifyFormat("x.in();"); verifyFormat("x.let();"); @@ -1157,6 +1162,17 @@ TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) { "foo() {}", getGoogleJSStyleWithColumns(10)); verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10)); + verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10)); + verifyFormat("x = (a['a']\n" + " ['b']);", + getGoogleJSStyleWithColumns(10)); + verifyFormat("function f() {\n" + " return foo.bar(\n" + " (param): param is {\n" + " a: SomeType\n" + " }&ABC => 1)\n" + "}", + getGoogleJSStyleWithColumns(25)); } TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) { @@ -1524,6 +1540,15 @@ TEST_F(FormatTestJS, ClassDeclarations) { "}"); } +TEST_F(FormatTestJS, StrictPropInitWrap) { + const FormatStyle &Style = getGoogleJSStyleWithColumns(22); + verifyFormat("class X {\n" + " strictPropInitField!:\n" + " string;\n" + "}", + Style); +} + TEST_F(FormatTestJS, InterfaceDeclarations) { verifyFormat("interface I {\n" " x: string;\n" @@ -2129,6 +2154,7 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) { verifyFormat("let x = foo!.bar();\n"); verifyFormat("let x = foo ? bar! : baz;\n"); verifyFormat("let x = !foo;\n"); + verifyFormat("if (!+a) {\n}"); verifyFormat("let x = foo[0]!;\n"); verifyFormat("let x = (foo)!;\n"); verifyFormat("let x = x(foo!);\n"); diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp index 2f376f765d66d..76e82612e0fec 100644 --- a/unittests/Format/FormatTestJava.cpp +++ b/unittests/Format/FormatTestJava.cpp @@ -21,13 +21,13 @@ class FormatTestJava : public ::testing::Test { protected: static std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length, const FormatStyle &Style) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); tooling::Replacements Replaces = reformat(Style, Code, Ranges); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -46,6 +46,7 @@ protected: static void verifyFormat( llvm::StringRef Code, const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_Java)) { + EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable"; EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); } }; @@ -144,6 +145,7 @@ TEST_F(FormatTestJava, ClassDeclarations) { verifyFormat("public interface SomeInterface {\n" " void doStuff(int theStuff);\n" " void doMoreStuff(int moreStuff);\n" + " default void doStuffWithDefault() {}\n" "}"); verifyFormat("@interface SomeInterface {\n" " void doStuff(int theStuff);\n" diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index 4220b44b4c47f..e56df6d130d25 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -40,8 +40,8 @@ protected: std::string format(llvm::StringRef Code, StatusCheck CheckComplete = SC_ExpectComplete) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -53,11 +53,12 @@ protected: } auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } void verifyFormat(StringRef Code) { + EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable"; EXPECT_EQ(Code.str(), format(test::messUp(Code))); } @@ -94,6 +95,75 @@ TEST(FormatTestObjCStyle, DetectsObjCInHeaders) { Style = getStyle("LLVM", "a.h", "none", "void f() {}"); ASSERT_TRUE((bool)Style); EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language); + + Style = getStyle("{}", "a.h", "none", "@interface Foo\n@end\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", + "const int interface = 1;\nconst int end = 2;\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language); + + Style = getStyle("{}", "a.h", "none", "@protocol Foo\n@end\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", + "const int protocol = 1;\nconst int end = 2;\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language); + + Style = + getStyle("{}", "a.h", "none", "typedef NS_ENUM(NSInteger, Foo) {};\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", "enum Foo {};"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language); + + Style = + getStyle("{}", "a.h", "none", "inline void Foo() { Log(@\"Foo\"); }\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = + getStyle("{}", "a.h", "none", "inline void Foo() { Log(\"Foo\"); }\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language); + + Style = + getStyle("{}", "a.h", "none", "inline void Foo() { id = @[1, 2, 3]; }\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", + "inline void Foo() { id foo = @{1: 2, 3: 4, 5: 6}; }\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", + "inline void Foo() { int foo[] = {1, 2, 3}; }\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_Cpp, Style->Language); + + // ObjC characteristic types. + Style = getStyle("{}", "a.h", "none", "extern NSString *kFoo;\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", "extern NSInteger Foo();\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", "NSObject *Foo();\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); + + Style = getStyle("{}", "a.h", "none", "NSSet *Foo();\n"); + ASSERT_TRUE((bool)Style); + EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language); } TEST_F(FormatTestObjC, FormatObjCTryCatch) { @@ -118,7 +188,8 @@ TEST_F(FormatTestObjC, FormatObjCAutoreleasepool) { "@autoreleasepool {\n" " f();\n" "}\n"); - Style.BreakBeforeBraces = FormatStyle::BS_Allman; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterControlStatement = true; verifyFormat("@autoreleasepool\n" "{\n" " f();\n" @@ -129,6 +200,36 @@ TEST_F(FormatTestObjC, FormatObjCAutoreleasepool) { "}\n"); } +TEST_F(FormatTestObjC, FormatObjCGenerics) { + Style.ColumnLimit = 40; + verifyFormat("int aaaaaaaaaaaaaaaa(\n" + " NSArray<aaaaaaaaaaaaaaaaaa *>\n" + " aaaaaaaaaaaaaaaaa);\n"); + verifyFormat("int aaaaaaaaaaaaaaaa(\n" + " NSArray<aaaaaaaaaaaaaaaaaaa<\n" + " aaaaaaaaaaaaaaaa *> *>\n" + " aaaaaaaaaaaaaaaaa);\n"); +} + +TEST_F(FormatTestObjC, FormatObjCSynchronized) { + verifyFormat("@synchronized(self) {\n" + " f();\n" + "}\n" + "@synchronized(self) {\n" + " f();\n" + "}\n"); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterControlStatement = true; + verifyFormat("@synchronized(self)\n" + "{\n" + " f();\n" + "}\n" + "@synchronized(self)\n" + "{\n" + " f();\n" + "}\n"); +} + TEST_F(FormatTestObjC, FormatObjCInterface) { verifyFormat("@interface Foo : NSObject <NSSomeDelegate> {\n" "@public\n" @@ -155,6 +256,12 @@ TEST_F(FormatTestObjC, FormatObjCInterface) { "@end"); verifyFormat("@interface Foo : Bar\n" + "@property(assign, readwrite) NSInteger bar;\n" + "+ (id)init;\n" + "@end"); + + verifyFormat("FOUNDATION_EXPORT NS_AVAILABLE_IOS(10.0) @interface Foo : Bar\n" + "@property(assign, readwrite) NSInteger bar;\n" "+ (id)init;\n" "@end"); @@ -192,6 +299,18 @@ TEST_F(FormatTestObjC, FormatObjCInterface) { "+ (id)init;\n" "@end"); + verifyFormat("@interface Foo<Baz : Blech> : Bar <Baz, Quux> {\n" + " int _i;\n" + "}\n" + "+ (id)init;\n" + "@end"); + + verifyFormat("@interface Foo<Bar : Baz <Blech>> : Xyzzy <Corge> {\n" + " int _i;\n" + "}\n" + "+ (id)init;\n" + "@end"); + verifyFormat("@interface Foo (HackStuff) {\n" " int _i;\n" "}\n" @@ -209,9 +328,46 @@ TEST_F(FormatTestObjC, FormatObjCInterface) { "}\n" "+ (id)init;\n" "@end"); + verifyFormat("@interface Foo\n" + "- (void)foo {\n" + "}\n" + "@end\n" + "@implementation Bar\n" + "- (void)bar {\n" + "}\n" + "@end"); + Style.ColumnLimit = 40; + verifyFormat("@interface ccccccccccccc () <\n" + " ccccccccccccc, ccccccccccccc,\n" + " ccccccccccccc, ccccccccccccc> {\n" + "}"); + verifyFormat("@interface ccccccccccccc (ccccccccccc) <\n" + " ccccccccccccc> {\n" + "}"); + Style.ObjCBinPackProtocolList = FormatStyle::BPS_Never; + verifyFormat("@interface ddddddddddddd () <\n" + " ddddddddddddd,\n" + " ddddddddddddd,\n" + " ddddddddddddd,\n" + " ddddddddddddd> {\n" + "}"); + + Style.BinPackParameters = false; + Style.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; + verifyFormat("@interface eeeeeeeeeeeee () <\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee> {\n" + "}"); + Style.ObjCBinPackProtocolList = FormatStyle::BPS_Always; + verifyFormat("@interface fffffffffffff () <\n" + " fffffffffffff, fffffffffffff,\n" + " fffffffffffff, fffffffffffff> {\n" + "}"); Style = getGoogleStyle(FormatStyle::LK_ObjC); - verifyFormat("@interface Foo : NSObject<NSSomeDelegate> {\n" + verifyFormat("@interface Foo : NSObject <NSSomeDelegate> {\n" " @public\n" " int field1;\n" " @protected\n" @@ -223,19 +379,22 @@ TEST_F(FormatTestObjC, FormatObjCInterface) { "}\n" "+ (id)init;\n" "@end"); - verifyFormat("@interface Foo : Bar<Baz, Quux>\n" + verifyFormat("@interface Foo : Bar <Baz, Quux>\n" "+ (id)init;\n" "@end"); - verifyFormat("@interface Foo (HackStuff)<MyProtocol>\n" + verifyFormat("@interface Foo (HackStuff) <MyProtocol>\n" "+ (id)init;\n" "@end"); - Style.BinPackParameters = false; - Style.ColumnLimit = 80; - verifyFormat("@interface aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ()<\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> {\n" + Style.ColumnLimit = 40; + // BinPackParameters should be true by default. + verifyFormat("void eeeeeeee(int eeeee, int eeeee,\n" + " int eeeee, int eeeee);\n"); + // ObjCBinPackProtocolList should be BPS_Never by default. + verifyFormat("@interface fffffffffffff () <\n" + " fffffffffffff,\n" + " fffffffffffff,\n" + " fffffffffffff,\n" + " fffffffffffff> {\n" "}"); } @@ -334,6 +493,10 @@ TEST_F(FormatTestObjC, FormatObjCProtocol) { "@protocol Bar\n" "@end"); + verifyFormat("FOUNDATION_EXPORT NS_AVAILABLE_IOS(10.0) @protocol Foo\n" + "@property(assign, readwrite) NSInteger bar;\n" + "@end"); + verifyFormat("@protocol myProtocol\n" "- (void)mandatoryWithInt:(int)i;\n" "@optional\n" @@ -354,7 +517,7 @@ TEST_F(FormatTestObjC, FormatObjCProtocol) { "@end"); Style = getGoogleStyle(FormatStyle::LK_ObjC); - verifyFormat("@protocol MyProtocol<NSObject>\n" + verifyFormat("@protocol MyProtocol <NSObject>\n" "- (NSUInteger)numberOfThings;\n" "@end"); } @@ -374,6 +537,7 @@ TEST_F(FormatTestObjC, FormatObjCMethodDeclarations) { " evenLongerKeyword:(float)theInterval\n" " error:(NSError **)theError {\n" "}"); + verifyFormat("+ (instancetype)new;\n"); Style.ColumnLimit = 60; verifyFormat("- (instancetype)initXxxxxx:(id<x>)x\n" " y:(id<yyyyyyyyyyyyyyyyyyyy>)y\n" @@ -381,12 +545,26 @@ TEST_F(FormatTestObjC, FormatObjCMethodDeclarations) { verifyFormat("- (void)drawRectOn:(id)surface\n" " ofSize:(size_t)height\n" " :(size_t)width;"); + Style.ColumnLimit = 40; + // Make sure selectors with 0, 1, or more arguments are indented when wrapped. + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); + verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n"); // Continuation indent width should win over aligning colons if the function // name is long. Style = getGoogleStyle(FormatStyle::LK_ObjC); Style.ColumnLimit = 40; - Style.IndentWrappedFunctionNames = true; verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n" " dontAlignNamef:(NSRect)theRect {\n" "}"); @@ -478,6 +656,9 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { verifyFormat("for (id foo in [self getStuffFor:bla]) {\n" "}"); verifyFormat("[self aaaaa:MACRO(a, b:, c:)];"); + verifyFormat("[self aaaaa:MACRO(a, b:c:, d:e:)];"); + verifyFormat("[self aaaaa:MACRO(a, b:c:d:, e:f:g:)];"); + verifyFormat("int XYMyFoo(int a, int b) NS_SWIFT_NAME(foo(self:scale:));"); verifyFormat("[self aaaaa:(1 + 2) bbbbb:3];"); verifyFormat("[self aaaaa:(Type)a bbbbb:3];"); @@ -497,6 +678,18 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { verifyFormat("[(id)foo bar:(id) ? baz : quux];"); verifyFormat("4 > 4 ? (id)a : (id)baz;"); + unsigned PreviousColumnLimit = Style.ColumnLimit; + Style.ColumnLimit = 50; + // Instead of: + // bool a = + // ([object a:42] == 0 || [object a:42 + // b:42] == 0); + verifyFormat("bool a = ([object a:42] == 0 ||\n" + " [object a:42 b:42] == 0);"); + Style.ColumnLimit = PreviousColumnLimit; + verifyFormat("bool a = ([aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaa ||\n" + " [aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaaaaa);"); + // This tests that the formatter doesn't break after "backing" but before ":", // which would be at 80 columns. verifyFormat( @@ -573,17 +766,101 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { "[self aaaaaaaaaaaaa:aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];"); + verifyFormat("[self // break\n" " a:a\n" " aaa:aaa];"); - verifyFormat("bool a = ([aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaa ||\n" - " [aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaaaaa);"); // Formats pair-parameters. verifyFormat("[I drawRectOn:surface ofSize:aa:bbb atOrigin:cc:dd];"); verifyFormat("[I drawRectOn:surface //\n" - " ofSize:aa:bbb\n" - " atOrigin:cc:dd];"); + " ofSize:aa:bbb\n" + " atOrigin:cc:dd];"); + + // Inline block as a first argument. + verifyFormat("[object justBlock:^{\n" + " a = 42;\n" + "}];"); + verifyFormat("[object\n" + " justBlock:^{\n" + " a = 42;\n" + " }\n" + " notBlock:42\n" + " a:42];"); + verifyFormat("[object\n" + " firstBlock:^{\n" + " a = 42;\n" + " }\n" + " blockWithLongerName:^{\n" + " a = 42;\n" + " }];"); + verifyFormat("[object\n" + " blockWithLongerName:^{\n" + " a = 42;\n" + " }\n" + " secondBlock:^{\n" + " a = 42;\n" + " }];"); + verifyFormat("[object\n" + " firstBlock:^{\n" + " a = 42;\n" + " }\n" + " notBlock:42\n" + " secondBlock:^{\n" + " a = 42;\n" + " }];"); + + // Space between cast rparen and selector name component. + verifyFormat("[((Foo *)foo) bar];"); + verifyFormat("[((Foo *)foo) bar:1 blech:2];"); + + Style.ColumnLimit = 20; + verifyFormat("aaaaa = [a aa:aa\n" + " aa:aa];"); + verifyFormat("aaaaaa = [aa aa:aa\n" + " aa:aa];"); + + // Message receiver taking multiple lines. + // Non-corner case. + verifyFormat("[[object block:^{\n" + " return 42;\n" + "}] a:42 b:42];"); + // Arguments just fit into one line. + verifyFormat("[[object block:^{\n" + " return 42;\n" + "}] aaaaaaa:42 b:42];"); + // Arguments just over a column limit. + verifyFormat("[[object block:^{\n" + " return 42;\n" + "}] aaaaaaa:42\n" + " bb:42];"); + // Arguments just fit into one line. + Style.ColumnLimit = 23; + verifyFormat("[[obj a:42\n" + " b:42\n" + " c:42\n" + " d:42] e:42 f:42];"); + + // Arguments do not fit into one line with a receiver. + Style.ColumnLimit = 20; + verifyFormat("[[obj a:42] a:42\n" + " b:42];"); + verifyFormat("[[obj a:42] a:42\n" + " b:42\n" + " c:42];"); + verifyFormat("[[obj aaaaaa:42\n" + " b:42]\n" + " cc:42\n" + " d:42];"); + + // Avoid breaking receiver expression. + Style.ColumnLimit = 30; + verifyFormat("fooooooo =\n" + " [[obj fooo] aaa:42\n" + " aaa:42];"); + verifyFormat("[[[obj foo] bar] aa:42\n" + " bb:42\n" + " cc:42];"); Style.ColumnLimit = 70; verifyFormat( @@ -616,6 +893,26 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { " backing:NSBackingStoreBuffered\n" " defer:NO]);\n" "}"); + + // Respect continuation indent and colon alignment (e.g. when object name is + // short, and first selector is the longest one) + Style = getLLVMStyle(); + Style.Language = FormatStyle::LK_ObjC; + Style.ContinuationIndentWidth = 8; + verifyFormat("[self performSelectorOnMainThread:@selector(loadAccessories)\n" + " withObject:nil\n" + " waitUntilDone:false];"); + verifyFormat("[self performSelector:@selector(loadAccessories)\n" + " withObjectOnMainThread:nil\n" + " waitUntilDone:false];"); + verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaa\n" + " performSelectorOnMainThread:@selector(loadAccessories)\n" + " withObject:nil\n" + " waitUntilDone:false];"); + verifyFormat("[self // force wrapping\n" + " performSelectorOnMainThread:@selector(loadAccessories)\n" + " withObject:nil\n" + " waitUntilDone:false];"); } TEST_F(FormatTestObjC, ObjCAt) { @@ -652,6 +949,15 @@ TEST_F(FormatTestObjC, ObjCAt) { verifyFormat("@ /*foo*/ interface"); } +TEST_F(FormatTestObjC, ObjCBlockTypesAndVariables) { + verifyFormat("void DoStuffWithBlockType(int (^)(char));"); + verifyFormat("int (^foo)(char, float);"); + verifyFormat("int (^foo[10])(char, float);"); + verifyFormat("int (^foo[kNumEntries])(char, float);"); + verifyFormat("int (^foo[kNumEntries + 10])(char, float);"); + verifyFormat("int (^foo[(kNumEntries + 10)])(char, float);"); +} + TEST_F(FormatTestObjC, ObjCSnippets) { verifyFormat("@autoreleasepool {\n" " foo();\n" @@ -676,6 +982,14 @@ TEST_F(FormatTestObjC, ObjCSnippets) { verifyFormat("@property(assign, nonatomic) CGFloat hoverAlpha;"); verifyFormat("@property(assign, getter=isEditable) BOOL editable;"); + Style.ColumnLimit = 50; + verifyFormat("@interface Foo\n" + "- (void)doStuffWithFoo:(id)name\n" + " bar:(id)bar\n" + " baz:(id)baz\n" + " NS_SWIFT_NAME(doStuff(withFoo:bar:baz:));\n" + "@end"); + Style = getMozillaStyle(); verifyFormat("@property (assign, getter=isEditable) BOOL editable;"); verifyFormat("@property BOOL editable;"); @@ -700,6 +1014,88 @@ TEST_F(FormatTestObjC, ObjCForIn) { " foo(n);\n" " }\n" "}"); + verifyFormat("for (Foo *x in bar) {\n}"); + verifyFormat("for (Foo *x in [bar baz]) {\n}"); + verifyFormat("for (Foo *x in [bar baz:blech]) {\n}"); + verifyFormat("for (Foo *x in [bar baz:blech, 1, 2, 3, 0]) {\n}"); + verifyFormat("for (Foo *x in [bar baz:^{\n" + " [uh oh];\n" + " }]) {\n}"); +} + +TEST_F(FormatTestObjC, ObjCCxxKeywords) { + verifyFormat("+ (instancetype)new {\n" + " return nil;\n" + "}\n"); + verifyFormat("+ (instancetype)myNew {\n" + " return [self new];\n" + "}\n"); + verifyFormat("SEL NewSelector(void) { return @selector(new); }\n"); + verifyFormat("SEL MacroSelector(void) { return MACRO(new); }\n"); + verifyFormat("+ (instancetype)delete {\n" + " return nil;\n" + "}\n"); + verifyFormat("+ (instancetype)myDelete {\n" + " return [self delete];\n" + "}\n"); + verifyFormat("SEL DeleteSelector(void) { return @selector(delete); }\n"); + verifyFormat("SEL MacroSelector(void) { return MACRO(delete); }\n"); + verifyFormat("MACRO(new:)\n"); + verifyFormat("MACRO(delete:)\n"); + verifyFormat("foo = @{MACRO(new:) : MACRO(delete:)}\n"); + verifyFormat("@implementation Foo\n" + "// Testing\n" + "- (Class)class {\n" + "}\n" + "- (void)foo {\n" + "}\n" + "@end\n"); + verifyFormat("@implementation Foo\n" + "- (Class)class {\n" + "}\n" + "- (void)foo {\n" + "}\n" + "@end"); + verifyFormat("@implementation Foo\n" + "+ (Class)class {\n" + "}\n" + "- (void)foo {\n" + "}\n" + "@end"); + verifyFormat("@implementation Foo\n" + "- (Class)class:(Class)klass {\n" + "}\n" + "- (void)foo {\n" + "}\n" + "@end"); + verifyFormat("@implementation Foo\n" + "+ (Class)class:(Class)klass {\n" + "}\n" + "- (void)foo {\n" + "}\n" + "@end"); + + verifyFormat("@interface Foo\n" + "// Testing\n" + "- (Class)class;\n" + "- (void)foo;\n" + "@end\n"); + verifyFormat("@interface Foo\n" + "- (Class)class;\n" + "- (void)foo;\n" + "@end"); + verifyFormat("@interface Foo\n" + "+ (Class)class;\n" + "- (void)foo;\n" + "@end"); + verifyFormat("@interface Foo\n" + "- (Class)class:(Class)klass;\n" + "- (void)foo;\n" + "@end"); + verifyFormat("@interface Foo\n" + "+ (Class)class:(Class)klass;\n" + "- (void)foo;\n" + "@end"); } TEST_F(FormatTestObjC, ObjCLiterals) { @@ -776,6 +1172,30 @@ TEST_F(FormatTestObjC, ObjCDictLiterals) { " (aaaaaaaa id)aaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaaaaaaaaaaaa,\n" " (aaaaaaaa id)aaaaaaaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaa,\n" "};"); + Style.ColumnLimit = 40; + verifyFormat("int Foo() {\n" + " a12345 = @{a12345 : a12345};\n" + "}"); + verifyFormat("int Foo() {\n" + " a12345 = @{a12345 : @(a12345)};\n" + "}"); + verifyFormat("int Foo() {\n" + " a12345 = @{(Foo *)a12345 : @(a12345)};\n" + "}"); + verifyFormat("int Foo() {\n" + " a12345 = @{@(a12345) : a12345};\n" + "}"); + verifyFormat("int Foo() {\n" + " a12345 = @{@(a12345) : @YES};\n" + "}"); + Style.SpacesInContainerLiterals = false; + verifyFormat("int Foo() {\n" + " b12345 = @{b12345: b12345};\n" + "}"); + verifyFormat("int Foo() {\n" + " b12345 = @{(Foo *)b12345: @(b12345)};\n" + "}"); + Style.SpacesInContainerLiterals = true; Style = getGoogleStyle(FormatStyle::LK_ObjC); verifyFormat( @@ -831,7 +1251,60 @@ TEST_F(FormatTestObjC, ObjCArrayLiterals) { verifyFormat("[someFunction someLooooooooooooongParameter:@[\n" " NSBundle.mainBundle.infoDictionary[@\"a\"]\n" "]];"); + Style.ColumnLimit = 40; + verifyFormat("int Foo() {\n" + " a12345 = @[ a12345, a12345 ];\n" + "}"); + verifyFormat("int Foo() {\n" + " a123 = @[ (Foo *)a12345, @(a12345) ];\n" + "}"); + Style.SpacesInContainerLiterals = false; + verifyFormat("int Foo() {\n" + " b12345 = @[b12345, b12345];\n" + "}"); + verifyFormat("int Foo() {\n" + " b12345 = @[(Foo *)b12345, @(b12345)];\n" + "}"); + Style.SpacesInContainerLiterals = true; + Style.ColumnLimit = 20; + // We can't break string literals inside NSArray literals + // (that raises -Wobjc-string-concatenation). + verifyFormat("NSArray *foo = @[\n" + " @\"aaaaaaaaaaaaaaaaaaaaaaaaaa\"\n" + "];\n"); +} + +TEST_F(FormatTestObjC, BreaksCallStatementWhereSemiJustOverTheLimit) { + Style.ColumnLimit = 60; + // If the statement starting with 'a = ...' is put on a single line, the ';' + // is at line 61. + verifyFormat("int f(int a) {\n" + " a = [self aaaaaaaaaa:bbbbbbbbb\n" + " ccccccccc:dddddddd\n" + " ee:fddd];\n" + "}"); } + +TEST_F(FormatTestObjC, AlwaysBreakBeforeMultilineStrings) { + Style = getGoogleStyle(FormatStyle::LK_ObjC); + Style.ColumnLimit = 40; + verifyFormat("aaaa = @\"bbbb\"\n" + " @\"cccc\";"); + verifyFormat("aaaa(@\"bbbb\"\n" + " @\"cccc\");"); + verifyFormat("aaaa(qqq, @\"bbbb\"\n" + " @\"cccc\");"); + verifyFormat("[aaaa qqqq:@\"bbbb\"\n" + " @\"cccc\"];"); + verifyFormat("aaaa = [aaaa qqqq:@\"bbbb\"\n" + " @\"cccc\"];"); + verifyFormat("[aaaa qqqq:@\"bbbb\"\n" + " @\"cccc\"\n" + " rr:42\n" + " ssssss:@\"ee\"\n" + " @\"fffff\"];"); +} + } // end namespace } // end namespace format } // end namespace clang diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp index df94d8172730b..d25aeb846a97c 100644 --- a/unittests/Format/FormatTestProto.cpp +++ b/unittests/Format/FormatTestProto.cpp @@ -21,13 +21,13 @@ class FormatTestProto : public ::testing::Test { protected: static std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length, const FormatStyle &Style) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); tooling::Replacements Replaces = reformat(Style, Code, Ranges); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -38,6 +38,7 @@ protected: } static void verifyFormat(llvm::StringRef Code) { + EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable"; EXPECT_EQ(Code.str(), format(test::messUp(Code))); } }; @@ -97,7 +98,7 @@ TEST_F(FormatTestProto, FormatsEnums) { " TYPE_B = 2;\n" "};"); verifyFormat("enum Type {\n" - " UNKNOWN = 0 [(some_options) = {a: aa, b: bb}];\n" + " UNKNOWN = 0 [(some_options) = { a: aa, b: bb }];\n" "};"); verifyFormat("enum Type {\n" " UNKNOWN = 0 [(some_options) = {\n" @@ -121,7 +122,7 @@ TEST_F(FormatTestProto, MessageFieldAttributes) { verifyFormat("optional LongMessageType long_proto_field = 1\n" " [default = REALLY_REALLY_LONG_CONSTANT_VALUE];"); verifyFormat("repeated double value = 1\n" - " [(aaaaaaa.aaaaaaaaa) = {aaaaaaaaaaaaaaaaa: AAAAAAAA}];"); + " [(aaaaaaa.aaaaaaaaa) = { aaaaaaaaaaaaaaaaa: AAAAAAAA }];"); verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n" " aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n" " bbbbbbbbbbbbbbbb: BBBBBBBBBB\n" @@ -158,9 +159,8 @@ TEST_F(FormatTestProto, MessageFieldAttributes) { " key: 'a' //\n" " }\n" "];"); - verifyFormat("optional string test = 1 [default =\n" - " \"test\"\n" - " \"test\"];"); + verifyFormat("optional string test = 1 [default = \"test\"\n" + " \"test\"];"); verifyFormat("optional Aaaaaaaa aaaaaaaa = 12 [\n" " (aaa) = aaaa,\n" " (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n" @@ -168,6 +168,16 @@ TEST_F(FormatTestProto, MessageFieldAttributes) { " aaaaaaaaaaaaaaaa: true\n" " }\n" "];"); + verifyFormat("extensions 20 [(proto2.type) = 'Aaaa.bbbb'];"); + verifyFormat("extensions 20\n" + " [(proto3.type) = 'Aaaa.bbbb', (aaa.Aaa) = 'aaa.bbb'];"); + verifyFormat("extensions 123 [\n" + " (aaa) = aaaa,\n" + " (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n" + " aaaaaaaaaaaaaaaaa: true,\n" + " aaaaaaaaaaaaaaaa: true\n" + " }\n" + "];"); } TEST_F(FormatTestProto, DoesntWrapFileOptions) { @@ -183,27 +193,27 @@ TEST_F(FormatTestProto, FormatsOptions) { " field_a: OK\n" " field_b: \"OK\"\n" " field_c: \"OK\"\n" - " msg_field: {field_d: 123}\n" + " msg_field: { field_d: 123 }\n" "};"); verifyFormat("option (MyProto.options) = {\n" " field_a: OK\n" " field_b: \"OK\"\n" " field_c: \"OK\"\n" - " msg_field: {field_d: 123 field_e: OK}\n" + " msg_field: { field_d: 123 field_e: OK }\n" "};"); verifyFormat("option (MyProto.options) = {\n" " field_a: OK // Comment\n" " field_b: \"OK\"\n" " field_c: \"OK\"\n" - " msg_field: {field_d: 123}\n" + " msg_field: { field_d: 123 }\n" "};"); verifyFormat("option (MyProto.options) = {\n" " field_c: \"OK\"\n" - " msg_field {field_d: 123}\n" + " msg_field { field_d: 123 }\n" "};"); verifyFormat("option (MyProto.options) = {\n" " field_a: OK\n" - " field_b {field_c: OK}\n" + " field_b { field_c: OK }\n" " field_d: OKOKOK\n" " field_e: OK\n" "}"); @@ -211,12 +221,14 @@ TEST_F(FormatTestProto, FormatsOptions) { // Support syntax with <> instead of {}. verifyFormat("option (MyProto.options) = {\n" " field_c: \"OK\",\n" - " msg_field: <field_d: 123>\n" + " msg_field: < field_d: 123 >\n" + " empty: <>\n" + " empty <>\n" "};"); verifyFormat("option (MyProto.options) = {\n" " field_a: OK\n" - " field_b <field_c: OK>\n" + " field_b < field_c: OK >\n" " field_d: OKOKOK\n" " field_e: OK\n" "}"); @@ -224,9 +236,9 @@ TEST_F(FormatTestProto, FormatsOptions) { verifyFormat("option (MyProto.options) = {\n" " msg_field: <>\n" " field_c: \"OK\",\n" - " msg_field: <field_d: 123>\n" + " msg_field: < field_d: 123 >\n" " field_e: OK\n" - " msg_field: <field_d: 12>\n" + " msg_field: < field_d: 12 >\n" "};"); verifyFormat("option (MyProto.options) = <\n" @@ -247,7 +259,7 @@ TEST_F(FormatTestProto, FormatsOptions) { verifyFormat("option (MyProto.options) = <\n" " field_a: \"OK\"\n" - " msg_field: {field_b: OK}\n" + " msg_field: { field_b: OK }\n" " field_g: OK\n" " field_g: OK\n" " field_g: OK\n" @@ -350,7 +362,7 @@ TEST_F(FormatTestProto, FormatsOptions) { " field_D: 4\n" " field_E: 5\n" " >\n" - " msg_field <field_A: 1 field_B: 2 field_C: 3 field_D: 4>\n" + " msg_field < field_A: 1 field_B: 2 field_C: 3 f_D: 4 >\n" " field_e: OK\n" " field_f: OK\n" " }\n" @@ -358,21 +370,21 @@ TEST_F(FormatTestProto, FormatsOptions) { ">;"); verifyFormat("option (MyProto.options) = <\n" - " data1 <key1: value1>\n" - " data2 {key2: value2}\n" + " data1 < key1: value1 >\n" + " data2 { key2: value2 }\n" ">;"); verifyFormat("option (MyProto.options) = <\n" " app_id: 'com.javax.swing.salsa.latino'\n" " head_id: 1\n" - " data <key: value>\n" + " data < key: value >\n" ">;"); verifyFormat("option (MyProto.options) = {\n" " app_id: 'com.javax.swing.salsa.latino'\n" " head_id: 1\n" " headheadheadheadheadhead_id: 1\n" - " product_data {product {1}}\n" + " product_data { product { 1 } }\n" "};"); } @@ -410,5 +422,236 @@ TEST_F(FormatTestProto, FormatsImports) { "}"); } +TEST_F(FormatTestProto, KeepsLongStringLiteralsOnSameLine) { + verifyFormat( + "option (MyProto.options) = {\n" + " foo: {\n" + " text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaa\"\n" + " }\n" + "}"); +} + +TEST_F(FormatTestProto, FormatsOptionsExtensions) { + verifyFormat("option (MyProto.options) = {\n" + " msg_field: { field_d: 123 }\n" + " [ext.t/u] { key: value }\n" + " key: value\n" + " [t.u/v] <\n" + " [ext] { key: value }\n" + " >\n" + "};"); +} + +TEST_F(FormatTestProto, SpacesAroundPercents) { + verifyFormat("option (MyProto.options) = {\n" + " key: %lld\n" + " key: 0x%04x\n" + " key: \"%d %d\"\n" + "};"); +} + +TEST_F(FormatTestProto, FormatsRepeatedListInitializersInOptions) { + verifyFormat("option (MyProto.options) = {\n" + " key: item\n" + " keys: [\n" + " 'ala',\n" + " 'bala',\n" + " 'porto',\n" + " 'kala',\n" + " 'too',\n" + " 'long',\n" + " 'long',\n" + " 'long'\n" + " ]\n" + " key: [ item ]\n" + " msg {\n" + " key: item\n" + " keys: [\n" + " 'ala',\n" + " 'bala',\n" + " 'porto',\n" + " 'kala',\n" + " 'too',\n" + " 'long',\n" + " 'long'\n" + " ]\n" + " }\n" + " key: value\n" + "};"); +} + +TEST_F(FormatTestProto, AcceptsOperatorAsKeyInOptions) { + verifyFormat("option (MyProto.options) = {\n" + " bbbbbbbbb: <\n" + " ccccccccccccccccccccccc: <\n" + " operator: 1\n" + " operator: 2\n" + " operator: 3\n" + " operator { key: value }\n" + " >\n" + " >\n" + "};"); +} + +TEST_F(FormatTestProto, BreaksEntriesOfSubmessagesContainingSubmessages) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; + // The column limit allows for the keys submessage to be put on 1 line, but we + // break it since it contains a submessage an another entry. + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub <>\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub {}\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub {}\n" + " sub: <>\n" + " sub: []\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub { msg: 1 }\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: { msg: 1 }\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub < msg: 1 >\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ msg: 1 ]\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: <\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ 1, 2 ]\n" + " >\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub {}\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: []\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub <>\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub { key: value }\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: data\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: data\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " sub: {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + " }\n" + "}"); +} + +TEST_F(FormatTestProto, PreventBreaksBetweenKeyAndSubmessages) { + verifyFormat("option (MyProto.options) = {\n" + " submessage: {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " submessage {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " submessage: <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " >\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " submessage <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " >\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " repeatedd: [\n" + " 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " ]\n" + "}"); +} + + } // end namespace tooling } // end namespace clang diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp index 6e7b7065875d9..307394341d74f 100644 --- a/unittests/Format/FormatTestRawStrings.cpp +++ b/unittests/Format/FormatTestRawStrings.cpp @@ -33,8 +33,8 @@ protected: std::string format(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), StatusCheck CheckComplete = SC_ExpectComplete) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -47,7 +47,7 @@ protected: ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -65,23 +65,43 @@ protected: FormatStyle getRawStringPbStyleWithColumns(unsigned ColumnLimit) { FormatStyle Style = getLLVMStyle(); Style.ColumnLimit = ColumnLimit; - Style.RawStringFormats = {{/*Delimiter=*/"pb", - /*Kind=*/FormatStyle::LK_TextProto, - /*BasedOnStyle=*/"google"}}; + Style.RawStringFormats = { + { + /*Language=*/FormatStyle::LK_TextProto, + /*Delimiters=*/{"pb"}, + /*EnclosingFunctions=*/{}, + /*CanonicalDelimiter=*/"", + /*BasedOnStyle=*/"google", + }, + }; return Style; } FormatStyle getRawStringLLVMCppStyleBasedOn(std::string BasedOnStyle) { FormatStyle Style = getLLVMStyle(); - Style.RawStringFormats = {{/*Delimiter=*/"cpp", - /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}}; + Style.RawStringFormats = { + { + /*Language=*/FormatStyle::LK_Cpp, + /*Delimiters=*/{"cpp"}, + /*EnclosingFunctions=*/{}, + /*CanonicalDelimiter=*/"", + BasedOnStyle, + }, + }; return Style; } FormatStyle getRawStringGoogleCppStyleBasedOn(std::string BasedOnStyle) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); - Style.RawStringFormats = {{/*Delimiter=*/"cpp", - /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}}; + Style.RawStringFormats = { + { + /*Language=*/FormatStyle::LK_Cpp, + /*Delimiters=*/{"cpp"}, + /*EnclosingFunctions=*/{}, + /*CanonicalDelimiter=*/"", + BasedOnStyle, + }, + }; return Style; } @@ -112,6 +132,27 @@ TEST_F(FormatTestRawStrings, ReformatsAccordingToBaseStyle) { getRawStringGoogleCppStyleBasedOn("llvm"))); } +TEST_F(FormatTestRawStrings, UsesConfigurationOverBaseStyle) { + // llvm style puts '*' on the right. + // google style puts '*' on the left. + + // Uses the configured google style inside raw strings even if BasedOnStyle in + // the raw string format is llvm. + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); + EXPECT_EQ(0, parseConfiguration("---\n" + "Language: Cpp\n" + "BasedOnStyle: Google", &Style).value()); + Style.RawStringFormats = {{ + FormatStyle::LK_Cpp, + {"cpp"}, + {}, + /*CanonicalDelimiter=*/"", + /*BasedOnStyle=*/"llvm", + }}; + expect_eq(R"test(int* i = R"cpp(int* j = 0;)cpp";)test", + format(R"test(int * i = R"cpp(int * j = 0;)cpp";)test", Style)); +} + TEST_F(FormatTestRawStrings, MatchesDelimitersCaseSensitively) { // Don't touch the 'PB' raw string, format the 'pb' raw string. expect_eq(R"test( @@ -121,29 +162,20 @@ t = R"pb(item: 1)pb";)test", s = R"PB(item:1)PB"; t = R"pb(item:1)pb";)test", getRawStringPbStyleWithColumns(40))); +} - FormatStyle MixedStyle = getLLVMStyle(); - MixedStyle.RawStringFormats = { - {/*Delimiter=*/"cpp", /*Kind=*/FormatStyle::LK_Cpp, - /*BasedOnStyle=*/"llvm"}, - {/*Delimiter=*/"CPP", /*Kind=*/FormatStyle::LK_Cpp, - /*BasedOnStyle=*/"google"}}; - - // Format the 'cpp' raw string with '*' on the right. - // Format the 'CPP' raw string with '*' on the left. - // Do not format the 'Cpp' raw string. - // Do not format non-raw strings. - expect_eq(R"test( -a = R"cpp(int *i = 0;)cpp"; -b = R"CPP(int* j = 0;)CPP"; -c = R"Cpp(int * k = 0;)Cpp"; -d = R"cpp(int * k = 0;)Cpp";)test", - format(R"test( -a = R"cpp(int * i = 0;)cpp"; -b = R"CPP(int * j = 0;)CPP"; -c = R"Cpp(int * k = 0;)Cpp"; -d = R"cpp(int * k = 0;)Cpp";)test", - MixedStyle)); +TEST_F(FormatTestRawStrings, RespectsClangFormatOff) { + expect_eq(R"test( +// clang-format off +s = R"pb(item: 1)pb"; +// clang-format on +t = R"pb(item: 1)pb";)test", + format(R"test( +// clang-format off +s = R"pb(item: 1)pb"; +// clang-format on +t = R"pb(item: 1)pb";)test", + getRawStringPbStyleWithColumns(40))); } TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) { @@ -167,12 +199,6 @@ TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) { format( R"test(P p = TP(R"pb(item_1:1 item_2:2)pb");)test", getRawStringPbStyleWithColumns(40))); - expect_eq( - R"test(P p = TP(R"pb(item_1 <1> item_2: {2})pb");)test", - format( - R"test(P p = TP(R"pb(item_1<1> item_2:{2})pb");)test", - getRawStringPbStyleWithColumns(40))); - // Merge two short lines into one. expect_eq(R"test( std::string s = R"pb( @@ -188,6 +214,18 @@ std::string s = R"pb( getRawStringPbStyleWithColumns(40))); } +TEST_F(FormatTestRawStrings, BreaksShortRawStringsWhenNeeded) { + // The raw string contains multiple submessage entries, so break for + // readability. + expect_eq(R"test( +P p = TP(R"pb(item_1 < 1 > + item_2: { 2 })pb");)test", + format( + R"test( +P p = TP(R"pb(item_1<1> item_2:{2})pb");)test", + getRawStringPbStyleWithColumns(40))); +} + TEST_F(FormatTestRawStrings, BreaksRawStringsExceedingColumnLimit) { expect_eq(R"test( P p = TPPPPPPPPPPPPPPP( @@ -207,8 +245,8 @@ P p = TPPPPPPPPPPPPPPP(R"pb(item_1: 1, item_2: 2, item_3: 3)pb");)test", getRawStringPbStyleWithColumns(40))); expect_eq(R"test( -P p = TP(R"pb(item_1 <1> - item_2: <2> +P p = TP(R"pb(item_1 < 1 > + item_2: < 2 > item_3 {})pb");)test", format(R"test( P p = TP(R"pb(item_1<1> item_2:<2> item_3{ })pb");)test", @@ -227,10 +265,10 @@ P p = TP(R"pb(item_1: 1, item_2: 2, item_3: 3, item_4: 4)pb");)test", expect_eq(R"test( P p = TPPPPPPPPPPPPPPP( - R"pb(item_1 <1>, - item_2: {2}, - item_3: <3>, - item_4: {4})pb");)test", + R"pb(item_1 < 1 >, + item_2: { 2 }, + item_3: < 3 >, + item_4: { 4 })pb");)test", format(R"test( P p = TPPPPPPPPPPPPPPP(R"pb(item_1<1>, item_2: {2}, item_3: <3>, item_4:{4})pb");)test", getRawStringPbStyleWithColumns(40))); @@ -277,7 +315,7 @@ int f(string s) { TEST_F(FormatTestRawStrings, FormatsRawStringArguments) { expect_eq(R"test( -P p = TP(R"pb(key {1})pb", param_2);)test", +P p = TP(R"pb(key { 1 })pb", param_2);)test", format(R"test( P p = TP(R"pb(key{1})pb",param_2);)test", getRawStringPbStyleWithColumns(40))); @@ -290,9 +328,9 @@ PPPPPPPPPPPPP(R"pb(keykeyk)pb", param_2);)test", getRawStringPbStyleWithColumns(40))); expect_eq(R"test( -P p = - TP(R"pb(item: {i: 1, s: 's'} - item: {i: 2, s: 't'})pb");)test", +P p = TP( + R"pb(item: { i: 1, s: 's' } + item: { i: 2, s: 't' })pb");)test", format(R"test( P p = TP(R"pb(item: {i: 1, s: 's'} item: {i: 2, s: 't'})pb");)test", getRawStringPbStyleWithColumns(40))); @@ -663,15 +701,14 @@ int s() { })test", getRawStringPbStyleWithColumns(20))); - // Align the suffix with the surrounding FirstIndent if the prefix is not on + // Align the suffix with the surrounding indent if the prefix is not on // a line of its own. expect_eq(R"test( int s() { - auto S = PTP( - R"pb( - item_1: 1, - item_2: 2 - )pb"); + auto S = PTP(R"pb( + item_1: 1, + item_2: 2 + )pb"); })test", format(R"test( int s() { @@ -728,6 +765,130 @@ TEST_F(FormatTestRawStrings, DontFormatNonRawStrings) { getRawStringPbStyleWithColumns(20))); } +TEST_F(FormatTestRawStrings, FormatsRawStringsWithEnclosingFunctionName) { + FormatStyle Style = getRawStringPbStyleWithColumns(40); + Style.RawStringFormats[0].EnclosingFunctions.push_back( + "PARSE_TEXT_PROTO"); + Style.RawStringFormats[0].EnclosingFunctions.push_back("ParseTextProto"); + expect_eq(R"test(a = PARSE_TEXT_PROTO(R"(key: value)");)test", + format(R"test(a = PARSE_TEXT_PROTO(R"(key:value)");)test", Style)); + + expect_eq(R"test( +a = PARSE_TEXT_PROTO /**/ ( + /**/ R"(key: value)");)test", + format(R"test( +a = PARSE_TEXT_PROTO/**/(/**/R"(key:value)");)test", + Style)); + + expect_eq(R"test( +a = ParseTextProto<ProtoType>( + R"(key: value)");)test", + format(R"test( +a = ParseTextProto<ProtoType>(R"(key:value)");)test", + Style)); +} + +TEST_F(FormatTestRawStrings, UpdatesToCanonicalDelimiters) { + FormatStyle Style = getRawStringPbStyleWithColumns(25); + Style.RawStringFormats[0].CanonicalDelimiter = "proto"; + expect_eq(R"test(a = R"proto(key: value)proto";)test", + format(R"test(a = R"pb(key:value)pb";)test", Style)); + + // Don't update to canonical delimiter if it occurs as a raw string suffix in + // the raw string content. + expect_eq(R"test(a = R"pb(key: ")proto")pb";)test", + format(R"test(a = R"pb(key:")proto")pb";)test", Style)); +} + +TEST_F(FormatTestRawStrings, PenalizesPrefixExcessChars) { + FormatStyle Style = getRawStringPbStyleWithColumns(60); + + // The '(' in R"pb is at column 60, no break. + expect_eq(R"test( +xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb( + Category: aaaaaaaaaaaaaaaaaaaaaaaaaa +)pb")); +)test", + format(R"test( +xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrr(PARSE_TEXT_PROTO(R"pb( + Category: aaaaaaaaaaaaaaaaaaaaaaaaaa +)pb")); +)test", Style)); + // The '(' in R"pb is at column 61, break. + expect_eq(R"test( +xxxxxxxaaaaax wwwwwww = + _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb( + Category: aaaaaaaaaaaaaaaaaaaaaaaaaa + )pb")); +)test", + format(R"test( +xxxxxxxaaaaax wwwwwww = _Verxrrrrrrrrr(PARSE_TEXT_PROTO(R"pb( + Category: aaaaaaaaaaaaaaaaaaaaaaaaaa +)pb")); +)test", Style)); +} + +TEST_F(FormatTestRawStrings, KeepsRBraceFolloedByMoreLBracesOnSameLine) { + FormatStyle Style = getRawStringPbStyleWithColumns(80); + + expect_eq( + R"test( +int f() { + if (1) { + TTTTTTTTTTTTTTTTTTTTT s = PARSE_TEXT_PROTO(R"pb( + ttttttttt { + ppppppppppppp { + [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_1: "123_1" } + [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_2: "123_2" } + } + } + )pb"); + } +} +)test", + format( + R"test( +int f() { + if (1) { + TTTTTTTTTTTTTTTTTTTTT s = PARSE_TEXT_PROTO(R"pb( + ttttttttt { + ppppppppppppp { + [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_1: "123_1" } + [cccccccccc.pppppppppppppp.TTTTTTTTTTTTTTTTTTTT] { field_2: "123_2" }}} + )pb"); + } +} +)test", + Style)); +} + +TEST_F(FormatTestRawStrings, + DoNotFormatUnrecognizedDelimitersInRecognizedFunctions) { + FormatStyle Style = getRawStringPbStyleWithColumns(60); + Style.RawStringFormats[0].EnclosingFunctions.push_back( + "EqualsProto"); + // EqualsProto is a recognized function, but the Raw delimiter is + // unrecognized. Do not touch the string in this case, since it might be + // special. + expect_eq(R"test( +void f() { + aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw( +item { + key: value +} +)Raw")); +})test", + format(R"test( +void f() { + aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw( +item { + key: value +} +)Raw")); +})test", + Style)); +} + } // end namespace } // end namespace format } // end namespace clang diff --git a/unittests/Format/FormatTestSelective.cpp b/unittests/Format/FormatTestSelective.cpp index 182218fe96dbe..36d9089c60569 100644 --- a/unittests/Format/FormatTestSelective.cpp +++ b/unittests/Format/FormatTestSelective.cpp @@ -21,8 +21,8 @@ namespace { class FormatTestSelective : public ::testing::Test { protected: std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); FormattingAttemptStatus Status; tooling::Replacements Replaces = @@ -30,7 +30,7 @@ protected: EXPECT_TRUE(Status.FormatComplete) << Code << "\n\n"; auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } @@ -177,6 +177,72 @@ TEST_F(FormatTestSelective, FormatsCommentsLocally) { 0, 0)); } +TEST_F(FormatTestSelective, ContinueReindenting) { + // When we change an indent, we continue formatting as long as following + // lines are not indented correctly. + EXPECT_EQ("int i;\n" + "int b;\n" + "int c;\n" + "int d;\n" + "int e;\n" + " int f;\n", + format("int i;\n" + " int b;\n" + " int c;\n" + " int d;\n" + "int e;\n" + " int f;\n", + 11, 0)); +} + +TEST_F(FormatTestSelective, ReindentClosingBrace) { + EXPECT_EQ("int i;\n" + "int f() {\n" + " int a;\n" + " int b;\n" + "}\n" + " int c;\n", + format("int i;\n" + " int f(){\n" + "int a;\n" + "int b;\n" + " }\n" + " int c;\n", + 11, 0)); + EXPECT_EQ("void f() {\n" + " if (foo) {\n" + " b();\n" + " } else {\n" + " c();\n" + " }\n" + "int d;\n" + "}\n", + format("void f() {\n" + " if (foo) {\n" + "b();\n" + "}else{\n" + "c();\n" + "}\n" + "int d;\n" + "}\n", + 13, 0)); + EXPECT_EQ("int i = []() {\n" + " class C {\n" + " int a;\n" + " int b;\n" + " };\n" + " int c;\n" + "};\n", + format("int i = []() {\n" + " class C{\n" + "int a;\n" + "int b;\n" + "};\n" + "int c;\n" + " };\n", + 17, 0)); +} + TEST_F(FormatTestSelective, IndividualStatementsOfNestedBlocks) { EXPECT_EQ("DEBUG({\n" " int i;\n" @@ -503,7 +569,7 @@ TEST_F(FormatTestSelective, StopFormattingWhenLeavingScope) { " if (a) {\n" " g();\n" " h();\n" - "}\n" + " }\n" "\n" "void g() {\n" "}", diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index 0a7bcdd823623..0875bd8925d12 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -21,24 +21,29 @@ class FormatTestTextProto : public ::testing::Test { protected: static std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length, const FormatStyle &Style) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); tooling::Replacements Replaces = reformat(Style, Code, Ranges); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } - static std::string format(llvm::StringRef Code) { - FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); - Style.ColumnLimit = 60; // To make writing tests easier. + static std::string format(llvm::StringRef Code, const FormatStyle &Style) { return format(Code, 0, Code.size(), Style); } + static void verifyFormat(llvm::StringRef Code, const FormatStyle &Style) { + EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable"; + EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); + } + static void verifyFormat(llvm::StringRef Code) { - EXPECT_EQ(Code.str(), format(test::messUp(Code))); + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; // To make writing tests easier. + verifyFormat(Code, Style); } }; @@ -49,9 +54,9 @@ TEST_F(FormatTestTextProto, KeepsTopLevelEntriesFittingALine) { TEST_F(FormatTestTextProto, SupportsMessageFields) { verifyFormat("msg_field: {}"); - verifyFormat("msg_field: {field_a: A}"); + verifyFormat("msg_field: { field_a: A }"); - verifyFormat("msg_field: {field_a: \"OK\" field_b: 123}"); + verifyFormat("msg_field: { field_a: \"OK\" field_b: 123 }"); verifyFormat("msg_field: {\n" " field_a: 1\n" @@ -63,9 +68,9 @@ TEST_F(FormatTestTextProto, SupportsMessageFields) { verifyFormat("msg_field {}"); - verifyFormat("msg_field {field_a: A}"); + verifyFormat("msg_field { field_a: A }"); - verifyFormat("msg_field {field_a: \"OK\" field_b: 123}"); + verifyFormat("msg_field { field_a: \"OK\" field_b: 123 }"); verifyFormat("msg_field {\n" " field_a: 1\n" @@ -78,11 +83,11 @@ TEST_F(FormatTestTextProto, SupportsMessageFields) { " field_h: 1234.567e-89\n" "}"); - verifyFormat("msg_field: {msg_field {field_a: 1}}"); + verifyFormat("msg_field: { msg_field { field_a: 1 } }"); verifyFormat("id: \"ala.bala\"\n" - "item {type: ITEM_A rank: 1 score: 90.0}\n" - "item {type: ITEM_B rank: 2 score: 70.5}\n" + "item { type: ITEM_A rank: 1 score: 90.0 }\n" + "item { type: ITEM_B rank: 2 score: 70.5 }\n" "item {\n" " type: ITEM_A\n" " rank: 3\n" @@ -102,24 +107,24 @@ TEST_F(FormatTestTextProto, AvoidsTopLevelBinPacking) { verifyFormat("field_a: OK\n" "field_b: \"OK\"\n" "field_c: \"OK\"\n" - "msg_field: {field_d: 123}\n" + "msg_field: { field_d: 123 }\n" "field_e: OK\n" "field_f: OK"); verifyFormat("field_a: OK\n" "field_b: \"OK\"\n" "field_c: \"OK\"\n" - "msg_field: {field_d: 123 field_e: OK}"); + "msg_field: { field_d: 123 field_e: OK }"); verifyFormat("a: {\n" " field_a: OK\n" - " field_b {field_c: OK}\n" + " field_b { field_c: OK }\n" " field_d: OKOKOK\n" " field_e: OK\n" "}"); verifyFormat("field_a: OK,\n" - "field_b {field_c: OK},\n" + "field_b { field_c: OK },\n" "field_d: OKOKOK,\n" "field_e: OK"); } @@ -139,29 +144,77 @@ TEST_F(FormatTestTextProto, AddsNewlinesAfterTrailingComments) { "}"); } +TEST_F(FormatTestTextProto, ImplicitStringLiteralConcatenation) { + verifyFormat("field_a: 'aaaaa'\n" + " 'bbbbb'"); + verifyFormat("field_a: \"aaaaa\"\n" + " \"bbbbb\""); + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.AlwaysBreakBeforeMultilineStrings = true; + verifyFormat("field_a:\n" + " 'aaaaa'\n" + " 'bbbbb'", + Style); + verifyFormat("field_a:\n" + " \"aaaaa\"\n" + " \"bbbbb\"", + Style); +} + TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { // Single-line tests verifyFormat("msg_field <>"); verifyFormat("msg_field: <>"); - verifyFormat("msg_field <field_a: OK>"); - verifyFormat("msg_field: <field_a: 123>"); - verifyFormat("msg_field <field_a <>>"); - verifyFormat("msg_field <field_a <field_b <>>>"); - verifyFormat("msg_field: <field_a <field_b: <>>>"); - verifyFormat("msg_field <field_a: OK, field_b: \"OK\">"); - verifyFormat("msg_field <field_a: OK field_b: <>, field_c: OK>"); - verifyFormat("msg_field <field_a {field_b: 1}, field_c: <field_d: 2>>"); - verifyFormat("msg_field: <field_a: OK, field_b: \"OK\">"); - verifyFormat("msg_field: <field_a: OK field_b: <>, field_c: OK>"); - verifyFormat("msg_field: <field_a {field_b: 1}, field_c: <field_d: 2>>"); - verifyFormat("field_a: \"OK\", msg_field: <field_b: 123>, field_c: {}"); - verifyFormat("field_a <field_b: 1>, msg_field: <field_b: 123>, field_c <>"); - verifyFormat("field_a <field_b: 1> msg_field: <field_b: 123> field_c <>"); - verifyFormat("field <field <field: <>>, field <>> field: <field: 1>"); - + verifyFormat("msg_field < field_a: OK >"); + verifyFormat("msg_field: < field_a: 123 >"); + verifyFormat("msg_field < field_a <> >"); + verifyFormat("msg_field < field_a < field_b <> > >"); + verifyFormat("msg_field: < field_a < field_b: <> > >"); + verifyFormat("msg_field < field_a: OK, field_b: \"OK\" >"); + verifyFormat("msg_field: < field_a: OK, field_b: \"OK\" >"); // Multiple lines tests verifyFormat("msg_field <\n" " field_a: OK\n" + " field_b: <>,\n" + " field_c: OK\n" + ">"); + + verifyFormat("msg_field <\n" + " field_a { field_b: 1 },\n" + " field_c: < f_d: 2 >\n" + ">"); + + verifyFormat("msg_field: <\n" + " field_a: OK\n" + " field_b: <>,\n" + " field_c: OK\n" + ">"); + + verifyFormat("msg_field: <\n" + " field_a { field_b: 1 },\n" + " field_c: < fd_d: 2 >\n" + ">"); + + verifyFormat("field_a: \"OK\",\n" + "msg_field: < field_b: 123 >,\n" + "field_c: {}"); + + verifyFormat("field_a < field_b: 1 >,\n" + "msg_fid: < fiel_b: 123 >,\n" + "field_c <>"); + + verifyFormat("field_a < field_b: 1 >\n" + "msg_fied: < field_b: 123 >\n" + "field_c <>"); + + verifyFormat("field <\n" + " field < field: <> >,\n" + " field <>\n" + ">\n" + "field: < field: 1 >"); + + verifyFormat("msg_field <\n" + " field_a: OK\n" " field_b: \"OK\"\n" " field_c: 1\n" " field_d: 12.5\n" @@ -170,37 +223,37 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { verifyFormat("msg_field: <>\n" "field_c: \"OK\",\n" - "msg_field: <field_d: 123>\n" + "msg_field: < field_d: 123 >\n" "field_e: OK\n" - "msg_field: <field_d: 12>"); + "msg_field: < field_d: 12 >"); verifyFormat("field_a: OK,\n" - "field_b <field_c: OK>,\n" - "field_d: <12.5>,\n" + "field_b < field_c: OK >,\n" + "field_d: < 12.5 >,\n" "field_e: OK"); verifyFormat("field_a: OK\n" - "field_b <field_c: OK>\n" - "field_d: <12.5>\n" + "field_b < field_c: OK >\n" + "field_d: < 12.5 >\n" "field_e: OKOKOK"); verifyFormat("msg_field <\n" " field_a: OK,\n" - " field_b <field_c: OK>,\n" - " field_d: <12.5>,\n" + " field_b < field_c: OK >,\n" + " field_d: < 12.5 >,\n" " field_e: OK\n" ">"); verifyFormat("msg_field <\n" - " field_a: <field: OK>,\n" - " field_b <field_c: OK>,\n" - " field_d: <12.5>,\n" + " field_a: < field: OK >,\n" + " field_b < field_c: OK >,\n" + " field_d: < 12.5 >,\n" " field_e: OK,\n" ">"); verifyFormat("msg_field: <\n" " field_a: \"OK\"\n" - " msg_field: {field_b: OK}\n" + " msg_field: { field_b: OK }\n" " field_g: OK\n" " field_g: OK\n" " field_g: OK\n" @@ -208,87 +261,479 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { verifyFormat("field_a {\n" " field_d: ok\n" - " field_b: <field_c: 1>\n" + " field_b: < field_c: 1 >\n" " field_d: ok\n" " field_d: ok\n" "}"); verifyFormat("field_a: {\n" " field_d: ok\n" - " field_b: <field_c: 1>\n" + " field_b: < field_c: 1 >\n" " field_d: ok\n" " field_d: ok\n" "}"); - verifyFormat("field_a: <f1: 1, f2: <>>\n" + verifyFormat("field_a: <\n" + " f1: 1,\n" + " f2: <>\n" + ">\n" "field_b <\n" " field_b1: <>\n" " field_b2: ok,\n" " field_b3: <\n" " field_x {} // Comment\n" - " field_y: {field_z: 1}\n" + " field_y: { field_z: 1 }\n" " field_w: ok\n" " >\n" " field {\n" " field_x <> // Comment\n" - " field_y: <field_z: 1>\n" + " field_y: < field_z: 1 >\n" " field_w: ok\n" " msg_field: <\n" " field: <>\n" - " field: <field: 1>\n" - " field: <field: 2>\n" - " field: <field: 3>\n" - " field: <field: 4>\n" + " field: < field: 1 >\n" + " field: < field: 2 >\n" + " field: < field: 3 >\n" + " field: < field: 4 >\n" " field: ok\n" " >\n" " }\n" ">\n" "field: OK,\n" - "field_c <field <field <>>>"); + "field_c < field < field <> > >"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "head_id: 1\n" - "data <key: value>"); + "data < key: value >"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "head_id: 1\n" - "data <key: value>\n" + "data < key: value >\n" "tail_id: 2"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "head_id: 1\n" - "data <key: value>\n" - "data {key: value}"); + "data < key: value >\n" + "data { key: value }"); verifyFormat("app {\n" " app_id: 'com.javax.swing.salsa.latino'\n" " head_id: 1\n" - " data <key: value>\n" + " data < key: value >\n" "}"); verifyFormat("app: {\n" " app_id: 'com.javax.swing.salsa.latino'\n" " head_id: 1\n" - " data <key: value>\n" + " data < key: value >\n" "}"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "headheadheadheadheadhead_id: 1\n" - "product_data {product {1}}"); + "product_data { product { 1 } }"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "headheadheadheadheadhead_id: 1\n" - "product_data <product {1}>"); + "product_data < product { 1 } >"); verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n" "headheadheadheadheadhead_id: 1\n" - "product_data <product <1>>"); + "product_data < product < 1 > >"); verifyFormat("app <\n" " app_id: 'com.javax.swing.salsa.latino'\n" " headheadheadheadheadhead_id: 1\n" - " product_data <product {1}>\n" + " product_data < product { 1 } >\n" ">"); + + verifyFormat("dcccwrnfioeruvginerurneitinfo {\n" + " exte3nsionrnfvui { key: value }\n" + "}"); +} + +TEST_F(FormatTestTextProto, DiscardsUnbreakableTailIfCanBreakAfter) { + // The two closing braces count towards the string UnbreakableTailLength, but + // since we have broken after the corresponding opening braces, we don't + // consider that length for string breaking. + verifyFormat( + "foo: {\n" + " bar: {\n" + " text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n" + " }\n" + "}"); +} + +TEST_F(FormatTestTextProto, KeepsLongStringLiteralsOnSameLine) { + verifyFormat( + "foo: {\n" + " text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaaaa\"\n" + "}"); +} + +TEST_F(FormatTestTextProto, KeepsCommentsIndentedInList) { + verifyFormat("aaaaaaaaaa: 100\n" + "bbbbbbbbbbbbbbbbbbbbbbbbbbb: 200\n" + "# Single line comment for stuff here.\n" + "cccccccccccccccccccccccc: 3849\n" + "# Multiline comment for stuff here.\n" + "# Multiline comment for stuff here.\n" + "# Multiline comment for stuff here.\n" + "cccccccccccccccccccccccc: 3849"); +} + +TEST_F(FormatTestTextProto, UnderstandsHashHashComments) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; // To make writing tests easier. + EXPECT_EQ("aaa: 100\n" + "##this is a double-hash comment.\n" + "bb: 100\n" + "## another double-hash comment.\n" + "### a triple-hash comment\n" + "cc: 200\n" + "#### a quadriple-hash comment\n" + "dd: 100\n", + format("aaa: 100\n" + "##this is a double-hash comment.\n" + "bb: 100\n" + "## another double-hash comment.\n" + "### a triple-hash comment\n" + "cc: 200\n" + "#### a quadriple-hash comment\n" + "dd: 100\n", + Style)); +} + +TEST_F(FormatTestTextProto, FormatsExtensions) { + verifyFormat("[type] { key: value }"); + verifyFormat("[type] {\n" + " keyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: value\n" + "}"); + verifyFormat("[type.type] { key: value }"); + verifyFormat("[type.type] < key: value >"); + verifyFormat("[type.type/type.type] { key: value }"); + verifyFormat("msg {\n" + " [type.type] { key: value }\n" + "}"); + verifyFormat("msg {\n" + " [type.type] {\n" + " keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n" + " }\n" + "}"); + verifyFormat("key: value\n" + "[a.b] { key: value }"); + verifyFormat("msg: <\n" + " key: value\n" + " [a.b.c/d.e]: < key: value >\n" + " [f.g]: <\n" + " key: valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n" + " key: {}\n" + " >\n" + " key {}\n" + " [h.i.j] < key: value >\n" + " [a]: {\n" + " [b.c]: {}\n" + " [d] <>\n" + " [e/f]: 1\n" + " }\n" + ">"); + verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n" + " .longg.longlong] { key: value }"); + verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n" + " .longg.longlong] {\n" + " key: value\n" + " key: value\n" + " key: value\n" + " key: value\n" + "}"); + verifyFormat("[longg.long.long.long.long.long.long.long.long.long\n" + " .long/longg.longlong] { key: value }"); + verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n" + " bbbbbbbbbbbbbb] { key: value }"); + // These go over the column limit intentionally, since the alternative + // [aa..a\n] is worse. + verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n" + " key: value\n" + "}"); + verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n" + " [type.type] {\n" + " keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n" + " }\n" + "}"); + verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n" + " bbbbbbb] {\n" + " [type.type] {\n" + " keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n" + " }\n" + "}"); + verifyFormat( + "aaaaaaaaaaaaaaa {\n" + " bbbbbb {\n" + " [a.b/cy] {\n" + " eeeeeeeeeeeee: \"The lazy coo cat jumps over the lazy hot dog\"\n" + " }\n" + " }\n" + "}"); } + +TEST_F(FormatTestTextProto, SpacesAroundPercents) { + verifyFormat("key: %d"); + verifyFormat("key: 0x%04x"); + verifyFormat("key: \"%d %d\""); +} + +TEST_F(FormatTestTextProto, FormatsRepeatedListInitializers) { + verifyFormat("keys: []"); + verifyFormat("keys: [ 1 ]"); + verifyFormat("keys: [ 'ala', 'bala' ]"); + verifyFormat("keys: [\n" + " 'ala',\n" + " 'bala',\n" + " 'porto',\n" + " 'kala',\n" + " 'too',\n" + " 'long',\n" + " 'ng'\n" + "]"); + verifyFormat("key: item\n" + "keys: [\n" + " 'ala',\n" + " 'bala',\n" + " 'porto',\n" + " 'kala',\n" + " 'too',\n" + " 'long',\n" + " 'long',\n" + " 'long'\n" + "]\n" + "key: item\n" + "msg {\n" + " key: item\n" + " keys: [\n" + " 'ala',\n" + " 'bala',\n" + " 'porto',\n" + " 'kala',\n" + " 'too',\n" + " 'long',\n" + " 'long'\n" + " ]\n" + "}\n" + "key: value" + ); + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; // To make writing tests easier. + Style.Cpp11BracedListStyle = true; + verifyFormat("keys: [1]", Style); +} + +TEST_F(FormatTestTextProto, AcceptsOperatorAsKey) { + verifyFormat("aaaaaaaaaaa: <\n" + " bbbbbbbbb: <\n" + " ccccccccccccccccccccccc: <\n" + " operator: 1\n" + " operator: 2\n" + " operator: 3\n" + " operator { key: value }\n" + " >\n" + " >\n" + ">"); +} + +TEST_F(FormatTestTextProto, BreaksConsecutiveStringLiterals) { + verifyFormat("ala: \"str1\"\n" + " \"str2\"\n"); +} + +TEST_F(FormatTestTextProto, PutsMultipleEntriesInExtensionsOnNewlines) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + verifyFormat("pppppppppp: {\n" + " ssssss: \"http://example.com/blahblahblah\"\n" + " ppppppp: \"sssss/MMMMMMMMMMMM\"\n" + " [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] { begin: 24 end: 252 }\n" + " [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] {\n" + " begin: 24\n" + " end: 252\n" + " key: value\n" + " key: value\n" + " }\n" + "}", Style); +} + +TEST_F(FormatTestTextProto, BreaksAfterBraceFollowedByClosingBraceOnNextLine) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; + verifyFormat("keys: [\n" + " data: { item: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }\n" + "]"); + verifyFormat("keys: <\n" + " data: { item: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }\n" + ">"); +} + +TEST_F(FormatTestTextProto, BreaksEntriesOfSubmessagesContainingSubmessages) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; + // The column limit allows for the keys submessage to be put on 1 line, but we + // break it since it contains a submessage an another entry. + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub <>\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub {}\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub {}\n" + " sub: <>\n" + " sub: []\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub { msg: 1 }\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: { msg: 1 }\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub < msg: 1 >\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ msg: 1 ]\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: <\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ 1, 2 ]\n" + ">"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub {}\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub: []\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub <>\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub { key: value }\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: data\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: data\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("sub: {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("sub: {\n" + " key: 1\n" + " sub: {}\n" + "}\n" + "# comment\n"); + verifyFormat("sub: {\n" + " key: 1\n" + " # comment\n" + " sub: {}\n" + "}"); +} + +TEST_F(FormatTestTextProto, PreventBreaksBetweenKeyAndSubmessages) { + verifyFormat("submessage: {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("submessage {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("submessage: <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + ">"); + verifyFormat("submessage <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + ">"); + verifyFormat("repeatedd: [\n" + " 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + "]"); + // "{" is going over the column limit. + verifyFormat( + "submessageeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee: {\n" + " key: 'aaaaa'\n" + "}"); +} + +TEST_F(FormatTestTextProto, FormatsCommentsAtEndOfFile) { + verifyFormat("key: value\n" + "# endfile comment"); + verifyFormat("key: value\n" + "// endfile comment"); + verifyFormat("key: value\n" + "// endfile comment 1\n" + "// endfile comment 2"); + verifyFormat("submessage { key: value }\n" + "# endfile comment"); + verifyFormat("submessage <\n" + " key: value\n" + " item {}\n" + ">\n" + "# endfile comment"); +} + +TEST_F(FormatTestTextProto, KeepsAmpersandsNextToKeys) { + verifyFormat("@tmpl { field: 1 }"); + verifyFormat("@placeholder: 1"); + verifyFormat("@name <>"); + verifyFormat("submessage: @base { key: value }"); + verifyFormat("submessage: @base {\n" + " key: value\n" + " item: {}\n" + "}"); + verifyFormat("submessage: {\n" + " msg: @base {\n" + " yolo: {}\n" + " key: value\n" + " }\n" + " key: value\n" + "}"); +} + } // end namespace tooling } // end namespace clang diff --git a/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/unittests/Format/NamespaceEndCommentsFixerTest.cpp index fda8b4d69fe09..ee083b8ad14cf 100644 --- a/unittests/Format/NamespaceEndCommentsFixerTest.cpp +++ b/unittests/Format/NamespaceEndCommentsFixerTest.cpp @@ -25,13 +25,13 @@ protected: fixNamespaceEndComments(llvm::StringRef Code, const std::vector<tooling::Range> &Ranges, const FormatStyle &Style = getLLVMStyle()) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); tooling::Replacements Replaces = clang::format::fixNamespaceEndComments(Style, Code, Ranges, "<stdin>"); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } diff --git a/unittests/Format/SortIncludesTest.cpp b/unittests/Format/SortIncludesTest.cpp index 09fc0703d42eb..dde88003784c0 100644 --- a/unittests/Format/SortIncludesTest.cpp +++ b/unittests/Format/SortIncludesTest.cpp @@ -26,12 +26,12 @@ protected: std::string sort(StringRef Code, std::vector<tooling::Range> Ranges, StringRef FileName = "input.cc") { - auto Replaces = sortIncludes(Style, Code, Ranges, FileName); + auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName); Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); auto Sorted = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Sorted)); auto Result = applyAllReplacements( - *Sorted, reformat(Style, *Sorted, Ranges, FileName)); + *Sorted, reformat(FmtStyle, *Sorted, Ranges, FileName)); EXPECT_TRUE(static_cast<bool>(Result)); return *Result; } @@ -41,12 +41,12 @@ protected: } unsigned newCursor(llvm::StringRef Code, unsigned Cursor) { - sortIncludes(Style, Code, GetCodeRange(Code), "input.cpp", &Cursor); + sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.cpp", &Cursor); return Cursor; } - FormatStyle Style = getLLVMStyle(); - + FormatStyle FmtStyle = getLLVMStyle(); + tooling::IncludeStyle &Style = FmtStyle.IncludeStyle; }; TEST_F(SortIncludesTest, BasicSorting) { @@ -74,11 +74,11 @@ TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) { "#include <d>\n" "#include <e>\n" "#include <f>\n"; - EXPECT_TRUE(sortIncludes(Style, Code, GetCodeRange(Code), "a.cc").empty()); + EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty()); } TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { - Style.IncludeBlocks = FormatStyle::IBS_Merge; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; EXPECT_EQ("#include \"a.h\"\n" "#include \"b.h\"\n" "#include \"c.h\"\n", @@ -88,7 +88,7 @@ TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { "\n" "#include \"b.h\"\n")); - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include \"a.h\"\n" "#include \"b.h\"\n" "#include \"c.h\"\n", @@ -119,7 +119,7 @@ TEST_F(SortIncludesTest, SupportClangFormatOff) { } TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { - Style.SortIncludes = false; + FmtStyle.SortIncludes = false; EXPECT_EQ("#include \"a.h\"\n" "#include \"c.h\"\n" "#include \"b.h\"\n", @@ -182,7 +182,7 @@ TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { } TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { - Style.IncludeBlocks = FormatStyle::IBS_Merge; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; EXPECT_EQ("#include \"a.h\"\n" "#include \"b.h\"\n" "#include \"c.h\"\n", @@ -202,7 +202,7 @@ TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { "// comment\n" "#include \"b.h\"\n")); - Style.IncludeBlocks = FormatStyle::IBS_Merge; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; EXPECT_EQ("#include \"a.h\"\n" "#include \"c.h\"\n" "// comment\n" @@ -212,7 +212,7 @@ TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { "// comment\n" "#include \"b.h\"\n")); - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include \"a.h\"\n" "#include \"c.h\"\n" "// comment\n" @@ -233,7 +233,7 @@ TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { "#include \"c.h\"\n" "#include \"a.h\"\n")); - Style = getGoogleStyle(FormatStyle::LK_Cpp); + FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); EXPECT_EQ("#include <b.h>\n" "#include <d.h>\n" "#include \"a.h\"\n" @@ -245,7 +245,7 @@ TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { } TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include \"a.h\"\n" "#include \"c.h\"\n" "\n" @@ -345,7 +345,7 @@ TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; - Style.IncludeBlocks = FormatStyle::IBS_Merge; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; EXPECT_EQ("#include \"c.h\"\n" "#include \"a.h\"\n" @@ -359,7 +359,7 @@ TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include \"a.h\"\n" "\n" @@ -417,7 +417,7 @@ TEST_F(SortIncludesTest, NegativePriorities) { TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}}; - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include \"important_os_header.h\"\n" "\n" @@ -467,7 +467,7 @@ TEST_F(SortIncludesTest, DeduplicateIncludes) { "#include <b>\n" "#include <c>\n")); - Style.IncludeBlocks = FormatStyle::IBS_Merge; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; EXPECT_EQ("#include <a>\n" "#include <b>\n" "#include <c>\n", @@ -479,7 +479,7 @@ TEST_F(SortIncludesTest, DeduplicateIncludes) { "#include <b>\n" "#include <c>\n")); - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include <a>\n" "#include <b>\n" "#include <c>\n", @@ -503,7 +503,7 @@ TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { "#include <c>\n" "#include <b>\n")); - Style.IncludeBlocks = FormatStyle::IBS_Merge; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; EXPECT_EQ("#include <a>\n" "#include <b>\n" "#include <c>\n", @@ -515,7 +515,7 @@ TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { "#include <c>\n" "#include <b>\n")); - Style.IncludeBlocks = FormatStyle::IBS_Regroup; + Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include <a>\n" "#include <b>\n" "#include <c>\n", @@ -573,7 +573,7 @@ TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { "\n" " int x ;"; std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; - auto Replaces = sortIncludes(Style, Code, Ranges, "input.cpp"); + auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); EXPECT_EQ(1u, Ranges.size()); EXPECT_EQ(0u, Ranges[0].getOffset()); diff --git a/unittests/Format/UsingDeclarationsSorterTest.cpp b/unittests/Format/UsingDeclarationsSorterTest.cpp index c4d971367be9e..2ba6520e057fb 100644 --- a/unittests/Format/UsingDeclarationsSorterTest.cpp +++ b/unittests/Format/UsingDeclarationsSorterTest.cpp @@ -23,13 +23,13 @@ protected: std::string sortUsingDeclarations(llvm::StringRef Code, const std::vector<tooling::Range> &Ranges, const FormatStyle &Style = getLLVMStyle()) { - DEBUG(llvm::errs() << "---\n"); - DEBUG(llvm::errs() << Code << "\n\n"); + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); tooling::Replacements Replaces = clang::format::sortUsingDeclarations(Style, Code, Ranges, "<stdin>"); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast<bool>(Result)); - DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } |