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

source code of clang/unittests/Format/FormatTestMacroExpansion.cpp