xref: /llvm-project/clang/unittests/Format/FormatTestTextProto.cpp (revision f28347ea7d082d629bdb29a6511b8cc66a6716ef)
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   enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete };
23 
24   static std::string format(llvm::StringRef Code, unsigned Offset,
25                             unsigned Length, const FormatStyle &Style,
26                             StatusCheck CheckComplete = SC_ExpectComplete) {
27     DEBUG(llvm::errs() << "---\n");
28     DEBUG(llvm::errs() << Code << "\n\n");
29     std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
30     FormattingAttemptStatus Status;
31     tooling::Replacements Replaces =
32         reformat(Style, Code, Ranges, "<stdin>", &Status);
33     bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
34     EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
35         << Code << "\n\n";
36     auto Result = applyAllReplacements(Code, Replaces);
37     EXPECT_TRUE(static_cast<bool>(Result));
38     DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
39     return *Result;
40   }
41 
42   static std::string format(llvm::StringRef Code, const FormatStyle &Style) {
43     return format(Code, 0, Code.size(), Style);
44   }
45 
46   static void verifyFormat(llvm::StringRef Code, const FormatStyle &Style) {
47     EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
48     EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
49   }
50 
51   static void verifyFormat(llvm::StringRef Code) {
52     FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
53     Style.ColumnLimit = 60; // To make writing tests easier.
54     verifyFormat(Code, Style);
55   }
56 
57   static void verifyIncompleteFormat(llvm::StringRef Code) {
58     FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
59     EXPECT_EQ(Code.str(),
60               format(Code, 0, Code.size(), Style, SC_ExpectIncomplete));
61   }
62 };
63 
64 TEST_F(FormatTestTextProto, KeepsTopLevelEntriesFittingALine) {
65   verifyFormat("field_a: OK field_b: OK field_c: OK field_d: OK field_e: OK");
66 }
67 
68 TEST_F(FormatTestTextProto, SupportsMessageFields) {
69   verifyFormat("msg_field: {}");
70 
71   verifyFormat("msg_field: { field_a: A }");
72 
73   verifyFormat("msg_field: { field_a: \"OK\" field_b: 123 }");
74 
75   verifyFormat("msg_field: {\n"
76                "  field_a: 1\n"
77                "  field_b: OK\n"
78                "  field_c: \"OK\"\n"
79                "  field_d: 123\n"
80                "  field_e: 23\n"
81                "}");
82 
83   verifyFormat("msg_field {}");
84 
85   verifyFormat("msg_field { field_a: A }");
86 
87   verifyFormat("msg_field { field_a: \"OK\" field_b: 123 }");
88 
89   verifyFormat("msg_field {\n"
90                "  field_a: 1\n"
91                "  field_b: OK\n"
92                "  field_c: \"OK\"\n"
93                "  field_d: 123\n"
94                "  field_e: 23.0\n"
95                "  field_f: false\n"
96                "  field_g: 'lala'\n"
97                "  field_h: 1234.567e-89\n"
98                "}");
99 
100   verifyFormat("msg_field: { msg_field { field_a: 1 } }");
101 
102   verifyFormat("id: \"ala.bala\"\n"
103                "item { type: ITEM_A rank: 1 score: 90.0 }\n"
104                "item { type: ITEM_B rank: 2 score: 70.5 }\n"
105                "item {\n"
106                "  type: ITEM_A\n"
107                "  rank: 3\n"
108                "  score: 20.0\n"
109                "  description: \"the third item has a description\"\n"
110                "}");
111 }
112 
113 TEST_F(FormatTestTextProto, AvoidsTopLevelBinPacking) {
114   verifyFormat("field_a: OK\n"
115                "field_b: OK\n"
116                "field_c: OK\n"
117                "field_d: OK\n"
118                "field_e: OK\n"
119                "field_f: OK");
120 
121   verifyFormat("field_a: OK\n"
122                "field_b: \"OK\"\n"
123                "field_c: \"OK\"\n"
124                "msg_field: { field_d: 123 }\n"
125                "field_e: OK\n"
126                "field_f: OK");
127 
128   verifyFormat("field_a: OK\n"
129                "field_b: \"OK\"\n"
130                "field_c: \"OK\"\n"
131                "msg_field: { field_d: 123 field_e: OK }");
132 
133   verifyFormat("a: {\n"
134                "  field_a: OK\n"
135                "  field_b { field_c: OK }\n"
136                "  field_d: OKOKOK\n"
137                "  field_e: OK\n"
138                "}");
139 
140   verifyFormat("field_a: OK,\n"
141                "field_b { field_c: OK },\n"
142                "field_d: OKOKOK,\n"
143                "field_e: OK");
144 }
145 
146 TEST_F(FormatTestTextProto, AddsNewlinesAfterTrailingComments) {
147   verifyFormat("field_a: OK  // Comment\n"
148                "field_b: 1");
149 
150   verifyFormat("field_a: OK\n"
151                "msg_field: {\n"
152                "  field_b: OK  // Comment\n"
153                "}");
154 
155   verifyFormat("field_a: OK\n"
156                "msg_field {\n"
157                "  field_b: OK  // Comment\n"
158                "}");
159 }
160 
161 TEST_F(FormatTestTextProto, ImplicitStringLiteralConcatenation) {
162   verifyFormat("field_a: 'aaaaa'\n"
163                "         'bbbbb'");
164   verifyFormat("field_a: \"aaaaa\"\n"
165                "         \"bbbbb\"");
166   FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
167   Style.AlwaysBreakBeforeMultilineStrings = true;
168   verifyFormat("field_a:\n"
169                "    'aaaaa'\n"
170                "    'bbbbb'",
171                Style);
172   verifyFormat("field_a:\n"
173                "    \"aaaaa\"\n"
174                "    \"bbbbb\"",
175                Style);
176 }
177 
178 TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) {
179   // Single-line tests
180   verifyFormat("msg_field <>");
181   verifyFormat("msg_field: <>");
182   verifyFormat("msg_field < field_a: OK >");
183   verifyFormat("msg_field: < field_a: 123 >");
184   verifyFormat("msg_field < field_a <> >");
185   verifyFormat("msg_field < field_a < field_b <> > >");
186   verifyFormat("msg_field: < field_a < field_b: <> > >");
187   verifyFormat("msg_field < field_a: OK, field_b: \"OK\" >");
188   verifyFormat("msg_field < field_a: OK field_b: <>, field_c: OK >");
189   verifyFormat("msg_field < field_a { field_b: 1 }, field_c: < f_d: 2 > >");
190   verifyFormat("msg_field: < field_a: OK, field_b: \"OK\" >");
191   verifyFormat("msg_field: < field_a: OK field_b: <>, field_c: OK >");
192   verifyFormat("msg_field: < field_a { field_b: 1 }, field_c: < fd_d: 2 > >");
193   verifyFormat("field_a: \"OK\", msg_field: < field_b: 123 >, field_c: {}");
194   verifyFormat("field_a < field_b: 1 >, msg_fid: < fiel_b: 123 >, field_c <>");
195   verifyFormat("field_a < field_b: 1 > msg_fied: < field_b: 123 > field_c <>");
196   verifyFormat("field < field < field: <> >, field <> > field: < field: 1 >");
197 
198   // Multiple lines tests
199   verifyFormat("msg_field <\n"
200                "  field_a: OK\n"
201                "  field_b: \"OK\"\n"
202                "  field_c: 1\n"
203                "  field_d: 12.5\n"
204                "  field_e: OK\n"
205                ">");
206 
207   verifyFormat("msg_field: <>\n"
208                "field_c: \"OK\",\n"
209                "msg_field: < field_d: 123 >\n"
210                "field_e: OK\n"
211                "msg_field: < field_d: 12 >");
212 
213   verifyFormat("field_a: OK,\n"
214                "field_b < field_c: OK >,\n"
215                "field_d: < 12.5 >,\n"
216                "field_e: OK");
217 
218   verifyFormat("field_a: OK\n"
219                "field_b < field_c: OK >\n"
220                "field_d: < 12.5 >\n"
221                "field_e: OKOKOK");
222 
223   verifyFormat("msg_field <\n"
224                "  field_a: OK,\n"
225                "  field_b < field_c: OK >,\n"
226                "  field_d: < 12.5 >,\n"
227                "  field_e: OK\n"
228                ">");
229 
230   verifyFormat("msg_field <\n"
231                "  field_a: < field: OK >,\n"
232                "  field_b < field_c: OK >,\n"
233                "  field_d: < 12.5 >,\n"
234                "  field_e: OK,\n"
235                ">");
236 
237   verifyFormat("msg_field: <\n"
238                "  field_a: \"OK\"\n"
239                "  msg_field: { field_b: OK }\n"
240                "  field_g: OK\n"
241                "  field_g: OK\n"
242                "  field_g: OK\n"
243                ">");
244 
245   verifyFormat("field_a {\n"
246                "  field_d: ok\n"
247                "  field_b: < field_c: 1 >\n"
248                "  field_d: ok\n"
249                "  field_d: ok\n"
250                "}");
251 
252   verifyFormat("field_a: {\n"
253                "  field_d: ok\n"
254                "  field_b: < field_c: 1 >\n"
255                "  field_d: ok\n"
256                "  field_d: ok\n"
257                "}");
258 
259   verifyFormat("field_a: < f1: 1, f2: <> >\n"
260                "field_b <\n"
261                "  field_b1: <>\n"
262                "  field_b2: ok,\n"
263                "  field_b3: <\n"
264                "    field_x {}  // Comment\n"
265                "    field_y: { field_z: 1 }\n"
266                "    field_w: ok\n"
267                "  >\n"
268                "  field {\n"
269                "    field_x <>  // Comment\n"
270                "    field_y: < field_z: 1 >\n"
271                "    field_w: ok\n"
272                "    msg_field: <\n"
273                "      field: <>\n"
274                "      field: < field: 1 >\n"
275                "      field: < field: 2 >\n"
276                "      field: < field: 3 >\n"
277                "      field: < field: 4 >\n"
278                "      field: ok\n"
279                "    >\n"
280                "  }\n"
281                ">\n"
282                "field: OK,\n"
283                "field_c < field < field <> > >");
284 
285   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
286                "head_id: 1\n"
287                "data < key: value >");
288 
289   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
290                "head_id: 1\n"
291                "data < key: value >\n"
292                "tail_id: 2");
293 
294   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
295                "head_id: 1\n"
296                "data < key: value >\n"
297                "data { key: value }");
298 
299   verifyFormat("app {\n"
300                "  app_id: 'com.javax.swing.salsa.latino'\n"
301                "  head_id: 1\n"
302                "  data < key: value >\n"
303                "}");
304 
305   verifyFormat("app: {\n"
306                "  app_id: 'com.javax.swing.salsa.latino'\n"
307                "  head_id: 1\n"
308                "  data < key: value >\n"
309                "}");
310 
311   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
312                "headheadheadheadheadhead_id: 1\n"
313                "product_data { product { 1 } }");
314 
315   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
316                "headheadheadheadheadhead_id: 1\n"
317                "product_data < product { 1 } >");
318 
319   verifyFormat("app_id: 'com.javax.swing.salsa.latino'\n"
320                "headheadheadheadheadhead_id: 1\n"
321                "product_data < product < 1 > >");
322 
323   verifyFormat("app <\n"
324                "  app_id: 'com.javax.swing.salsa.latino'\n"
325                "  headheadheadheadheadhead_id: 1\n"
326                "  product_data < product { 1 } >\n"
327                ">");
328 
329   verifyFormat("dcccwrnfioeruvginerurneitinfo {\n"
330                "  exte3nsionrnfvui { key: value }\n"
331                "}");
332 }
333 
334 TEST_F(FormatTestTextProto, DiscardsUnbreakableTailIfCanBreakAfter) {
335   // The two closing braces count towards the string UnbreakableTailLength, but
336   // since we have broken after the corresponding opening braces, we don't
337   // consider that length for string breaking.
338   verifyFormat(
339       "foo: {\n"
340       "  bar: {\n"
341       "    text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
342       "  }\n"
343       "}");
344 }
345 
346 TEST_F(FormatTestTextProto, KeepsLongStringLiteralsOnSameLine) {
347   verifyFormat(
348       "foo: {\n"
349       "  text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaaaa\"\n"
350       "}");
351 }
352 
353 TEST_F(FormatTestTextProto, KeepsCommentsIndentedInList) {
354   verifyFormat("aaaaaaaaaa: 100\n"
355                "bbbbbbbbbbbbbbbbbbbbbbbbbbb: 200\n"
356                "# Single line comment for stuff here.\n"
357                "cccccccccccccccccccccccc: 3849\n"
358                "# Multiline comment for stuff here.\n"
359                "# Multiline comment for stuff here.\n"
360                "# Multiline comment for stuff here.\n"
361                "cccccccccccccccccccccccc: 3849");
362 }
363 
364 TEST_F(FormatTestTextProto, FormatsExtensions) {
365   verifyFormat("[type] { key: value }");
366   verifyFormat("[type] {\n"
367                "  keyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: value\n"
368                "}");
369   verifyFormat("[type.type] { key: value }");
370   verifyFormat("[type.type] < key: value >");
371   verifyFormat("[type.type/type.type] { key: value }");
372   verifyFormat("msg {\n"
373                "  [type.type] { key: value }\n"
374                "}");
375   verifyFormat("msg {\n"
376                "  [type.type] {\n"
377                "    keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
378                "  }\n"
379                "}");
380   verifyFormat("key: value\n"
381                "[a.b] { key: value }");
382   verifyFormat("msg: <\n"
383                "  key: value\n"
384                "  [a.b.c/d.e]: < key: value >\n"
385                "  [f.g]: <\n"
386                "    key: valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n"
387                "    key: {}\n"
388                "  >\n"
389                "  key {}\n"
390                "  [h.i.j] < key: value >\n"
391                "  [a]: {\n"
392                "    [b.c]: {}\n"
393                "    [d] <>\n"
394                "    [e/f]: 1\n"
395                "  }\n"
396                ">");
397   verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
398                "     .longg.longlong] { key: value }");
399   verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
400                "     .longg.longlong] {\n"
401                "  key: value\n"
402                "  key: value\n"
403                "  key: value\n"
404                "  key: value\n"
405                "}");
406   verifyFormat("[longg.long.long.long.long.long.long.long.long.long\n"
407                "     .long/longg.longlong] { key: value }");
408   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
409                " bbbbbbbbbbbbbb] { key: value }");
410   // These go over the column limit intentionally, since the alternative
411   // [aa..a\n] is worse.
412   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n"
413                "  key: value\n"
414                "}");
415   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] {\n"
416                "  [type.type] {\n"
417                "    keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
418                "  }\n"
419                "}");
420   verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
421                " bbbbbbb] {\n"
422                "  [type.type] {\n"
423                "    keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
424                "  }\n"
425                "}");
426   verifyFormat(
427       "aaaaaaaaaaaaaaa {\n"
428       "  bbbbbb {\n"
429       "    [a.b/cy] {\n"
430       "      eeeeeeeeeeeee: \"The lazy coo cat jumps over the lazy hot dog\"\n"
431       "    }\n"
432       "  }\n"
433       "}");
434 }
435 
436 TEST_F(FormatTestTextProto, SpacesAroundPercents) {
437   verifyFormat("key: %d");
438   verifyFormat("key: 0x%04x");
439   verifyFormat("key: \"%d %d\"");
440 }
441 
442 TEST_F(FormatTestTextProto, FormatsRepeatedListInitializers) {
443   verifyFormat("keys: []");
444   verifyFormat("keys: [ 1 ]");
445   verifyFormat("keys: [ 'ala', 'bala' ]");
446   verifyFormat("keys:\n"
447                "    [ 'ala', 'bala', 'porto', 'kala', 'too', 'long', 'ng' ]");
448   verifyFormat("key: item\n"
449                "keys: [\n"
450                "  'ala',\n"
451                "  'bala',\n"
452                "  'porto',\n"
453                "  'kala',\n"
454                "  'too',\n"
455                "  'long',\n"
456                "  'long',\n"
457                "  'long'\n"
458                "]\n"
459                "key: item\n"
460                "msg {\n"
461                "  key: item\n"
462                "  keys: [\n"
463                "    'ala',\n"
464                "    'bala',\n"
465                "    'porto',\n"
466                "    'kala',\n"
467                "    'too',\n"
468                "    'long',\n"
469                "    'long'\n"
470                "  ]\n"
471                "}\n"
472                "key: value"
473                );
474   FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
475   Style.ColumnLimit = 60; // To make writing tests easier.
476   Style.Cpp11BracedListStyle = true;
477   verifyFormat("keys: [1]", Style);
478 }
479 
480 TEST_F(FormatTestTextProto, AcceptsOperatorAsKey) {
481   verifyFormat("aaaaaaaaaaa: <\n"
482                "  bbbbbbbbb: <\n"
483                "    ccccccccccccccccccccccc: <\n"
484                "      operator: 1\n"
485                "      operator: 2\n"
486                "      operator { key: value }\n"
487                "    >\n"
488                "  >\n"
489                ">");
490 }
491 
492 TEST_F(FormatTestTextProto, BreaksConsecutiveStringLiterals) {
493   verifyFormat("ala: \"str1\"\n"
494                "     \"str2\"\n");
495 }
496 
497 TEST_F(FormatTestTextProto, PutsMultipleEntriesInExtensionsOnNewlines) {
498   FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
499   verifyFormat("pppppppppp: {\n"
500                "  ssssss: \"http://example.com/blahblahblah\"\n"
501                "  ppppppp: \"sssss/MMMMMMMMMMMM\"\n"
502                "  [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] { begin: 24 end: 252 }\n"
503                "  [ns.sssss.eeeeeeeee.eeeeeeeeeeeeeee] {\n"
504                "    begin: 24\n"
505                "    end: 252\n"
506                "    key: value\n"
507                "    key: value\n"
508                "  }\n"
509                "}", Style);
510 }
511 
512 TEST_F(FormatTestTextProto, IncompleteFormat) {
513   verifyIncompleteFormat("data {");
514   verifyIncompleteFormat("data <");
515   verifyIncompleteFormat("data [");
516   verifyIncompleteFormat("data: {");
517   verifyIncompleteFormat("data: <");
518   verifyIncompleteFormat("data: [");
519   verifyIncompleteFormat("key:");
520   verifyIncompleteFormat("key:}");
521   verifyIncompleteFormat("key: ]");
522   verifyIncompleteFormat("key: >");
523   verifyIncompleteFormat(": value");
524   verifyIncompleteFormat(": {}");
525   verifyIncompleteFormat(": <>");
526   verifyIncompleteFormat(": []");
527   verifyIncompleteFormat("}\n"
528                          "key: value");
529   verifyIncompleteFormat("]\n"
530                          "key: value");
531   verifyIncompleteFormat("> key: value");
532   verifyIncompleteFormat("data { key: {");
533   verifyIncompleteFormat("data < key: [");
534   verifyIncompleteFormat("data [ key: {");
535   verifyIncompleteFormat("> key: value {");
536   verifyIncompleteFormat("> key: [");
537   verifyIncompleteFormat("}\n"
538                          "key: {");
539   verifyIncompleteFormat("data { key: 1 id:");
540   verifyIncompleteFormat("}\n"
541                          "key {");
542   verifyIncompleteFormat("> <");
543 }
544 
545 } // end namespace tooling
546 } // end namespace clang
547