xref: /llvm-project/clang/unittests/Format/FormatTestProto.cpp (revision c9a918c560aa2f524815dfb4ec68c3b24f3b211a)
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 FormatTestProto : 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) {
35     FormatStyle Style = getGoogleStyle(FormatStyle::LK_Proto);
36     Style.ColumnLimit = 60; // To make writing tests easier.
37     return format(Code, 0, Code.size(), Style);
38   }
39 
40   static void verifyFormat(llvm::StringRef Code) {
41     EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
42     EXPECT_EQ(Code.str(), format(test::messUp(Code)));
43   }
44 };
45 
46 TEST_F(FormatTestProto, FormatsMessages) {
47   verifyFormat("message SomeMessage {\n"
48                "  required int32 field1 = 1;\n"
49                "}");
50   verifyFormat("message SomeMessage {\n"
51                "  required .absolute.Reference field1 = 1;\n"
52                "}");
53   verifyFormat("message SomeMessage {\n"
54                "  required int32 field1 = 1;\n"
55                "  optional string field2 = 2 [default = \"2\"]\n"
56                "}");
57 
58   verifyFormat("message SomeMessage {\n"
59                "  optional really.really.long.qualified.type.aaa.aaaaaaa\n"
60                "      fiiiiiiiiiiiiiiiiiiiiiiiiield = 1;\n"
61                "  optional\n"
62                "      really.really.long.qualified.type.aaa.aaaaaaa.aaaaaaaa\n"
63                "          another_fiiiiiiiiiiiiiiiiiiiiield = 2;\n"
64                "}");
65   verifyFormat("message SomeMessage {\n"
66                "  map<string, Project> projects = 1;\n"
67                "  optional map<string, int32> size_projects = 2;\n"
68                "  map<int, really.really.really.long.qualified.type.nameeee>\n"
69                "      projects = 3;\n"
70                "  map<int, really.really.really.really.long.qualified.type\n"
71                "               .nameeee> projects = 4;\n"
72                "  map<int,\n"
73                "      reallyreallyreallyreallyreallyreallyreallylongname>\n"
74                "      projects = 5;\n"
75                "  map<int, Project>\n"
76                "      longlonglonglonglonglonglonglonglonglongonglon = 6;\n"
77                "  map<releleallyreallyreallyreallyreallyreallyreallylongname,\n"
78                "      int> projects = 7;\n"
79                "  map<releleallyreallyreallyreallyreallyreallyreallylongname,\n"
80                "      releleallyreallyreallyreallyreallyreallyreallylongname>\n"
81                "      releleallyreallyreallyreallyreallyreallyreallylongnam =\n"
82                "          8;\n"
83                "  map<relele.llyreal.yreallyr.allyreally.eallyreal\n"
84                "          .sauenirylongname,\n"
85                "      really.really.really.really.long.qualified.type\n"
86                "          .nameeee> projects = 9;\n"
87                "}");
88 }
89 
90 TEST_F(FormatTestProto, KeywordsInOtherLanguages) {
91   verifyFormat("optional string operator = 1;");
92 }
93 
94 TEST_F(FormatTestProto, FormatsEnums) {
95   verifyFormat("enum Type {\n"
96                "  UNKNOWN = 0;\n"
97                "  TYPE_A = 1;\n"
98                "  TYPE_B = 2;\n"
99                "};");
100   verifyFormat("enum Type {\n"
101                "  UNKNOWN = 0 [(some_options) = { a: aa, b: bb }];\n"
102                "};");
103   verifyFormat("enum Type {\n"
104                "  UNKNOWN = 0 [(some_options) = {\n"
105                "    a: aa,  // wrap\n"
106                "    b: bb\n"
107                "  }];\n"
108                "};");
109 }
110 
111 TEST_F(FormatTestProto, UnderstandsReturns) {
112   verifyFormat("rpc Search(SearchRequest) returns (SearchResponse);");
113 }
114 
115 TEST_F(FormatTestProto, MessageFieldAttributes) {
116   verifyFormat("optional string test = 1 [default = \"test\"];");
117   verifyFormat("optional bool a = 1 [default = true, deprecated = true];");
118   verifyFormat("optional LongMessageType long_proto_field = 1 [\n"
119                "  default = REALLY_REALLY_LONG_CONSTANT_VALUE,\n"
120                "  deprecated = true\n"
121                "];");
122   verifyFormat("optional LongMessageType long_proto_field = 1\n"
123                "    [default = REALLY_REALLY_LONG_CONSTANT_VALUE];");
124   verifyFormat("repeated double value = 1\n"
125                "    [(aaaaaaa.aaaaaaaaa) = { aaaaaaaaaaaaaaaaa: AAAAAAAA }];");
126   verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
127                "  aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
128                "  bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
129                "}];");
130   verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
131                "  aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
132                "  bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
133                "}];");
134   verifyFormat("repeated double value = 1 [\n"
135                "  (aaaaaaa.aaaaaaaaa) = {\n"
136                "    aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
137                "    bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
138                "  },\n"
139                "  (bbbbbbb.bbbbbbbbb) = {\n"
140                "    aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
141                "    bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
142                "  }\n"
143                "];");
144   verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
145                "  type: \"AAAAAAAAAA\"\n"
146                "  is: \"AAAAAAAAAA\"\n"
147                "  or: \"BBBBBBBBBB\"\n"
148                "}];");
149   verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
150                "  aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
151                "  bbbbbbb: BBBB,\n"
152                "  bbbb: BBB\n"
153                "}];");
154   verifyFormat("optional AAA aaa = 1 [\n"
155                "  foo = {\n"
156                "    key: 'a'  //\n"
157                "  },\n"
158                "  bar = {\n"
159                "    key: 'a'  //\n"
160                "  }\n"
161                "];");
162   verifyFormat("optional string test = 1 [default = \"test\"\n"
163                "                                    \"test\"];");
164   verifyFormat("optional Aaaaaaaa aaaaaaaa = 12 [\n"
165                "  (aaa) = aaaa,\n"
166                "  (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
167                "    aaaaaaaaaaaaaaaaa: true,\n"
168                "    aaaaaaaaaaaaaaaa: true\n"
169                "  }\n"
170                "];");
171   verifyFormat("extensions 20 [(proto2.type) = 'Aaaa.bbbb'];");
172   verifyFormat("extensions 20\n"
173                "    [(proto3.type) = 'Aaaa.bbbb', (aaa.Aaa) = 'aaa.bbb'];");
174   verifyFormat("extensions 123 [\n"
175                "  (aaa) = aaaa,\n"
176                "  (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
177                "    aaaaaaaaaaaaaaaaa: true,\n"
178                "    aaaaaaaaaaaaaaaa: true\n"
179                "  }\n"
180                "];");
181 }
182 
183 TEST_F(FormatTestProto, DoesntWrapFileOptions) {
184   EXPECT_EQ(
185       "option java_package = "
186       "\"some.really.long.package.that.exceeds.the.column.limit\";",
187       format("option    java_package   =    "
188              "\"some.really.long.package.that.exceeds.the.column.limit\";"));
189 }
190 
191 TEST_F(FormatTestProto, FormatsOptions) {
192   verifyFormat("option (MyProto.options) = {\n"
193                "  field_a: OK\n"
194                "  field_b: \"OK\"\n"
195                "  field_c: \"OK\"\n"
196                "  msg_field: { field_d: 123 }\n"
197                "};");
198   verifyFormat("option (MyProto.options) = {\n"
199                "  field_a: OK\n"
200                "  field_b: \"OK\"\n"
201                "  field_c: \"OK\"\n"
202                "  msg_field: { field_d: 123 field_e: OK }\n"
203                "};");
204   verifyFormat("option (MyProto.options) = {\n"
205                "  field_a: OK  // Comment\n"
206                "  field_b: \"OK\"\n"
207                "  field_c: \"OK\"\n"
208                "  msg_field: { field_d: 123 }\n"
209                "};");
210   verifyFormat("option (MyProto.options) = {\n"
211                "  field_c: \"OK\"\n"
212                "  msg_field { field_d: 123 }\n"
213                "};");
214   verifyFormat("option (MyProto.options) = {\n"
215                "  field_a: OK\n"
216                "  field_b { field_c: OK }\n"
217                "  field_d: OKOKOK\n"
218                "  field_e: OK\n"
219                "}");
220 
221   // Support syntax with <> instead of {}.
222   verifyFormat("option (MyProto.options) = {\n"
223                "  field_c: \"OK\",\n"
224                "  msg_field: < field_d: 123 >\n"
225                "  empty: <>\n"
226                "  empty <>\n"
227                "};");
228 
229   verifyFormat("option (MyProto.options) = {\n"
230                "  field_a: OK\n"
231                "  field_b < field_c: OK >\n"
232                "  field_d: OKOKOK\n"
233                "  field_e: OK\n"
234                "}");
235 
236   verifyFormat("option (MyProto.options) = {\n"
237                "  msg_field: <>\n"
238                "  field_c: \"OK\",\n"
239                "  msg_field: < field_d: 123 >\n"
240                "  field_e: OK\n"
241                "  msg_field: < field_d: 12 >\n"
242                "};");
243 
244   verifyFormat("option (MyProto.options) = <\n"
245                "  field_a: OK\n"
246                "  field_b: \"OK\"\n"
247                "  field_c: 1\n"
248                "  field_d: 12.5\n"
249                "  field_e: OK\n"
250                ">;");
251 
252   verifyFormat("option (MyProto.options) = <\n"
253                "  field_a: OK,\n"
254                "  field_b: \"OK\",\n"
255                "  field_c: 1,\n"
256                "  field_d: 12.5,\n"
257                "  field_e: OK,\n"
258                ">;");
259 
260   verifyFormat("option (MyProto.options) = <\n"
261                "  field_a: \"OK\"\n"
262                "  msg_field: { field_b: OK }\n"
263                "  field_g: OK\n"
264                "  field_g: OK\n"
265                "  field_g: OK\n"
266                ">;");
267 
268   verifyFormat("option (MyProto.options) = <\n"
269                "  field_a: \"OK\"\n"
270                "  msg_field <\n"
271                "    field_b: OK\n"
272                "    field_c: OK\n"
273                "    field_d: OK\n"
274                "    field_e: OK\n"
275                "    field_f: OK\n"
276                "  >\n"
277                "  field_g: OK\n"
278                ">;");
279 
280   verifyFormat("option (MyProto.options) = <\n"
281                "  field_a: \"OK\"\n"
282                "  msg_field <\n"
283                "    field_b: OK,\n"
284                "    field_c: OK,\n"
285                "    field_d: OK,\n"
286                "    field_e: OK,\n"
287                "    field_f: OK\n"
288                "  >\n"
289                "  field_g: OK\n"
290                ">;");
291 
292   verifyFormat("option (MyProto.options) = <\n"
293                "  field_a: \"OK\"\n"
294                "  msg_field: <\n"
295                "    field_b: OK\n"
296                "    field_c: OK\n"
297                "    field_d: OK\n"
298                "    field_e: OK\n"
299                "    field_f: OK\n"
300                "  >\n"
301                "  field_g: OK\n"
302                ">;");
303 
304   verifyFormat("option (MyProto.options) = <\n"
305                "  field_a: \"OK\"\n"
306                "  msg_field: {\n"
307                "    field_b: OK\n"
308                "    field_c: OK\n"
309                "    field_d: OK\n"
310                "    field_e: OK\n"
311                "    field_f: OK\n"
312                "  }\n"
313                "  field_g: OK\n"
314                ">;");
315 
316   verifyFormat("option (MyProto.options) = <\n"
317                "  field_a: \"OK\"\n"
318                "  msg_field {\n"
319                "    field_b: OK\n"
320                "    field_c: OK\n"
321                "    field_d: OK\n"
322                "    field_e: OK\n"
323                "    field_f: OK\n"
324                "  }\n"
325                "  field_g: OK\n"
326                ">;");
327 
328   verifyFormat("option (MyProto.options) = {\n"
329                "  field_a: \"OK\"\n"
330                "  msg_field <\n"
331                "    field_b: OK\n"
332                "    field_c: OK\n"
333                "    field_d: OK\n"
334                "    field_e: OK\n"
335                "    field_f: OK\n"
336                "  >\n"
337                "  field_g: OK\n"
338                "};");
339 
340   verifyFormat("option (MyProto.options) = {\n"
341                "  field_a: \"OK\"\n"
342                "  msg_field: <\n"
343                "    field_b: OK\n"
344                "    field_c: OK\n"
345                "    field_d: OK\n"
346                "    field_e: OK\n"
347                "    field_f: OK\n"
348                "  >\n"
349                "  field_g: OK\n"
350                "};");
351 
352   verifyFormat("option (MyProto.options) = <\n"
353                "  field_a: \"OK\"\n"
354                "  msg_field {\n"
355                "    field_b: OK\n"
356                "    field_c: OK\n"
357                "    field_d: OK\n"
358                "    msg_field <\n"
359                "      field_A: 1\n"
360                "      field_B: 2\n"
361                "      field_C: 3\n"
362                "      field_D: 4\n"
363                "      field_E: 5\n"
364                "    >\n"
365                "    msg_field < field_A: 1 field_B: 2 field_C: 3 f_D: 4 >\n"
366                "    field_e: OK\n"
367                "    field_f: OK\n"
368                "  }\n"
369                "  field_g: OK\n"
370                ">;");
371 
372   verifyFormat("option (MyProto.options) = <\n"
373                "  data1 < key1: value1 >\n"
374                "  data2 { key2: value2 }\n"
375                ">;");
376 
377   verifyFormat("option (MyProto.options) = <\n"
378                "  app_id: 'com.javax.swing.salsa.latino'\n"
379                "  head_id: 1\n"
380                "  data < key: value >\n"
381                ">;");
382 
383   verifyFormat("option (MyProto.options) = {\n"
384                "  app_id: 'com.javax.swing.salsa.latino'\n"
385                "  head_id: 1\n"
386                "  headheadheadheadheadhead_id: 1\n"
387                "  product_data { product { 1 } }\n"
388                "};");
389 }
390 
391 TEST_F(FormatTestProto, FormatsService) {
392   verifyFormat("service SearchService {\n"
393                "  rpc Search(SearchRequest) returns (SearchResponse) {\n"
394                "    option foo = true;\n"
395                "  }\n"
396                "};");
397 }
398 
399 TEST_F(FormatTestProto, ExtendingMessage) {
400   verifyFormat("extend .foo.Bar {\n"
401                "}");
402 }
403 
404 TEST_F(FormatTestProto, FormatsImports) {
405   verifyFormat("import \"a.proto\";\n"
406                "import \"b.proto\";\n"
407                "// comment\n"
408                "message A {\n"
409                "}");
410 
411   verifyFormat("import public \"a.proto\";\n"
412                "import \"b.proto\";\n"
413                "// comment\n"
414                "message A {\n"
415                "}");
416 
417   // Missing semicolons should not confuse clang-format.
418   verifyFormat("import \"a.proto\"\n"
419                "import \"b.proto\"\n"
420                "// comment\n"
421                "message A {\n"
422                "}");
423 }
424 
425 TEST_F(FormatTestProto, KeepsLongStringLiteralsOnSameLine) {
426   verifyFormat(
427       "option (MyProto.options) = {\n"
428       "  foo: {\n"
429       "    text: \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasaaaaaaaa\"\n"
430       "  }\n"
431       "}");
432 }
433 
434 TEST_F(FormatTestProto, FormatsOptionsExtensions) {
435   verifyFormat("option (MyProto.options) = {\n"
436                "  msg_field: { field_d: 123 }\n"
437                "  [ext.t/u] { key: value }\n"
438                "  key: value\n"
439                "  [t.u/v] <\n"
440                "    [ext] { key: value }\n"
441                "  >\n"
442                "};");
443 }
444 
445 TEST_F(FormatTestProto, NoSpaceAfterPercent) {
446   verifyFormat("option (MyProto.options) = {\n"
447                "  key: %lld\n"
448                "};");
449 }
450 
451 TEST_F(FormatTestProto, FormatsRepeatedListInitializersInOptions) {
452   verifyFormat("option (MyProto.options) = {\n"
453                "  key: item\n"
454                "  keys: [\n"
455                "    'ala',\n"
456                "    'bala',\n"
457                "    'porto',\n"
458                "    'kala',\n"
459                "    'too',\n"
460                "    'long',\n"
461                "    'long',\n"
462                "    'long'\n"
463                "  ]\n"
464                "  key: [ item ]\n"
465                "  msg {\n"
466                "    key: item\n"
467                "    keys: [\n"
468                "      'ala',\n"
469                "      'bala',\n"
470                "      'porto',\n"
471                "      'kala',\n"
472                "      'too',\n"
473                "      'long',\n"
474                "      'long'\n"
475                "    ]\n"
476                "  }\n"
477                "  key: value\n"
478                "};");
479 }
480 
481 TEST_F(FormatTestProto, AcceptsOperatorAsKeyInOptions) {
482   verifyFormat("option (MyProto.options) = {\n"
483                "  bbbbbbbbb: <\n"
484                "    ccccccccccccccccccccccc: <\n"
485                "      operator: 1\n"
486                "      operator: 2\n"
487                "      operator { key: value }\n"
488                "    >\n"
489                "  >\n"
490                "};");
491 }
492 
493 } // end namespace tooling
494 } // end namespace clang
495