blob: d391fe3d715c38bfc28a0ed9eda14c5cb7641f2a [file] [log] [blame]
//===- 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