mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 14:26:08 +00:00
308 lines
7.5 KiB
C++
308 lines
7.5 KiB
C++
//===- unittest/Format/FormatMacroExpansion.cpp - Formatting unit tests ---===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FormatTestBase.h"
|
|
|
|
#define DEBUG_TYPE "format-test-macro-expansion"
|
|
|
|
namespace clang {
|
|
namespace format {
|
|
namespace test {
|
|
namespace {
|
|
|
|
class FormatTestMacroExpansion : public FormatTestBase {};
|
|
|
|
TEST_F(FormatTestMacroExpansion, UnexpandConfiguredMacros) {
|
|
FormatStyle Style = getLLVMStyle();
|
|
Style.Macros.push_back("CLASS=class C {");
|
|
Style.Macros.push_back("SEMI=;");
|
|
Style.Macros.push_back("STMT=f();");
|
|
Style.Macros.push_back("ID(x)=x");
|
|
Style.Macros.push_back("ID3(x, y, z)=x y z");
|
|
Style.Macros.push_back("CALL(x)=f([] { x })");
|
|
Style.Macros.push_back("ASSIGN_OR_RETURN(a, b)=a = (b)");
|
|
Style.Macros.push_back("ASSIGN_OR_RETURN(a, b, c)=a = (b); if (x) return c");
|
|
Style.Macros.push_back("MOCK_METHOD(r, n, a, s)=r n a s");
|
|
|
|
verifyFormat("ID(nested(a(b, c), d))", Style);
|
|
verifyFormat("CLASS\n"
|
|
" a *b;\n"
|
|
"};",
|
|
Style);
|
|
verifyFormat("SEMI\n"
|
|
"SEMI\n"
|
|
"SEMI",
|
|
Style);
|
|
verifyFormat("STMT\n"
|
|
"STMT\n"
|
|
"STMT",
|
|
Style);
|
|
verifyFormat("void f() { ID(a *b); }", Style);
|
|
verifyFormat("ID(\n"
|
|
" {\n"
|
|
" ID(a *b);\n"
|
|
" });",
|
|
Style);
|
|
verifyIncompleteFormat("ID3({, ID(a *b),\n"
|
|
" ;\n"
|
|
" });",
|
|
Style);
|
|
|
|
verifyFormat("ID(CALL(CALL(return a * b;)));", Style);
|
|
|
|
verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
|
|
" MySomewhatLongFunction(SomethingElse()));",
|
|
Style);
|
|
verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
|
|
" MySomewhatLongFunction(SomethingElse()), "
|
|
"ReturnMe());",
|
|
Style);
|
|
|
|
verifyFormat(R"(
|
|
#define MACRO(a, b) ID(a + b)
|
|
)",
|
|
Style);
|
|
EXPECT_EQ(R"(
|
|
int a;
|
|
int b;
|
|
int c;
|
|
int d;
|
|
int e;
|
|
int f;
|
|
ID(
|
|
namespace foo {
|
|
int a;
|
|
}
|
|
) // namespace k
|
|
)",
|
|
format(R"(
|
|
int a;
|
|
int b;
|
|
int c;
|
|
int d;
|
|
int e;
|
|
int f;
|
|
ID(namespace foo { int a; }) // namespace k
|
|
)",
|
|
Style));
|
|
verifyFormat(R"(ID(
|
|
//
|
|
({ ; }))
|
|
)",
|
|
Style);
|
|
|
|
Style.ColumnLimit = 35;
|
|
// FIXME: Arbitrary formatting of macros where the end of the logical
|
|
// line is in the middle of a macro call are not working yet.
|
|
verifyFormat(R"(ID(
|
|
void f();
|
|
void)
|
|
ID(g) ID(()) ID(
|
|
;
|
|
void g();)
|
|
)",
|
|
Style);
|
|
|
|
Style.ColumnLimit = 10;
|
|
verifyFormat("STMT\n"
|
|
"STMT\n"
|
|
"STMT",
|
|
Style);
|
|
|
|
EXPECT_EQ(R"(
|
|
ID(CALL(CALL(
|
|
a *b)));
|
|
)",
|
|
format(R"(
|
|
ID(CALL(CALL(a * b)));
|
|
)",
|
|
Style));
|
|
|
|
// FIXME: If we want to support unbalanced braces or parens from macro
|
|
// expansions we need to re-think how we propagate errors in
|
|
// TokenAnnotator::parseLine; for investigation, switching the inner loop of
|
|
// TokenAnnotator::parseLine to return LT_Other instead of LT_Invalid in case
|
|
// of !consumeToken() changes the formatting of the test below and makes it
|
|
// believe it has a fully correct formatting.
|
|
EXPECT_EQ(R"(
|
|
ID3(
|
|
{
|
|
CLASS
|
|
a *b;
|
|
};
|
|
},
|
|
ID(x *y);
|
|
,
|
|
STMT
|
|
STMT
|
|
STMT)
|
|
void f();
|
|
)",
|
|
format(R"(
|
|
ID3({CLASS a*b; };}, ID(x*y);, STMT STMT STMT)
|
|
void f();
|
|
)",
|
|
Style));
|
|
|
|
verifyFormat("ID(a(\n"
|
|
"#ifdef A\n"
|
|
" b, c\n"
|
|
"#else\n"
|
|
" d(e)\n"
|
|
"#endif\n"
|
|
" ))",
|
|
Style);
|
|
Style.ColumnLimit = 80;
|
|
verifyFormat(R"(ASSIGN_OR_RETURN(
|
|
// Comment
|
|
a b, c);
|
|
)",
|
|
Style);
|
|
Style.ColumnLimit = 30;
|
|
verifyFormat(R"(ASSIGN_OR_RETURN(
|
|
// Comment
|
|
//
|
|
a b,
|
|
xxxxxxxxxxxx(
|
|
yyyyyyyyyyyyyyyyy,
|
|
zzzzzzzzzzzzzzzzzz),
|
|
f([]() {
|
|
a();
|
|
b();
|
|
}));
|
|
)",
|
|
Style);
|
|
verifyFormat(R"(int a = []() {
|
|
ID(
|
|
x;
|
|
y;
|
|
z;)
|
|
;
|
|
}();
|
|
)",
|
|
Style);
|
|
EXPECT_EQ(
|
|
R"(ASSIGN_OR_RETURN((
|
|
====
|
|
#))
|
|
})",
|
|
format(R"(ASSIGN_OR_RETURN((
|
|
====
|
|
#))
|
|
})",
|
|
Style, SC_ExpectIncomplete));
|
|
EXPECT_EQ(R"(ASSIGN_OR_RETURN(
|
|
}
|
|
(
|
|
====
|
|
#),
|
|
a))",
|
|
format(R"(ASSIGN_OR_RETURN(
|
|
}
|
|
(
|
|
====
|
|
#),
|
|
a))",
|
|
Style, SC_ExpectIncomplete));
|
|
EXPECT_EQ(R"(ASSIGN_OR_RETURN(a
|
|
//
|
|
====
|
|
#
|
|
<))",
|
|
format(R"(ASSIGN_OR_RETURN(a
|
|
//
|
|
====
|
|
#
|
|
<))",
|
|
Style));
|
|
verifyFormat("class C {\n"
|
|
" MOCK_METHOD(R, f,\n"
|
|
" (a *b, c *d),\n"
|
|
" (override));\n"
|
|
"};",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion, KeepParensWhenExpandingObjectLikeMacros) {
|
|
FormatStyle Style = getLLVMStyle();
|
|
Style.Macros.push_back("FN=class C { int f");
|
|
verifyFormat("void f() {\n"
|
|
" FN(a *b);\n"
|
|
" };\n"
|
|
"}",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion, DoesNotExpandFunctionLikeMacrosWithoutParens) {
|
|
FormatStyle Style = getLLVMStyle();
|
|
Style.Macros.push_back("CLASS()=class C {");
|
|
verifyFormat("CLASS void f();\n"
|
|
"}\n"
|
|
";",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion,
|
|
ContinueFormattingAfterUnclosedParensAfterObjectLikeMacro) {
|
|
FormatStyle Style = getLLVMStyle();
|
|
Style.Macros.push_back("O=class {");
|
|
verifyIncompleteFormat("O(auto x = [](){\n"
|
|
" f();}",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion, CommaAsOperator) {
|
|
FormatStyle Style = getGoogleStyleWithColumns(42);
|
|
Style.Macros.push_back("MACRO(a, b, c)=a=(b); if(x) c");
|
|
verifyFormat("MACRO(auto a,\n"
|
|
" looooongfunction(first, second,\n"
|
|
" third),\n"
|
|
" fourth);",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion, ForcedBreakDiffers) {
|
|
FormatStyle Style = getGoogleStyleWithColumns(40);
|
|
Style.Macros.push_back("MACRO(a, b)=a=(b)");
|
|
verifyFormat("//\n"
|
|
"MACRO(const type variable,\n"
|
|
" functtioncall(\n"
|
|
" first, longsecondarg, third));",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion,
|
|
PreferNotBreakingBetweenReturnTypeAndFunction) {
|
|
FormatStyle Style = getGoogleStyleWithColumns(22);
|
|
Style.Macros.push_back("MOCK_METHOD(r, n, a)=r n a");
|
|
// In the expanded code, we parse a full function signature, and afterwards
|
|
// know that we prefer not to break before the function name.
|
|
verifyFormat("MOCK_METHOD(\n"
|
|
" type, variable,\n"
|
|
" (type));",
|
|
Style);
|
|
}
|
|
|
|
TEST_F(FormatTestMacroExpansion, IndentChildrenWithinMacroCall) {
|
|
FormatStyle Style = getGoogleStyleWithColumns(22);
|
|
Style.Macros.push_back("MACRO(a, b)=a=(b)");
|
|
verifyFormat("void f() {\n"
|
|
" MACRO(a b, call([] {\n"
|
|
" if (expr) {\n"
|
|
" indent();\n"
|
|
" }\n"
|
|
" }));\n"
|
|
"}",
|
|
Style);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace test
|
|
} // namespace format
|
|
} // namespace clang
|