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