xref: /llvm-project/clang/unittests/Format/FormatTestMacroExpansion.cpp (revision 6a621ed8e4cb02bd55fe4a4a0254615576b70a55)
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("ID3({, ID(a *b), ; });", Style);
51 
52   verifyFormat("ID(CALL(CALL(return a * b;)));", Style);
53 
54   verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
55                "                 MySomewhatLongFunction(SomethingElse()));\n",
56                Style);
57   verifyFormat("ASSIGN_OR_RETURN(MySomewhatLongType *variable,\n"
58                "                 MySomewhatLongFunction(SomethingElse()), "
59                "ReturnMe());\n",
60                Style);
61 
62   verifyFormat(R"(
63 #define MACRO(a, b) ID(a + b)
64 )",
65                Style);
66   EXPECT_EQ(R"(
67 int a;
68 int b;
69 int c;
70 int d;
71 int e;
72 int f;
73 ID(
74     namespace foo {
75     int a;
76     }
77 ) // namespace k
78 )",
79             format(R"(
80 int a;
81 int b;
82 int c;
83 int d;
84 int e;
85 int f;
86 ID(namespace foo { int a; })  // namespace k
87 )",
88                    Style));
89   verifyFormat(R"(ID(
90     //
91     ({ ; }))
92 )",
93                Style);
94 
95   Style.ColumnLimit = 35;
96   // FIXME: Arbitrary formatting of macros where the end of the logical
97   // line is in the middle of a macro call are not working yet.
98   verifyFormat(R"(ID(
99     void f();
100     void)
101 ID(g) ID(()) ID(
102     ;
103     void g();)
104 )",
105                Style);
106 
107   Style.ColumnLimit = 10;
108   verifyFormat("STMT\n"
109                "STMT\n"
110                "STMT",
111                Style);
112 
113   EXPECT_EQ(R"(
114 ID(CALL(CALL(
115     a *b)));
116 )",
117             format(R"(
118 ID(CALL(CALL(a * b)));
119 )",
120                    Style));
121 
122   // FIXME: If we want to support unbalanced braces or parens from macro
123   // expansions we need to re-think how we propagate errors in
124   // TokenAnnotator::parseLine; for investigation, switching the inner loop of
125   // TokenAnnotator::parseLine to return LT_Other instead of LT_Invalid in case
126   // of !consumeToken() changes the formatting of the test below and makes it
127   // believe it has a fully correct formatting.
128   EXPECT_EQ(R"(
129 ID3(
130     {
131     CLASS
132     a *b;
133     };
134     },
135     ID(x *y);
136     ,
137     STMT
138     STMT
139     STMT)
140 void f();
141 )",
142             format(R"(
143 ID3({CLASS a*b; };}, ID(x*y);, STMT STMT STMT)
144 void f();
145 )",
146                    Style));
147 
148   verifyFormat("ID(a(\n"
149                "#ifdef A\n"
150                "    b, c\n"
151                "#else\n"
152                "    d(e)\n"
153                "#endif\n"
154                "    ))",
155                Style);
156   Style.ColumnLimit = 80;
157   verifyFormat(R"(ASSIGN_OR_RETURN(
158     // Comment
159     a b, c);
160 )",
161                Style);
162   Style.ColumnLimit = 30;
163   verifyFormat(R"(ASSIGN_OR_RETURN(
164     // Comment
165     //
166     a b,
167     xxxxxxxxxxxx(
168         yyyyyyyyyyyyyyyyy,
169         zzzzzzzzzzzzzzzzzz),
170     f([]() {
171       a();
172       b();
173     }));
174 )",
175                Style);
176   verifyFormat(R"(int a = []() {
177   ID(
178       x;
179       y;
180       z;)
181   ;
182 }();
183 )",
184                Style);
185   EXPECT_EQ(
186       R"(ASSIGN_OR_RETURN((
187 ====
188 #))
189 })",
190       format(R"(ASSIGN_OR_RETURN((
191 ====
192 #))
193 })",
194              Style, SC_ExpectIncomplete));
195   EXPECT_EQ(R"(ASSIGN_OR_RETURN(
196 }
197 (
198 ====
199 #),
200     a))",
201             format(R"(ASSIGN_OR_RETURN(
202 }
203 (
204 ====
205 #),
206 a))",
207                    Style, SC_ExpectIncomplete));
208   EXPECT_EQ(R"(ASSIGN_OR_RETURN(a
209 //
210 ====
211 #
212                  <))",
213             format(R"(ASSIGN_OR_RETURN(a
214 //
215 ====
216 #
217                  <))",
218                    Style));
219   verifyFormat("class C {\n"
220                "  MOCK_METHOD(R, f,\n"
221                "              (a *b, c *d),\n"
222                "              (override));\n"
223                "};",
224                Style);
225 }
226 
227 TEST_F(FormatTestMacroExpansion, KeepParensWhenExpandingObjectLikeMacros) {
228   FormatStyle Style = getLLVMStyle();
229   Style.Macros.push_back("FN=class C { int f");
230   verifyFormat("void f() {\n"
231                "  FN(a *b);\n"
232                "  };\n"
233                "}",
234                Style);
235 }
236 
237 TEST_F(FormatTestMacroExpansion, DoesNotExpandFunctionLikeMacrosWithoutParens) {
238   FormatStyle Style = getLLVMStyle();
239   Style.Macros.push_back("CLASS()=class C {");
240   verifyFormat("CLASS void f();\n"
241                "}\n"
242                ";",
243                Style);
244 }
245 
246 TEST_F(FormatTestMacroExpansion,
247        ContinueFormattingAfterUnclosedParensAfterObjectLikeMacro) {
248   FormatStyle Style = getLLVMStyle();
249   Style.Macros.push_back("O=class {");
250   verifyIncompleteFormat("O(auto x = [](){f();}", Style);
251 }
252 
253 } // namespace
254 } // namespace test
255 } // namespace format
256 } // namespace clang
257