xref: /llvm-project/clang/unittests/Format/FormatTestMacroExpansion.cpp (revision d08fcc817eba7f0186620688eee73f6d25fa90e8)
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 
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(R"(ID(
47     { ID(a *b); });
48 )",
49                Style);
50   verifyIncompleteFormat(R"(ID3({, ID(a *b),
51   ;
52   });
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()));\n",
60                Style);
61   verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
62                "                 MySomewhatLongFunction(SomethingElse()), "
63                "ReturnMe());\n",
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 
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 
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 
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 
259 } // namespace
260 } // namespace test
261 } // namespace format
262 } // namespace clang
263