xref: /llvm-project/clang/unittests/Format/FormatTestTextProto.cpp (revision 9ad7af64232488ec7c8b4801486051ccdceeead2)
1 //===- unittest/Format/FormatTestProto.cpp --------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "FormatTestUtils.h"
11 #include "clang/Format/Format.h"
12 #include "llvm/Support/Debug.h"
13 #include "gtest/gtest.h"
14 
15 #define DEBUG_TYPE "format-test"
16 
17 namespace clang {
18 namespace format {
19 
20 class FormatTestTextProto : public ::testing::Test {
21 protected:
22   static std::string format(llvm::StringRef Code, unsigned Offset,
23                             unsigned Length, const FormatStyle &Style) {
24     DEBUG(llvm::errs() << "---\n");
25     DEBUG(llvm::errs() << Code << "\n\n");
26     std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
27     tooling::Replacements Replaces = reformat(Style, Code, Ranges);
28     auto Result = applyAllReplacements(Code, Replaces);
29     EXPECT_TRUE(static_cast<bool>(Result));
30     DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
31     return *Result;
32   }
33 
34   static std::string format(llvm::StringRef Code, const FormatStyle &Style) {
35     return format(Code, 0, Code.size(), Style);
36   }
37 
38   static void verifyFormat(llvm::StringRef Code, const FormatStyle &Style) {
39     EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
40   }
41 
42   static void verifyFormat(llvm::StringRef Code) {
43     FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
44     Style.ColumnLimit = 60; // To make writing tests easier.
45     verifyFormat(Code, Style);
46   }
47 };
48 
49 TEST_F(FormatTestTextProto, KeepsTopLevelEntriesFittingALine) {
50   verifyFormat("field_a: OK field_b: OK field_c: OK field_d: OK field_e: OK");
51 }
52 
53 TEST_F(FormatTestTextProto, SupportsMessageFields) {
54   verifyFormat("msg_field: {}");
55 
56   verifyFormat("msg_field: { field_a: A }");
57 
58   verifyFormat("msg_field: { field_a: \"OK\" field_b: 123 }");
59 
60   verifyFormat("msg_field: {\n"
61                "  field_a: 1\n"
62                "  field_b: OK\n"
63                "  field_c: \"OK\"\n"
64                "  field_d: 123\n"
65                "  field_e: 23\n"
66                "}");
67 
68   verifyFormat("msg_field {}");
69 
70   verifyFormat("msg_field { field_a: A }");
71 
72   verifyFormat("msg_field { field_a: \"OK\" field_b: 123 }");
73 
74   verifyFormat("msg_field {\n"
75                "  field_a: 1\n"
76                "  field_b: OK\n"
77                "  field_c: \"OK\"\n"
78                "  field_d: 123\n"
79                "  field_e: 23.0\n"
80                "  field_f: false\n"
81                "  field_g: 'lala'\n"
82                "  field_h: 1234.567e-89\n"
83                "}");
84 
85   verifyFormat("msg_field: { msg_field { field_a: 1 } }");
86 
87   verifyFormat("id: \"ala.bala\"\n"
88                "item { type: ITEM_A rank: 1 score: 90.0 }\n"
89                "item { type: ITEM_B rank: 2 score: 70.5 }\n"
90                "item {\n"
91                "  type: ITEM_A\n"
92                "  rank: 3\n"
93                "  score: 20.0\n"
94                "  description: \"the third item has a description\"\n"
95                "}");
96 }
97 
98 TEST_F(FormatTestTextProto, AvoidsTopLevelBinPacking) {
99   verifyFormat("field_a: OK\n"
100                "field_b: OK\n"
101                "field_c: OK\n"
102                "field_d: OK\n"
103                "field_e: OK\n"
104                "field_f: OK");
105 
106   verifyFormat("field_a: OK\n"
107                "field_b: \"OK\"\n"
108                "field_c: \"OK\"\n"
109                "msg_field: { field_d: 123 }\n"
110                "field_e: OK\n"
111                "field_f: OK");
112 
113   verifyFormat("field_a: OK\n"
114                "field_b: \"OK\"\n"
115                "field_c: \"OK\"\n"
116                "msg_field: { field_d: 123 field_e: OK }");
117 
118   verifyFormat("a: {\n"
119                "  field_a: OK\n"
120                "  field_b { field_c: OK }\n"
121                "  field_d: OKOKOK\n"
122                "  field_e: OK\n"
123                "}");
124 
125   verifyFormat("field_a: OK,\n"
126                "field_b { field_c: OK },\n"
127                "field_d: OKOKOK,\n"
128                "field_e: OK");
129 }
130 
131 TEST_F(FormatTestTextProto, AddsNewlinesAfterTrailingComments) {
132   verifyFormat("field_a: OK  // Comment\n"
133                "field_b: 1");
134 
135   verifyFormat("field_a: OK\n"
136                "msg_field: {\n"
137                "  field_b: OK  // Comment\n"
138                "}");
139 
140   verifyFormat("field_a: OK\n"
141                "msg_field {\n"
142                "  field_b: OK  // Comment\n"
143                "}");
144 }
145 
146 TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
147   // Single-line tests
148   verifyFormat("msg_field <>");
149   verifyFormat("msg_field: <>");
150   verifyFormat("msg_field < field_a: OK >");
151   verifyFormat("msg_field: < field_a: 123 >");
152   verifyFormat("msg_field < field_a <> >");
153   verifyFormat("msg_field < field_a < field_b <> > >");
154   verifyFormat("msg_field: < field_a < field_b: <> > >");
155   verifyFormat("msg_field < field_a: OK, field_b: \"OK\" >");
156   verifyFormat("msg_field < field_a: OK field_b: <>, field_c: OK >");
157   verifyFormat("msg_field < field_a { field_b: 1 }, field_c: < f_d: 2 > >");
158   verifyFormat("msg_field: < field_a: OK, field_b: \"OK\" >");
159   verifyFormat("msg_field: < field_a: OK field_b: <>, field_c: OK >");
160   verifyFormat("msg_field: < field_a { field_b: 1 }, field_c: < fd_d: 2 > >");
161   verifyFormat("field_a: \"OK\", msg_field: < field_b: 123 >, field_c: {}");
162   verifyFormat("field_a < field_b: 1 >, msg_fid: < fiel_b: 123 >, field_c <>");
163   verifyFormat("field_a < field_b: 1 > msg_fied: < field_b: 123 > field_c <>");
164   verifyFormat("field < field < field: <> >, field <> > field: < field: 1 >");
165 
166   // Multiple lines tests
167   verifyFormat("msg_field <\n"
168                "  field_a: OK\n"
169                "  field_b: \"OK\"\n"
170                "  field_c: 1\n"
171                "  field_d: 12.5\n"
172                "  field_e: OK\n"
173                ">");
174 
175   verifyFormat("msg_field: <>\n"
176                "field_c: \"OK\",\n"
177                "msg_field: < field_d: 123 >\n"
178                "field_e: OK\n"
179                "msg_field: < field_d: 12 >");
180 
181   verifyFormat("field_a: OK,\n"
182                "field_b < field_c: OK >,\n"
183                "field_d: < 12.5 >,\n"
184                "field_e: OK");
185 
186   verifyFormat("field_a: OK\n"
187                "field_b < field_c: OK >\n"
188                "field_d: < 12.5 >\n"
189                "field_e: OKOKOK");
190 
191   verifyFormat("msg_field <\n"
192                "  field_a: OK,\n"
193                "  field_b < field_c: OK >,\n"
194                "  field_d: < 12.5 >,\n"
195                "  field_e: OK\n"
196                ">");
197 
198   verifyFormat("msg_field <\n"
199                "  field_a: < field: OK >,\n"
200                "  field_b < field_c: OK >,\n"
201                "  field_d: < 12.5 >,\n"
202                "  field_e: OK,\n"
203                ">");
204 
205   verifyFormat("msg_field: <\n"
206                "  field_a: \"OK\"\n"
207                "  msg_field: { field_b: OK }\n"
208                "  field_g: OK\n"
209                "  field_g: OK\n"
210                "  field_g: OK\n"
211                ">");
212 
213   verifyFormat("field_a {\n"
214                "  field_d: ok\n"
215                "  field_b: < field_c: 1 >\n"
216                "  field_d: ok\n"
217                "  field_d: ok\n"
218                "}");
219 
220   verifyFormat("field_a: {\n"
221                "  field_d: ok\n"
222                "  field_b: < field_c: 1 >\n"
223                "  field_d: ok\n"
224                "  field_d: ok\n"
225                "}");
226 
227   verifyFormat("field_a: < f1: 1, f2: <> >\n"
228                "field_b <\n"
229                "  field_b1: <>\n"
230                "  field_b2: ok,\n"
231                "  field_b3: <\n"
232                "    field_x {}  // Comment\n"
233                "    field_y: { field_z: 1 }\n"
234                "    field_w: ok\n"
235                "  >\n"
236                "  field {\n"
237                "    field_x <>  // Comment\n"
238                "    field_y: < field_z: 1 >\n"
239                "    field_w: ok\n"
240                "    msg_field: <\n"
241                "      field: <>\n"
242                "      field: < field: 1 >\n"
243                "      field: < field: 2 >\n"
244                "      field: < field: 3 >\n"
245                "      field: < field: 4 >\n"
246                "      field: ok\n"
247                "    >\n"
248                "  }\n"
249                ">\n"
250                "field: OK,\n"
251                "field_c < field < field <> > >");
252 
253   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
254                "head_id: 1\n"
255                "data < key: value >");
256 
257   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
258                "head_id: 1\n"
259                "data < key: value >\n"
260                "tail_id: 2");
261 
262   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
263                "head_id: 1\n"
264                "data < key: value >\n"
265                "data { key: value }");
266 
267   verifyFormat("app {\n"
268                "  app_id: 'com.javax.swing.salsa.latino'\n"
269                "  head_id: 1\n"
270                "  data < key: value >\n"
271                "}");
272 
273   verifyFormat("app: {\n"
274                "  app_id: 'com.javax.swing.salsa.latino'\n"
275                "  head_id: 1\n"
276                "  data < key: value >\n"
277                "}");
278 
279   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
280                "headheadheadheadheadhead_id: 1\n"
281                "product_data { product { 1 } }");
282 
283   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
284                "headheadheadheadheadhead_id: 1\n"
285                "product_data < product { 1 } >");
286 
287   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
288                "headheadheadheadheadhead_id: 1\n"
289                "product_data < product < 1 > >");
290 
291   verifyFormat("app <\n"
292                "  app_id: 'com.javax.swing.salsa.latino'\n"
293                "  headheadheadheadheadhead_id: 1\n"
294                "  product_data < product { 1 } >\n"
295                ">");
296 
297   verifyFormat("dcccwrnfioeruvginerurneitinfo {\n"
298                "  exte3nsionrnfvui { key: value }\n"
299                "}");
300 }
301 
302 TEST_F(FormatTestTextProto, DiscardsUnbreakableTailIfCanBreakAfter) {
303   // The two closing braces count towards the string UnbreakableTailLength, but
304   // since we have broken after the corresponding opening braces, we don't
305   // consider that length for string breaking.
306   verifyFormat(
307       "foo: {\n"
308       "  bar: {\n"
309       "    text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
310       "  }\n"
311       "}");
312 }
313 
314 TEST_F(FormatTestTextProto, KeepsLongStringLiteralsOnSameLine) {
315   verifyFormat(
316       "foo: {\n"
317       "  text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaaaa\"\n"
318       "}");
319 }
320 
321 TEST_F(FormatTestTextProto, KeepsCommentsIndentedInList) {
322   verifyFormat("aaaaaaaaaa: 100\n"
323                "bbbbbbbbbbbbbbbbbbbbbbbbbbb: 200\n"
324                "# Single line comment for stuff here.\n"
325                "cccccccccccccccccccccccc: 3849\n"
326                "# Multiline comment for stuff here.\n"
327                "# Multiline comment for stuff here.\n"
328                "# Multiline comment for stuff here.\n"
329                "cccccccccccccccccccccccc: 3849");
330 }
331 
332 TEST_F(FormatTestTextProto, FormatsExtensions) {
333   verifyFormat("[type] { key: value }");
334   verifyFormat("[type] {\n"
335                "  keyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: value\n"
336                "}");
337   verifyFormat("[type.type] { key: value }");
338   verifyFormat("[type.type] < key: value >");
339   verifyFormat("[type.type/type.type] { key: value }");
340   verifyFormat("msg {\n"
341                "  [type.type] { key: value }\n"
342                "}");
343   verifyFormat("msg {\n"
344                "  [type.type] {\n"
345                "    keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
346                "  }\n"
347                "}");
348   verifyFormat("key: value\n"
349                "[a.b] { key: value }");
350   verifyFormat("msg: <\n"
351                "  key: value\n"
352                "  [a.b.c/d.e]: < key: value >\n"
353                "  [f.g]: <\n"
354                "    key: valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n"
355                "    key: {}\n"
356                "  >\n"
357                "  key {}\n"
358                "  [h.i.j] < key: value >\n"
359                "  [a]: {\n"
360                "    [b.c]: {}\n"
361                "    [d] <>\n"
362                "    [e/f]: 1\n"
363                "  }\n"
364                ">");
365   verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
366                "     .longg.longlong] { key: value }");
367   verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
368                "     .longg.longlong] {\n"
369                "  key: value\n"
370                "  key: value\n"
371                "  key: value\n"
372                "  key: value\n"
373                "}");
374   verifyFormat("[longg.long.long.long.long.long.long.long.long.long\n"
375                "     .long/longg.longlong] { key: value }");
376   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
377                " bbbbbbbbbbbbbb] { key: value }");
378   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
379                "] { key: value }");
380   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
381                "] {\n"
382                "  [type.type] {\n"
383                "    keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
384                "  }\n"
385                "}");
386   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
387                " bbbbbbb] {\n"
388                "  [type.type] {\n"
389                "    keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
390                "  }\n"
391                "}");
392   verifyFormat(
393       "aaaaaaaaaaaaaaa {\n"
394       "  bbbbbb {\n"
395       "    [a.b/cy] {\n"
396       "      eeeeeeeeeeeee: \"The lazy coo cat jumps over the lazy hot dog\"\n"
397       "    }\n"
398       "  }\n"
399       "}");
400 }
401 
402 TEST_F(FormatTestTextProto, NoSpaceAfterPercent) {
403   verifyFormat("key: %d");
404 }
405 
406 TEST_F(FormatTestTextProto, FormatsRepeatedListInitializers) {
407   verifyFormat("keys: []");
408   verifyFormat("keys: [ 1 ]");
409   verifyFormat("keys: [ 'ala', 'bala' ]");
410   verifyFormat("keys:\n"
411                "    [ 'ala', 'bala', 'porto', 'kala', 'too', 'long', 'ng' ]");
412   verifyFormat("key: item\n"
413                "keys: [\n"
414                "  'ala',\n"
415                "  'bala',\n"
416                "  'porto',\n"
417                "  'kala',\n"
418                "  'too',\n"
419                "  'long',\n"
420                "  'long',\n"
421                "  'long'\n"
422                "]\n"
423                "key: item\n"
424                "msg {\n"
425                "  key: item\n"
426                "  keys: [\n"
427                "    'ala',\n"
428                "    'bala',\n"
429                "    'porto',\n"
430                "    'kala',\n"
431                "    'too',\n"
432                "    'long',\n"
433                "    'long'\n"
434                "  ]\n"
435                "}\n"
436                "key: value"
437                );
438   FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
439   Style.ColumnLimit = 60; // To make writing tests easier.
440   Style.Cpp11BracedListStyle = true;
441   verifyFormat("keys: [1]", Style);
442 }
443 
444 TEST_F(FormatTestTextProto, AcceptsOperatorAsKey) {
445   verifyFormat("aaaaaaaaaaa: <\n"
446                "  bbbbbbbbb: <\n"
447                "    ccccccccccccccccccccccc: <\n"
448                "      operator: 1\n"
449                "      operator: 2\n"
450                "      operator { key: value }\n"
451                "    >\n"
452                "  >\n"
453                ">");
454 }
455 
456 TEST_F(FormatTestTextProto, BreaksConsecutiveStringLiterals) {
457   verifyFormat("ala: \"str1\"\n"
458                "     \"str2\"\n");
459 }
460 
461 } // end namespace tooling
462 } // end namespace clang
463