1f8d10d5aSManuel Klimek //===- unittest/Format/FormatMacroExpansion.cpp - Formatting unit tests ---===//
2f8d10d5aSManuel Klimek //
3f8d10d5aSManuel Klimek // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f8d10d5aSManuel Klimek // See https://llvm.org/LICENSE.txt for license information.
5f8d10d5aSManuel Klimek // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f8d10d5aSManuel Klimek //
7f8d10d5aSManuel Klimek //===----------------------------------------------------------------------===//
8f8d10d5aSManuel Klimek
9f8d10d5aSManuel Klimek #include "FormatTestBase.h"
10f8d10d5aSManuel Klimek
11f8d10d5aSManuel Klimek #define DEBUG_TYPE "format-test-macro-expansion"
12f8d10d5aSManuel Klimek
13f8d10d5aSManuel Klimek namespace clang {
14f8d10d5aSManuel Klimek namespace format {
15f8d10d5aSManuel Klimek namespace test {
16f8d10d5aSManuel Klimek namespace {
17f8d10d5aSManuel Klimek
18f8d10d5aSManuel Klimek class FormatTestMacroExpansion : public FormatTestBase {};
19f8d10d5aSManuel Klimek
TEST_F(FormatTestMacroExpansion,UnexpandConfiguredMacros)20f8d10d5aSManuel Klimek TEST_F(FormatTestMacroExpansion, UnexpandConfiguredMacros) {
21f8d10d5aSManuel Klimek FormatStyle Style = getLLVMStyle();
22f8d10d5aSManuel Klimek Style.Macros.push_back("CLASS=class C {");
23f8d10d5aSManuel Klimek Style.Macros.push_back("SEMI=;");
24f8d10d5aSManuel Klimek Style.Macros.push_back("STMT=f();");
25f8d10d5aSManuel Klimek Style.Macros.push_back("ID(x)=x");
26f8d10d5aSManuel Klimek Style.Macros.push_back("ID3(x, y, z)=x y z");
27f8d10d5aSManuel Klimek Style.Macros.push_back("CALL(x)=f([] { x })");
28f8d10d5aSManuel Klimek Style.Macros.push_back("ASSIGN_OR_RETURN(a, b)=a = (b)");
29f8d10d5aSManuel Klimek Style.Macros.push_back("ASSIGN_OR_RETURN(a, b, c)=a = (b); if (x) return c");
30f8d10d5aSManuel Klimek Style.Macros.push_back("MOCK_METHOD(r, n, a, s)=r n a s");
31f8d10d5aSManuel Klimek
32f8d10d5aSManuel Klimek verifyFormat("ID(nested(a(b, c), d))", Style);
33f8d10d5aSManuel Klimek verifyFormat("CLASS\n"
34f8d10d5aSManuel Klimek " a *b;\n"
35f8d10d5aSManuel Klimek "};",
36f8d10d5aSManuel Klimek Style);
37f8d10d5aSManuel Klimek verifyFormat("SEMI\n"
38f8d10d5aSManuel Klimek "SEMI\n"
39f8d10d5aSManuel Klimek "SEMI",
40f8d10d5aSManuel Klimek Style);
41f8d10d5aSManuel Klimek verifyFormat("STMT\n"
42f8d10d5aSManuel Klimek "STMT\n"
43f8d10d5aSManuel Klimek "STMT",
44f8d10d5aSManuel Klimek Style);
45f8d10d5aSManuel Klimek verifyFormat("void f() { ID(a *b); }", Style);
46*51f16814SOwen Pan verifyFormat("ID(\n"
47*51f16814SOwen Pan " {\n"
48*51f16814SOwen Pan " ID(a *b);\n"
49*51f16814SOwen Pan " });",
50f8d10d5aSManuel Klimek Style);
517e856d18SOwen Pan verifyIncompleteFormat("ID3({, ID(a *b),\n"
527e856d18SOwen Pan " ;\n"
537e856d18SOwen Pan " });",
54d08fcc81SOwen Pan Style);
55f8d10d5aSManuel Klimek
56f8d10d5aSManuel Klimek verifyFormat("ID(CALL(CALL(return a * b;)));", Style);
57f8d10d5aSManuel Klimek
58f8d10d5aSManuel Klimek verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
5988934a82SOwen Pan " MySomewhatLongFunction(SomethingElse()));",
60f8d10d5aSManuel Klimek Style);
61f8d10d5aSManuel Klimek verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
62f8d10d5aSManuel Klimek " MySomewhatLongFunction(SomethingElse()), "
6388934a82SOwen Pan "ReturnMe());",
64f8d10d5aSManuel Klimek Style);
65f8d10d5aSManuel Klimek
66f8d10d5aSManuel Klimek verifyFormat(R"(
67f8d10d5aSManuel Klimek #define MACRO(a, b) ID(a + b)
68f8d10d5aSManuel Klimek )",
69f8d10d5aSManuel Klimek Style);
70f8d10d5aSManuel Klimek EXPECT_EQ(R"(
71f8d10d5aSManuel Klimek int a;
72f8d10d5aSManuel Klimek int b;
73f8d10d5aSManuel Klimek int c;
74f8d10d5aSManuel Klimek int d;
75f8d10d5aSManuel Klimek int e;
76f8d10d5aSManuel Klimek int f;
77f8d10d5aSManuel Klimek ID(
78f8d10d5aSManuel Klimek namespace foo {
79f8d10d5aSManuel Klimek int a;
80f8d10d5aSManuel Klimek }
81f8d10d5aSManuel Klimek ) // namespace k
82f8d10d5aSManuel Klimek )",
83f8d10d5aSManuel Klimek format(R"(
84f8d10d5aSManuel Klimek int a;
85f8d10d5aSManuel Klimek int b;
86f8d10d5aSManuel Klimek int c;
87f8d10d5aSManuel Klimek int d;
88f8d10d5aSManuel Klimek int e;
89f8d10d5aSManuel Klimek int f;
90f8d10d5aSManuel Klimek ID(namespace foo { int a; }) // namespace k
91f8d10d5aSManuel Klimek )",
92f8d10d5aSManuel Klimek Style));
93f8d10d5aSManuel Klimek verifyFormat(R"(ID(
94f8d10d5aSManuel Klimek //
95f8d10d5aSManuel Klimek ({ ; }))
96f8d10d5aSManuel Klimek )",
97f8d10d5aSManuel Klimek Style);
98f8d10d5aSManuel Klimek
99f8d10d5aSManuel Klimek Style.ColumnLimit = 35;
100f8d10d5aSManuel Klimek // FIXME: Arbitrary formatting of macros where the end of the logical
101f8d10d5aSManuel Klimek // line is in the middle of a macro call are not working yet.
102f8d10d5aSManuel Klimek verifyFormat(R"(ID(
103f8d10d5aSManuel Klimek void f();
104f8d10d5aSManuel Klimek void)
105f8d10d5aSManuel Klimek ID(g) ID(()) ID(
106f8d10d5aSManuel Klimek ;
107f8d10d5aSManuel Klimek void g();)
108f8d10d5aSManuel Klimek )",
109f8d10d5aSManuel Klimek Style);
110f8d10d5aSManuel Klimek
111f8d10d5aSManuel Klimek Style.ColumnLimit = 10;
112f8d10d5aSManuel Klimek verifyFormat("STMT\n"
113f8d10d5aSManuel Klimek "STMT\n"
114f8d10d5aSManuel Klimek "STMT",
115f8d10d5aSManuel Klimek Style);
116f8d10d5aSManuel Klimek
117f8d10d5aSManuel Klimek EXPECT_EQ(R"(
118f8d10d5aSManuel Klimek ID(CALL(CALL(
119f8d10d5aSManuel Klimek a *b)));
120f8d10d5aSManuel Klimek )",
121f8d10d5aSManuel Klimek format(R"(
122f8d10d5aSManuel Klimek ID(CALL(CALL(a * b)));
123f8d10d5aSManuel Klimek )",
124f8d10d5aSManuel Klimek Style));
125f8d10d5aSManuel Klimek
126f8d10d5aSManuel Klimek // FIXME: If we want to support unbalanced braces or parens from macro
127f8d10d5aSManuel Klimek // expansions we need to re-think how we propagate errors in
128f8d10d5aSManuel Klimek // TokenAnnotator::parseLine; for investigation, switching the inner loop of
129f8d10d5aSManuel Klimek // TokenAnnotator::parseLine to return LT_Other instead of LT_Invalid in case
130f8d10d5aSManuel Klimek // of !consumeToken() changes the formatting of the test below and makes it
131f8d10d5aSManuel Klimek // believe it has a fully correct formatting.
132f8d10d5aSManuel Klimek EXPECT_EQ(R"(
133f8d10d5aSManuel Klimek ID3(
134f8d10d5aSManuel Klimek {
135f8d10d5aSManuel Klimek CLASS
136f8d10d5aSManuel Klimek a *b;
137f8d10d5aSManuel Klimek };
138f8d10d5aSManuel Klimek },
139f8d10d5aSManuel Klimek ID(x *y);
140f8d10d5aSManuel Klimek ,
141f8d10d5aSManuel Klimek STMT
142f8d10d5aSManuel Klimek STMT
143f8d10d5aSManuel Klimek STMT)
144f8d10d5aSManuel Klimek void f();
145f8d10d5aSManuel Klimek )",
146f8d10d5aSManuel Klimek format(R"(
147f8d10d5aSManuel Klimek ID3({CLASS a*b; };}, ID(x*y);, STMT STMT STMT)
148f8d10d5aSManuel Klimek void f();
149f8d10d5aSManuel Klimek )",
150f8d10d5aSManuel Klimek Style));
151f8d10d5aSManuel Klimek
152f8d10d5aSManuel Klimek verifyFormat("ID(a(\n"
153f8d10d5aSManuel Klimek "#ifdef A\n"
154f8d10d5aSManuel Klimek " b, c\n"
155f8d10d5aSManuel Klimek "#else\n"
156f8d10d5aSManuel Klimek " d(e)\n"
157f8d10d5aSManuel Klimek "#endif\n"
158f8d10d5aSManuel Klimek " ))",
159f8d10d5aSManuel Klimek Style);
160f8d10d5aSManuel Klimek Style.ColumnLimit = 80;
161f8d10d5aSManuel Klimek verifyFormat(R"(ASSIGN_OR_RETURN(
162f8d10d5aSManuel Klimek // Comment
163f8d10d5aSManuel Klimek a b, c);
164f8d10d5aSManuel Klimek )",
165f8d10d5aSManuel Klimek Style);
166f8d10d5aSManuel Klimek Style.ColumnLimit = 30;
167f8d10d5aSManuel Klimek verifyFormat(R"(ASSIGN_OR_RETURN(
168f8d10d5aSManuel Klimek // Comment
169f8d10d5aSManuel Klimek //
170f8d10d5aSManuel Klimek a b,
171f8d10d5aSManuel Klimek xxxxxxxxxxxx(
172f8d10d5aSManuel Klimek yyyyyyyyyyyyyyyyy,
173f8d10d5aSManuel Klimek zzzzzzzzzzzzzzzzzz),
174f8d10d5aSManuel Klimek f([]() {
175f8d10d5aSManuel Klimek a();
176f8d10d5aSManuel Klimek b();
177f8d10d5aSManuel Klimek }));
178f8d10d5aSManuel Klimek )",
179f8d10d5aSManuel Klimek Style);
180f8d10d5aSManuel Klimek verifyFormat(R"(int a = []() {
181f8d10d5aSManuel Klimek ID(
182f8d10d5aSManuel Klimek x;
183f8d10d5aSManuel Klimek y;
184f8d10d5aSManuel Klimek z;)
185f8d10d5aSManuel Klimek ;
186f8d10d5aSManuel Klimek }();
187f8d10d5aSManuel Klimek )",
188f8d10d5aSManuel Klimek Style);
189f8d10d5aSManuel Klimek EXPECT_EQ(
190f8d10d5aSManuel Klimek R"(ASSIGN_OR_RETURN((
191f8d10d5aSManuel Klimek ====
192f8d10d5aSManuel Klimek #))
193f8d10d5aSManuel Klimek })",
194f8d10d5aSManuel Klimek format(R"(ASSIGN_OR_RETURN((
195f8d10d5aSManuel Klimek ====
196f8d10d5aSManuel Klimek #))
197f8d10d5aSManuel Klimek })",
198f8d10d5aSManuel Klimek Style, SC_ExpectIncomplete));
199f8d10d5aSManuel Klimek EXPECT_EQ(R"(ASSIGN_OR_RETURN(
200f8d10d5aSManuel Klimek }
201f8d10d5aSManuel Klimek (
202f8d10d5aSManuel Klimek ====
203f8d10d5aSManuel Klimek #),
204f8d10d5aSManuel Klimek a))",
205f8d10d5aSManuel Klimek format(R"(ASSIGN_OR_RETURN(
206f8d10d5aSManuel Klimek }
207f8d10d5aSManuel Klimek (
208f8d10d5aSManuel Klimek ====
209f8d10d5aSManuel Klimek #),
210f8d10d5aSManuel Klimek a))",
211f8d10d5aSManuel Klimek Style, SC_ExpectIncomplete));
212f8d10d5aSManuel Klimek EXPECT_EQ(R"(ASSIGN_OR_RETURN(a
213f8d10d5aSManuel Klimek //
214f8d10d5aSManuel Klimek ====
215f8d10d5aSManuel Klimek #
216f8d10d5aSManuel Klimek <))",
217f8d10d5aSManuel Klimek format(R"(ASSIGN_OR_RETURN(a
218f8d10d5aSManuel Klimek //
219f8d10d5aSManuel Klimek ====
220f8d10d5aSManuel Klimek #
221f8d10d5aSManuel Klimek <))",
222f8d10d5aSManuel Klimek Style));
223f8d10d5aSManuel Klimek verifyFormat("class C {\n"
224f8d10d5aSManuel Klimek " MOCK_METHOD(R, f,\n"
225f8d10d5aSManuel Klimek " (a *b, c *d),\n"
226f8d10d5aSManuel Klimek " (override));\n"
227f8d10d5aSManuel Klimek "};",
228f8d10d5aSManuel Klimek Style);
229f8d10d5aSManuel Klimek }
230f8d10d5aSManuel Klimek
TEST_F(FormatTestMacroExpansion,KeepParensWhenExpandingObjectLikeMacros)231f8d10d5aSManuel Klimek TEST_F(FormatTestMacroExpansion, KeepParensWhenExpandingObjectLikeMacros) {
232f8d10d5aSManuel Klimek FormatStyle Style = getLLVMStyle();
233f8d10d5aSManuel Klimek Style.Macros.push_back("FN=class C { int f");
234f8d10d5aSManuel Klimek verifyFormat("void f() {\n"
235f8d10d5aSManuel Klimek " FN(a *b);\n"
236f8d10d5aSManuel Klimek " };\n"
237f8d10d5aSManuel Klimek "}",
238f8d10d5aSManuel Klimek Style);
239f8d10d5aSManuel Klimek }
240f8d10d5aSManuel Klimek
TEST_F(FormatTestMacroExpansion,DoesNotExpandFunctionLikeMacrosWithoutParens)241f8d10d5aSManuel Klimek TEST_F(FormatTestMacroExpansion, DoesNotExpandFunctionLikeMacrosWithoutParens) {
242f8d10d5aSManuel Klimek FormatStyle Style = getLLVMStyle();
243f8d10d5aSManuel Klimek Style.Macros.push_back("CLASS()=class C {");
244f8d10d5aSManuel Klimek verifyFormat("CLASS void f();\n"
245f8d10d5aSManuel Klimek "}\n"
246f8d10d5aSManuel Klimek ";",
247f8d10d5aSManuel Klimek Style);
248f8d10d5aSManuel Klimek }
249f8d10d5aSManuel Klimek
TEST_F(FormatTestMacroExpansion,ContinueFormattingAfterUnclosedParensAfterObjectLikeMacro)250f8d10d5aSManuel Klimek TEST_F(FormatTestMacroExpansion,
251f8d10d5aSManuel Klimek ContinueFormattingAfterUnclosedParensAfterObjectLikeMacro) {
252f8d10d5aSManuel Klimek FormatStyle Style = getLLVMStyle();
253f8d10d5aSManuel Klimek Style.Macros.push_back("O=class {");
254d08fcc81SOwen Pan verifyIncompleteFormat("O(auto x = [](){\n"
255d08fcc81SOwen Pan " f();}",
256d08fcc81SOwen Pan Style);
257f8d10d5aSManuel Klimek }
258f8d10d5aSManuel Klimek
TEST_F(FormatTestMacroExpansion,CommaAsOperator)259b7770befSr4nt TEST_F(FormatTestMacroExpansion, CommaAsOperator) {
260b7770befSr4nt FormatStyle Style = getGoogleStyleWithColumns(42);
261b7770befSr4nt Style.Macros.push_back("MACRO(a, b, c)=a=(b); if(x) c");
262b7770befSr4nt verifyFormat("MACRO(auto a,\n"
263b7770befSr4nt " looooongfunction(first, second,\n"
264b7770befSr4nt " third),\n"
265b7770befSr4nt " fourth);",
266b7770befSr4nt Style);
267b7770befSr4nt }
268b7770befSr4nt
TEST_F(FormatTestMacroExpansion,ForcedBreakDiffers)269b7770befSr4nt TEST_F(FormatTestMacroExpansion, ForcedBreakDiffers) {
270b7770befSr4nt FormatStyle Style = getGoogleStyleWithColumns(40);
271b7770befSr4nt Style.Macros.push_back("MACRO(a, b)=a=(b)");
272b7770befSr4nt verifyFormat("//\n"
273b7770befSr4nt "MACRO(const type variable,\n"
274b7770befSr4nt " functtioncall(\n"
275b7770befSr4nt " first, longsecondarg, third));",
276b7770befSr4nt Style);
277b7770befSr4nt }
278b7770befSr4nt
TEST_F(FormatTestMacroExpansion,PreferNotBreakingBetweenReturnTypeAndFunction)279b7770befSr4nt TEST_F(FormatTestMacroExpansion,
280b7770befSr4nt PreferNotBreakingBetweenReturnTypeAndFunction) {
281b7770befSr4nt FormatStyle Style = getGoogleStyleWithColumns(22);
282b7770befSr4nt Style.Macros.push_back("MOCK_METHOD(r, n, a)=r n a");
283b7770befSr4nt // In the expanded code, we parse a full function signature, and afterwards
284b7770befSr4nt // know that we prefer not to break before the function name.
285b7770befSr4nt verifyFormat("MOCK_METHOD(\n"
286b7770befSr4nt " type, variable,\n"
287b7770befSr4nt " (type));",
288ddb4450aSr4nt Style);
289ddb4450aSr4nt }
290ddb4450aSr4nt
TEST_F(FormatTestMacroExpansion,IndentChildrenWithinMacroCall)291ddb4450aSr4nt TEST_F(FormatTestMacroExpansion, IndentChildrenWithinMacroCall) {
292ddb4450aSr4nt FormatStyle Style = getGoogleStyleWithColumns(22);
293ddb4450aSr4nt Style.Macros.push_back("MACRO(a, b)=a=(b)");
294ddb4450aSr4nt verifyFormat("void f() {\n"
295ddb4450aSr4nt " MACRO(a b, call([] {\n"
296ddb4450aSr4nt " if (expr) {\n"
297ddb4450aSr4nt " indent();\n"
298ddb4450aSr4nt " }\n"
299ddb4450aSr4nt " }));\n"
300ddb4450aSr4nt "}",
301b7770befSr4nt Style);
302b7770befSr4nt }
303b7770befSr4nt
304f8d10d5aSManuel Klimek } // namespace
305f8d10d5aSManuel Klimek } // namespace test
306f8d10d5aSManuel Klimek } // namespace format
307f8d10d5aSManuel Klimek } // namespace clang
308