blob: feafadb1593e2952c37428f002dd31a4bcf6b385 [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(R"(ID(
{ ID(a *b); });
)",
Style);
verifyIncompleteFormat(R"(ID3({, ID(a *b),
;
});
)",
Style);
verifyFormat("ID(CALL(CALL(return a * b;)));", Style);
verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
" MySomewhatLongFunction(SomethingElse()));\n",
Style);
verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
" MySomewhatLongFunction(SomethingElse()), "
"ReturnMe());\n",
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);
}
} // namespace
} // namespace test
} // namespace format
} // namespace clang