clang-format: better handle namespace macros
Summary:
Other macros are used to declare namespaces, and should thus be handled
similarly. This is the case for crpcut's TESTSUITE macro, or for
unittest-cpp's SUITE macro:
TESTSUITE(Foo) {
TEST(MyFirstTest) {
assert(0);
}
} // TESTSUITE(Foo)
This patch deals with this cases by introducing a new option to specify
lists of namespace macros. Internally, it re-uses the system already in
place for foreach and statement macros, to ensure there is no impact on
performance.
Reviewers: krasimir, djasper, klimek
Reviewed By: klimek
Subscribers: acoomans, cfe-commits, klimek
Tags: #clang
Differential Revision: https://reviews.llvm.org/D37813
llvm-svn: 362740
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 87405bc..885aac0 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -1870,9 +1870,117 @@
Style));
}
+TEST_F(FormatTest, NamespaceMacros) {
+ FormatStyle Style = getLLVMStyle();
+ Style.NamespaceMacros.push_back("TESTSUITE");
+
+ verifyFormat("TESTSUITE(A) {\n"
+ "int foo();\n"
+ "} // TESTSUITE(A)",
+ Style);
+
+ verifyFormat("TESTSUITE(A, B) {\n"
+ "int foo();\n"
+ "} // TESTSUITE(A)",
+ Style);
+
+ // Properly indent according to NamespaceIndentation style
+ Style.NamespaceIndentation = FormatStyle::NI_All;
+ verifyFormat("TESTSUITE(A) {\n"
+ " int foo();\n"
+ "} // TESTSUITE(A)",
+ Style);
+ verifyFormat("TESTSUITE(A) {\n"
+ " namespace B {\n"
+ " int foo();\n"
+ " } // namespace B\n"
+ "} // TESTSUITE(A)",
+ Style);
+ verifyFormat("namespace A {\n"
+ " TESTSUITE(B) {\n"
+ " int foo();\n"
+ " } // TESTSUITE(B)\n"
+ "} // namespace A",
+ Style);
+
+ Style.NamespaceIndentation = FormatStyle::NI_Inner;
+ verifyFormat("TESTSUITE(A) {\n"
+ "TESTSUITE(B) {\n"
+ " int foo();\n"
+ "} // TESTSUITE(B)\n"
+ "} // TESTSUITE(A)",
+ Style);
+ verifyFormat("TESTSUITE(A) {\n"
+ "namespace B {\n"
+ " int foo();\n"
+ "} // namespace B\n"
+ "} // TESTSUITE(A)",
+ Style);
+ verifyFormat("namespace A {\n"
+ "TESTSUITE(B) {\n"
+ " int foo();\n"
+ "} // TESTSUITE(B)\n"
+ "} // namespace A",
+ Style);
+
+ // Properly merge namespace-macros blocks in CompactNamespaces mode
+ Style.NamespaceIndentation = FormatStyle::NI_None;
+ Style.CompactNamespaces = true;
+ verifyFormat("TESTSUITE(A) { TESTSUITE(B) {\n"
+ "}} // TESTSUITE(A::B)",
+ Style);
+
+ EXPECT_EQ("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}} // TESTSUITE(out::in)",
+ format("TESTSUITE(out) {\n"
+ "TESTSUITE(in) {\n"
+ "} // TESTSUITE(in)\n"
+ "} // TESTSUITE(out)",
+ Style));
+
+ EXPECT_EQ("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}} // TESTSUITE(out::in)",
+ format("TESTSUITE(out) {\n"
+ "TESTSUITE(in) {\n"
+ "} // TESTSUITE(in)\n"
+ "} // TESTSUITE(out)",
+ Style));
+
+ // Do not merge different namespaces/macros
+ EXPECT_EQ("namespace out {\n"
+ "TESTSUITE(in) {\n"
+ "} // TESTSUITE(in)\n"
+ "} // namespace out",
+ format("namespace out {\n"
+ "TESTSUITE(in) {\n"
+ "} // TESTSUITE(in)\n"
+ "} // namespace out",
+ Style));
+ EXPECT_EQ("TESTSUITE(out) {\n"
+ "namespace in {\n"
+ "} // namespace in\n"
+ "} // TESTSUITE(out)",
+ format("TESTSUITE(out) {\n"
+ "namespace in {\n"
+ "} // namespace in\n"
+ "} // TESTSUITE(out)",
+ Style));
+ Style.NamespaceMacros.push_back("FOOBAR");
+ EXPECT_EQ("TESTSUITE(out) {\n"
+ "FOOBAR(in) {\n"
+ "} // FOOBAR(in)\n"
+ "} // TESTSUITE(out)",
+ format("TESTSUITE(out) {\n"
+ "FOOBAR(in) {\n"
+ "} // FOOBAR(in)\n"
+ "} // TESTSUITE(out)",
+ Style));
+}
+
TEST_F(FormatTest, FormatsCompactNamespaces) {
FormatStyle Style = getLLVMStyle();
Style.CompactNamespaces = true;
+ Style.NamespaceMacros.push_back("TESTSUITE");
verifyFormat("namespace A { namespace B {\n"
"}} // namespace A::B",
@@ -11700,6 +11808,12 @@
CHECK_PARSE("StatementMacros: [QUNUSED, QT_REQUIRE_VERSION]", StatementMacros,
std::vector<std::string>({"QUNUSED", "QT_REQUIRE_VERSION"}));
+ Style.NamespaceMacros.clear();
+ CHECK_PARSE("NamespaceMacros: [TESTSUITE]", NamespaceMacros,
+ std::vector<std::string>{"TESTSUITE"});
+ CHECK_PARSE("NamespaceMacros: [TESTSUITE, SUITE]", NamespaceMacros,
+ std::vector<std::string>({"TESTSUITE", "SUITE"}));
+
Style.IncludeStyle.IncludeCategories.clear();
std::vector<tooling::IncludeStyle::IncludeCategory> ExpectedCategories = {
{"abc/.*", 2}, {".*", 1}};
diff --git a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
index d4c16c8..44cb4ef6 100644
--- a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
+++ b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
@@ -52,6 +52,7 @@
"int i;\n"
"int j;\n"
"}"));
+
EXPECT_EQ("namespace {\n"
"int i;\n"
"int j;\n"
@@ -248,6 +249,85 @@
"// unrelated"));
}
+TEST_F(NamespaceEndCommentsFixerTest, AddsMacroEndComment) {
+ FormatStyle Style = getLLVMStyle();
+ Style.NamespaceMacros.push_back("TESTSUITE");
+
+ EXPECT_EQ("TESTSUITE() {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE()",
+ fixNamespaceEndComments("TESTSUITE() {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+ EXPECT_EQ("inline TESTSUITE(A) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(A)",
+ fixNamespaceEndComments("inline TESTSUITE(A) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+ EXPECT_EQ("TESTSUITE(::A) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(::A)",
+ fixNamespaceEndComments("TESTSUITE(::A) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+ EXPECT_EQ("TESTSUITE(::A::B) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(::A::B)",
+ fixNamespaceEndComments("TESTSUITE(::A::B) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+ EXPECT_EQ("TESTSUITE(/**/::/**/A/**/::/**/B/**/) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(::A::B)",
+ fixNamespaceEndComments("TESTSUITE(/**/::/**/A/**/::/**/B/**/) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+ EXPECT_EQ("TESTSUITE(A, B) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A, B) {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+ EXPECT_EQ("TESTSUITE(\"Test1\") {\n"
+ "int i;\n"
+ "int j;\n"
+ "}// TESTSUITE(\"Test1\")",
+ fixNamespaceEndComments("TESTSUITE(\"Test1\") {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ Style));
+}
+
TEST_F(NamespaceEndCommentsFixerTest, AddsNewlineIfNeeded) {
EXPECT_EQ("namespace A {\n"
"int i;\n"
@@ -380,6 +460,54 @@
"}; /* unnamed namespace */"));
}
+TEST_F(NamespaceEndCommentsFixerTest, KeepsValidMacroEndComment) {
+ FormatStyle Style = getLLVMStyle();
+ Style.NamespaceMacros.push_back("TESTSUITE");
+
+ EXPECT_EQ("TESTSUITE() {\n"
+ "int i;\n"
+ "} // end anonymous TESTSUITE()",
+ fixNamespaceEndComments("TESTSUITE() {\n"
+ "int i;\n"
+ "} // end anonymous TESTSUITE()",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} /* end of TESTSUITE(A) */",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} /* end of TESTSUITE(A) */",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ Style));
+ EXPECT_EQ("TESTSUITE(A::B) {\n"
+ "int i;\n"
+ "} // end TESTSUITE(A::B)",
+ fixNamespaceEndComments("TESTSUITE(A::B) {\n"
+ "int i;\n"
+ "} // end TESTSUITE(A::B)",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; // end TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; // end TESTSUITE(A)",
+ Style));
+ EXPECT_EQ("TESTSUITE() {\n"
+ "int i;\n"
+ "}; /* unnamed TESTSUITE() */",
+ fixNamespaceEndComments("TESTSUITE() {\n"
+ "int i;\n"
+ "}; /* unnamed TESTSUITE() */",
+ Style));
+}
+
TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndLineComment) {
EXPECT_EQ("namespace {\n"
"int i;\n"
@@ -446,6 +574,96 @@
CompactNamespacesStyle));
}
+TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidMacroEndLineComment) {
+ FormatStyle Style = getLLVMStyle();
+ Style.NamespaceMacros.push_back("TESTSUITE");
+
+ EXPECT_EQ("TESTSUITE() {\n"
+ "int i;\n"
+ "} // TESTSUITE()",
+ fixNamespaceEndComments("TESTSUITE() {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE()",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} //",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; //",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE A",
+ Style));
+ EXPECT_EQ("TESTSUITE() {\n"
+ "int i;\n"
+ "} // TESTSUITE()",
+ fixNamespaceEndComments("TESTSUITE() {\n"
+ "int i;\n"
+ "} // TESTSUITE",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TOASTSUITE(A)",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; // TOASTSUITE(A)",
+ Style));
+ // Updates invalid line comments even for short namespaces.
+ EXPECT_EQ("TESTSUITE(A) {} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {} // TESTSUITE()", Style));
+ EXPECT_EQ("TESTSUITE(A) {}; // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {}; // TESTSUITE()", Style));
+
+ // Update invalid comments for compacted namespaces.
+ FormatStyle CompactNamespacesStyle = getLLVMStyle();
+ CompactNamespacesStyle.CompactNamespaces = true;
+ CompactNamespacesStyle.NamespaceMacros.push_back("TESTSUITE");
+
+ EXPECT_EQ("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}} // TESTSUITE(out::in)",
+ fixNamespaceEndComments("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}} // TESTSUITE(out)",
+ CompactNamespacesStyle));
+ EXPECT_EQ("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}} // TESTSUITE(out::in)",
+ fixNamespaceEndComments("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}} // TESTSUITE(in)",
+ CompactNamespacesStyle));
+ EXPECT_EQ("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}\n"
+ "} // TESTSUITE(out::in)",
+ fixNamespaceEndComments("TESTSUITE(out) { TESTSUITE(in) {\n"
+ "}// TAOSTSUITE(in)\n"
+ "} // TESTSUITE(out)",
+ CompactNamespacesStyle));
+}
+
TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndBlockComment) {
EXPECT_EQ("namespace {\n"
"int i;\n"
@@ -489,6 +707,58 @@
fixNamespaceEndComments("namespace A {}; /**/"));
}
+TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidMacroEndBlockComment) {
+ FormatStyle Style = getLLVMStyle();
+ Style.NamespaceMacros.push_back("TESTSUITE");
+
+ EXPECT_EQ("TESTSUITE() {\n"
+ "int i;\n"
+ "} // TESTSUITE()",
+ fixNamespaceEndComments("TESTSUITE() {\n"
+ "int i;\n"
+ "} /* TESTSUITE(A) */",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} /* end TESTSUITE() */",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} /**/",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} /* end unnamed TESTSUITE() */",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "} /* TOASTSUITE(A) */",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {\n"
+ "int i;\n"
+ "}; /* TAOSTSUITE(A) */",
+ Style));
+ EXPECT_EQ("TESTSUITE(A) {} // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {} /**/", Style));
+ EXPECT_EQ("TESTSUITE(A) {}; // TESTSUITE(A)",
+ fixNamespaceEndComments("TESTSUITE(A) {}; /**/", Style));
+}
+
TEST_F(NamespaceEndCommentsFixerTest,
DoesNotAddEndCommentForNamespacesControlledByMacros) {
EXPECT_EQ("#ifdef 1\n"