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