xref: /llvm-project/clang/unittests/Format/FormatTestMacroExpansion.cpp (revision 51f1681424f1a8ccf1e3432d71c341e799597171)
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 
13 namespace clang {
14 namespace format {
15 namespace test {
16 namespace {
17 
18 class FormatTestMacroExpansion : public FormatTestBase {};
19 
TEST_F(FormatTestMacroExpansion,UnexpandConfiguredMacros)20 TEST_F(FormatTestMacroExpansion, UnexpandConfiguredMacros) {
21   FormatStyle Style = getLLVMStyle();
22   Style.Macros.push_back("CLASS=class C {");
23   Style.Macros.push_back("SEMI=;");
24   Style.Macros.push_back("STMT=f();");
25   Style.Macros.push_back("ID(x)=x");
26   Style.Macros.push_back("ID3(x, y, z)=x y z");
27   Style.Macros.push_back("CALL(x)=f([] { x })");
28   Style.Macros.push_back("ASSIGN_OR_RETURN(a, b)=a = (b)");
29   Style.Macros.push_back("ASSIGN_OR_RETURN(a, b, c)=a = (b); if (x) return c");
30   Style.Macros.push_back("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"(
71 int a;
72 int b;
73 int c;
74 int d;
75 int e;
76 int f;
77 ID(
78     namespace foo {
79     int a;
80     }
81 ) // namespace k
82 )",
83             format(R"(
84 int a;
85 int b;
86 int c;
87 int d;
88 int e;
89 int f;
90 ID(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)
105 ID(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"(
118 ID(CALL(CALL(
119     a *b)));
120 )",
121             format(R"(
122 ID(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"(
133 ID3(
134     {
135       CLASS
136         a *b;
137       };
138     },
139     ID(x *y);
140     ,
141     STMT
142     STMT
143     STMT)
144 void f();
145 )",
146             format(R"(
147 ID3({CLASS a*b; };}, ID(x*y);, STMT STMT STMT)
148 void 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 #),
210 a))",
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 
TEST_F(FormatTestMacroExpansion,KeepParensWhenExpandingObjectLikeMacros)231 TEST_F(FormatTestMacroExpansion, KeepParensWhenExpandingObjectLikeMacros) {
232   FormatStyle Style = getLLVMStyle();
233   Style.Macros.push_back("FN=class C { int f");
234   verifyFormat("void f() {\n"
235                "  FN(a *b);\n"
236                "  };\n"
237                "}",
238                Style);
239 }
240 
TEST_F(FormatTestMacroExpansion,DoesNotExpandFunctionLikeMacrosWithoutParens)241 TEST_F(FormatTestMacroExpansion, DoesNotExpandFunctionLikeMacrosWithoutParens) {
242   FormatStyle Style = getLLVMStyle();
243   Style.Macros.push_back("CLASS()=class C {");
244   verifyFormat("CLASS void f();\n"
245                "}\n"
246                ";",
247                Style);
248 }
249 
TEST_F(FormatTestMacroExpansion,ContinueFormattingAfterUnclosedParensAfterObjectLikeMacro)250 TEST_F(FormatTestMacroExpansion,
251        ContinueFormattingAfterUnclosedParensAfterObjectLikeMacro) {
252   FormatStyle Style = getLLVMStyle();
253   Style.Macros.push_back("O=class {");
254   verifyIncompleteFormat("O(auto x = [](){\n"
255                          "    f();}",
256                          Style);
257 }
258 
TEST_F(FormatTestMacroExpansion,CommaAsOperator)259 TEST_F(FormatTestMacroExpansion, CommaAsOperator) {
260   FormatStyle Style = getGoogleStyleWithColumns(42);
261   Style.Macros.push_back("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 
TEST_F(FormatTestMacroExpansion,ForcedBreakDiffers)269 TEST_F(FormatTestMacroExpansion, ForcedBreakDiffers) {
270   FormatStyle Style = getGoogleStyleWithColumns(40);
271   Style.Macros.push_back("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 
TEST_F(FormatTestMacroExpansion,PreferNotBreakingBetweenReturnTypeAndFunction)279 TEST_F(FormatTestMacroExpansion,
280        PreferNotBreakingBetweenReturnTypeAndFunction) {
281   FormatStyle Style = getGoogleStyleWithColumns(22);
282   Style.Macros.push_back("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 
TEST_F(FormatTestMacroExpansion,IndentChildrenWithinMacroCall)291 TEST_F(FormatTestMacroExpansion, IndentChildrenWithinMacroCall) {
292   FormatStyle Style = getGoogleStyleWithColumns(22);
293   Style.Macros.push_back("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