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