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