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