summaryrefslogtreecommitdiff
path: root/unittests/Format
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
commit486754660bb926339aefcf012a3f848592babb8b (patch)
treeecdbc446c9876f4f120f701c243373cd3cb43db3 /unittests/Format
parent55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff)
Notes
Diffstat (limited to 'unittests/Format')
-rw-r--r--unittests/Format/CleanupTest.cpp513
-rw-r--r--unittests/Format/FormatTest.cpp683
-rw-r--r--unittests/Format/FormatTestComments.cpp22
-rw-r--r--unittests/Format/FormatTestJS.cpp32
-rw-r--r--unittests/Format/FormatTestJava.cpp8
-rw-r--r--unittests/Format/FormatTestObjC.cpp513
-rw-r--r--unittests/Format/FormatTestProto.cpp289
-rw-r--r--unittests/Format/FormatTestRawStrings.cpp269
-rw-r--r--unittests/Format/FormatTestSelective.cpp74
-rw-r--r--unittests/Format/FormatTestTextProto.cpp577
-rw-r--r--unittests/Format/NamespaceEndCommentsFixerTest.cpp6
-rw-r--r--unittests/Format/SortIncludesTest.cpp44
-rw-r--r--unittests/Format/UsingDeclarationsSorterTest.cpp6
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;
}