1 //===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "FormatTestUtils.h" 10 #include "clang/Format/Format.h" 11 #include "llvm/ADT/None.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 namespace { 20 21 class SortIncludesTest : public ::testing::Test { 22 protected: 23 std::vector<tooling::Range> GetCodeRange(StringRef Code) { 24 return std::vector<tooling::Range>(1, tooling::Range(0, Code.size())); 25 } 26 27 std::string sort(StringRef Code, std::vector<tooling::Range> Ranges, 28 StringRef FileName = "input.cc", 29 unsigned ExpectedNumRanges = 1) { 30 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName); 31 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 32 EXPECT_EQ(ExpectedNumRanges, Replaces.size()); 33 auto Sorted = applyAllReplacements(Code, Replaces); 34 EXPECT_TRUE(static_cast<bool>(Sorted)); 35 auto Result = applyAllReplacements( 36 *Sorted, reformat(FmtStyle, *Sorted, Ranges, FileName)); 37 EXPECT_TRUE(static_cast<bool>(Result)); 38 return *Result; 39 } 40 41 std::string sort(StringRef Code, 42 StringRef FileName = "input.cpp", 43 unsigned ExpectedNumRanges = 1) { 44 return sort(Code, GetCodeRange(Code), FileName, ExpectedNumRanges); 45 } 46 47 unsigned newCursor(llvm::StringRef Code, unsigned Cursor) { 48 sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.cpp", &Cursor); 49 return Cursor; 50 } 51 52 FormatStyle FmtStyle = getLLVMStyle(); 53 tooling::IncludeStyle &Style = FmtStyle.IncludeStyle; 54 }; 55 56 TEST_F(SortIncludesTest, BasicSorting) { 57 EXPECT_EQ("#include \"a.h\"\n" 58 "#include \"b.h\"\n" 59 "#include \"c.h\"\n", 60 sort("#include \"a.h\"\n" 61 "#include \"c.h\"\n" 62 "#include \"b.h\"\n")); 63 64 EXPECT_EQ("// comment\n" 65 "#include <a>\n" 66 "#include <b>\n", 67 sort("// comment\n" 68 "#include <b>\n" 69 "#include <a>\n", 70 {tooling::Range(25, 1)})); 71 } 72 73 TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) { 74 FmtStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 75 FmtStyle.IncludeStyle.IncludeCategories = { 76 {"^<sys/param\\.h>", 1, 0}, 77 {"^<sys/types\\.h>", 1, 1}, 78 {"^<sys.*/", 1, 2}, 79 {"^<uvm/", 2, 3}, 80 {"^<machine/", 3, 4}, 81 {"^<dev/", 4, 5}, 82 {"^<net.*/", 5, 6}, 83 {"^<protocols/", 5, 7}, 84 {"^<(fs|miscfs|msdosfs|nfs|ntfs|ufs)/", 6, 8}, 85 {"^<(x86|amd64|i386|xen)/", 7, 8}, 86 {"<path", 9, 11}, 87 {"^<[^/].*\\.h>", 8, 10}, 88 {"^\".*\\.h\"", 10, 12}}; 89 EXPECT_EQ("#include <sys/param.h>\n" 90 "#include <sys/types.h>\n" 91 "#include <sys/ioctl.h>\n" 92 "#include <sys/socket.h>\n" 93 "#include <sys/stat.h>\n" 94 "#include <sys/wait.h>\n" 95 "\n" 96 "#include <net/if.h>\n" 97 "#include <net/if_dl.h>\n" 98 "#include <net/route.h>\n" 99 "#include <netinet/in.h>\n" 100 "#include <protocols/rwhod.h>\n" 101 "\n" 102 "#include <assert.h>\n" 103 "#include <errno.h>\n" 104 "#include <inttypes.h>\n" 105 "#include <stdio.h>\n" 106 "#include <stdlib.h>\n" 107 "\n" 108 "#include <paths.h>\n" 109 "\n" 110 "#include \"pathnames.h\"\n", 111 sort("#include <sys/param.h>\n" 112 "#include <sys/types.h>\n" 113 "#include <sys/ioctl.h>\n" 114 "#include <net/if_dl.h>\n" 115 "#include <net/route.h>\n" 116 "#include <netinet/in.h>\n" 117 "#include <sys/socket.h>\n" 118 "#include <sys/stat.h>\n" 119 "#include <sys/wait.h>\n" 120 "#include <net/if.h>\n" 121 "#include <protocols/rwhod.h>\n" 122 "#include <assert.h>\n" 123 "#include <paths.h>\n" 124 "#include \"pathnames.h\"\n" 125 "#include <errno.h>\n" 126 "#include <inttypes.h>\n" 127 "#include <stdio.h>\n" 128 "#include <stdlib.h>\n")); 129 } 130 TEST_F(SortIncludesTest, SortPriorityNotDefined) { 131 FmtStyle = getLLVMStyle(); 132 EXPECT_EQ("#include \"FormatTestUtils.h\"\n" 133 "#include \"clang/Format/Format.h\"\n" 134 "#include \"llvm/ADT/None.h\"\n" 135 "#include \"llvm/Support/Debug.h\"\n" 136 "#include \"gtest/gtest.h\"\n", 137 sort("#include \"clang/Format/Format.h\"\n" 138 "#include \"llvm/ADT/None.h\"\n" 139 "#include \"FormatTestUtils.h\"\n" 140 "#include \"gtest/gtest.h\"\n" 141 "#include \"llvm/Support/Debug.h\"\n")); 142 } 143 144 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) { 145 // Identical #includes have led to a failure with an unstable sort. 146 std::string Code = "#include <a>\n" 147 "#include <b>\n" 148 "#include <c>\n" 149 "#include <d>\n" 150 "#include <e>\n" 151 "#include <f>\n"; 152 EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty()); 153 } 154 155 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { 156 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 157 EXPECT_EQ("#include \"a.h\"\n" 158 "#include \"b.h\"\n" 159 "#include \"c.h\"\n", 160 sort("#include \"a.h\"\n" 161 "#include \"c.h\"\n" 162 "\n" 163 "\n" 164 "#include \"b.h\"\n")); 165 166 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 167 EXPECT_EQ("#include \"a.h\"\n" 168 "#include \"b.h\"\n" 169 "#include \"c.h\"\n", 170 sort("#include \"a.h\"\n" 171 "#include \"c.h\"\n" 172 "\n" 173 "\n" 174 "#include \"b.h\"\n")); 175 } 176 177 TEST_F(SortIncludesTest, SupportClangFormatOff) { 178 EXPECT_EQ("#include <a>\n" 179 "#include <b>\n" 180 "#include <c>\n" 181 "// clang-format off\n" 182 "#include <b>\n" 183 "#include <a>\n" 184 "#include <c>\n" 185 "// clang-format on\n", 186 sort("#include <b>\n" 187 "#include <a>\n" 188 "#include <c>\n" 189 "// clang-format off\n" 190 "#include <b>\n" 191 "#include <a>\n" 192 "#include <c>\n" 193 "// clang-format on\n")); 194 } 195 196 TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) { 197 EXPECT_EQ("#include <a>\n" 198 "#include <b>\n" 199 "#include <c>\n" 200 "/* clang-format off */\n" 201 "#include <b>\n" 202 "#include <a>\n" 203 "#include <c>\n" 204 "/* clang-format on */\n", 205 sort("#include <b>\n" 206 "#include <a>\n" 207 "#include <c>\n" 208 "/* clang-format off */\n" 209 "#include <b>\n" 210 "#include <a>\n" 211 "#include <c>\n" 212 "/* clang-format on */\n")); 213 214 // Not really turning it off 215 EXPECT_EQ("#include <a>\n" 216 "#include <b>\n" 217 "#include <c>\n" 218 "/* clang-format offically */\n" 219 "#include <a>\n" 220 "#include <b>\n" 221 "#include <c>\n" 222 "/* clang-format onwards */\n", 223 sort("#include <b>\n" 224 "#include <a>\n" 225 "#include <c>\n" 226 "/* clang-format offically */\n" 227 "#include <b>\n" 228 "#include <a>\n" 229 "#include <c>\n" 230 "/* clang-format onwards */\n", "input.h", 2)); 231 } 232 233 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { 234 FmtStyle.SortIncludes = false; 235 EXPECT_EQ("#include \"a.h\"\n" 236 "#include \"c.h\"\n" 237 "#include \"b.h\"\n", 238 sort("#include \"a.h\"\n" 239 "#include \"c.h\"\n" 240 "#include \"b.h\"\n", 241 "input.h", 0)); 242 } 243 244 TEST_F(SortIncludesTest, MixIncludeAndImport) { 245 EXPECT_EQ("#include \"a.h\"\n" 246 "#import \"b.h\"\n" 247 "#include \"c.h\"\n", 248 sort("#include \"a.h\"\n" 249 "#include \"c.h\"\n" 250 "#import \"b.h\"\n")); 251 } 252 253 TEST_F(SortIncludesTest, FixTrailingComments) { 254 EXPECT_EQ("#include \"a.h\" // comment\n" 255 "#include \"bb.h\" // comment\n" 256 "#include \"ccc.h\"\n", 257 sort("#include \"a.h\" // comment\n" 258 "#include \"ccc.h\"\n" 259 "#include \"bb.h\" // comment\n")); 260 } 261 262 TEST_F(SortIncludesTest, LeadingWhitespace) { 263 EXPECT_EQ("#include \"a.h\"\n" 264 "#include \"b.h\"\n" 265 "#include \"c.h\"\n", 266 sort(" #include \"a.h\"\n" 267 " #include \"c.h\"\n" 268 " #include \"b.h\"\n")); 269 EXPECT_EQ("#include \"a.h\"\n" 270 "#include \"b.h\"\n" 271 "#include \"c.h\"\n", 272 sort("# include \"a.h\"\n" 273 "# include \"c.h\"\n" 274 "# include \"b.h\"\n")); 275 } 276 277 TEST_F(SortIncludesTest, GreaterInComment) { 278 EXPECT_EQ("#include \"a.h\"\n" 279 "#include \"b.h\" // >\n" 280 "#include \"c.h\"\n", 281 sort("#include \"a.h\"\n" 282 "#include \"c.h\"\n" 283 "#include \"b.h\" // >\n")); 284 } 285 286 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { 287 EXPECT_EQ("#include \"a.h\"\n" 288 "#include \"c.h\"\n" 289 "\n" 290 "#include \"b.h\"\n", 291 sort("#include \"a.h\"\n" 292 "#include \"c.h\"\n" 293 "\n" 294 "#include \"b.h\"\n", "input.h", 0)); 295 } 296 297 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { 298 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 299 EXPECT_EQ("#include \"a.h\"\n" 300 "#include \"b.h\"\n" 301 "#include \"c.h\"\n", 302 sort("#include \"a.h\"\n" 303 "#include \"c.h\"\n" 304 "\n" 305 "#include \"b.h\"\n")); 306 } 307 308 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { 309 EXPECT_EQ("#include \"a.h\"\n" 310 "#include \"c.h\"\n" 311 "// comment\n" 312 "#include \"b.h\"\n", 313 sort("#include \"c.h\"\n" 314 "#include \"a.h\"\n" 315 "// comment\n" 316 "#include \"b.h\"\n")); 317 318 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 319 EXPECT_EQ("#include \"a.h\"\n" 320 "#include \"c.h\"\n" 321 "// comment\n" 322 "#include \"b.h\"\n", 323 sort("#include \"c.h\"\n" 324 "#include \"a.h\"\n" 325 "// comment\n" 326 "#include \"b.h\"\n")); 327 328 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 329 EXPECT_EQ("#include \"a.h\"\n" 330 "#include \"c.h\"\n" 331 "// comment\n" 332 "#include \"b.h\"\n", 333 sort("#include \"c.h\"\n" 334 "#include \"a.h\"\n" 335 "// comment\n" 336 "#include \"b.h\"\n")); 337 } 338 339 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { 340 EXPECT_EQ("#include \"a.h\"\n" 341 "#include \"c.h\"\n" 342 "#include <array>\n" 343 "#include <b.h>\n" 344 "#include <d.h>\n" 345 "#include <vector>\n", 346 sort("#include <vector>\n" 347 "#include <d.h>\n" 348 "#include <array>\n" 349 "#include <b.h>\n" 350 "#include \"c.h\"\n" 351 "#include \"a.h\"\n")); 352 353 FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); 354 EXPECT_EQ("#include <b.h>\n" 355 "#include <d.h>\n" 356 "\n" 357 "#include <array>\n" 358 "#include <vector>\n" 359 "\n" 360 "#include \"a.h\"\n" 361 "#include \"c.h\"\n", 362 sort("#include <vector>\n" 363 "#include <d.h>\n" 364 "#include <array>\n" 365 "#include <b.h>\n" 366 "#include \"c.h\"\n" 367 "#include \"a.h\"\n")); 368 } 369 370 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { 371 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 372 EXPECT_EQ("#include \"a.h\"\n" 373 "#include \"c.h\"\n" 374 "\n" 375 "#include <b.h>\n" 376 "#include <d.h>\n", 377 sort("#include <d.h>\n" 378 "#include <b.h>\n" 379 "#include \"c.h\"\n" 380 "#include \"a.h\"\n")); 381 } 382 383 TEST_F(SortIncludesTest, HandlesMultilineIncludes) { 384 EXPECT_EQ("#include \"a.h\"\n" 385 "#include \"b.h\"\n" 386 "#include \"c.h\"\n", 387 sort("#include \"a.h\"\n" 388 "#include \\\n" 389 "\"c.h\"\n" 390 "#include \"b.h\"\n")); 391 } 392 393 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { 394 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 395 EXPECT_EQ("#include \"llvm/a.h\"\n" 396 "#include \"b.h\"\n" 397 "#include \"c.h\"\n", 398 sort("#include \"llvm/a.h\"\n" 399 "#include \"c.h\"\n" 400 "#include \"b.h\"\n", 401 "a.cc")); 402 EXPECT_EQ("#include \"llvm/a.h\"\n" 403 "#include \"b.h\"\n" 404 "#include \"c.h\"\n", 405 sort("#include \"llvm/a.h\"\n" 406 "#include \"c.h\"\n" 407 "#include \"b.h\"\n", 408 "a_test.cc")); 409 EXPECT_EQ("#include \"llvm/input.h\"\n" 410 "#include \"b.h\"\n" 411 "#include \"c.h\"\n", 412 sort("#include \"llvm/input.h\"\n" 413 "#include \"c.h\"\n" 414 "#include \"b.h\"\n", 415 "input.mm")); 416 417 // Don't allow prefixes. 418 EXPECT_EQ("#include \"b.h\"\n" 419 "#include \"c.h\"\n" 420 "#include \"llvm/not_a.h\"\n", 421 sort("#include \"llvm/not_a.h\"\n" 422 "#include \"c.h\"\n" 423 "#include \"b.h\"\n", 424 "a.cc")); 425 426 // Don't do this for _main and other suffixes. 427 EXPECT_EQ("#include \"b.h\"\n" 428 "#include \"c.h\"\n" 429 "#include \"llvm/a.h\"\n", 430 sort("#include \"llvm/a.h\"\n" 431 "#include \"c.h\"\n" 432 "#include \"b.h\"\n", 433 "a_main.cc")); 434 435 // Don't do this in headers. 436 EXPECT_EQ("#include \"b.h\"\n" 437 "#include \"c.h\"\n" 438 "#include \"llvm/a.h\"\n", 439 sort("#include \"llvm/a.h\"\n" 440 "#include \"c.h\"\n" 441 "#include \"b.h\"\n", 442 "a.h")); 443 444 // Only do this in the first #include block. 445 EXPECT_EQ("#include <a>\n" 446 "\n" 447 "#include \"b.h\"\n" 448 "#include \"c.h\"\n" 449 "#include \"llvm/a.h\"\n", 450 sort("#include <a>\n" 451 "\n" 452 "#include \"llvm/a.h\"\n" 453 "#include \"c.h\"\n" 454 "#include \"b.h\"\n", 455 "a.cc")); 456 457 // Only recognize the first #include with a matching basename as main include. 458 EXPECT_EQ("#include \"a.h\"\n" 459 "#include \"b.h\"\n" 460 "#include \"c.h\"\n" 461 "#include \"llvm/a.h\"\n", 462 sort("#include \"b.h\"\n" 463 "#include \"a.h\"\n" 464 "#include \"c.h\"\n" 465 "#include \"llvm/a.h\"\n", 466 "a.cc")); 467 } 468 469 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { 470 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 471 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 472 473 EXPECT_EQ("#include \"c.h\"\n" 474 "#include \"a.h\"\n" 475 "#include \"b.h\"\n", 476 sort("#include \"b.h\"\n" 477 "\n" 478 "#include \"a.h\"\n" 479 "#include \"c.h\"\n", 480 "c.cc")); 481 } 482 483 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { 484 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 485 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 486 487 EXPECT_EQ("#include \"a.h\"\n" 488 "\n" 489 "#include \"b.h\"\n" 490 "#include \"c.h\"\n", 491 sort("#include \"b.h\"\n" 492 "\n" 493 "#include \"a.h\"\n" 494 "#include \"c.h\"\n", 495 "a.cc")); 496 } 497 498 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { 499 // Setup an regex for main includes so we can cover those as well. 500 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 501 502 // Ensure both main header detection and grouping work in a case insensitive 503 // manner. 504 EXPECT_EQ("#include \"llvm/A.h\"\n" 505 "#include \"b.h\"\n" 506 "#include \"c.h\"\n" 507 "#include \"LLVM/z.h\"\n" 508 "#include \"llvm/X.h\"\n" 509 "#include \"GTest/GTest.h\"\n" 510 "#include \"gmock/gmock.h\"\n", 511 sort("#include \"c.h\"\n" 512 "#include \"b.h\"\n" 513 "#include \"GTest/GTest.h\"\n" 514 "#include \"llvm/A.h\"\n" 515 "#include \"gmock/gmock.h\"\n" 516 "#include \"llvm/X.h\"\n" 517 "#include \"LLVM/z.h\"\n", 518 "a_TEST.cc")); 519 } 520 521 TEST_F(SortIncludesTest, NegativePriorities) { 522 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 523 EXPECT_EQ("#include \"important_os_header.h\"\n" 524 "#include \"c_main.h\"\n" 525 "#include \"a_other.h\"\n", 526 sort("#include \"c_main.h\"\n" 527 "#include \"a_other.h\"\n" 528 "#include \"important_os_header.h\"\n", 529 "c_main.cc")); 530 531 // check stable when re-run 532 EXPECT_EQ("#include \"important_os_header.h\"\n" 533 "#include \"c_main.h\"\n" 534 "#include \"a_other.h\"\n", 535 sort("#include \"important_os_header.h\"\n" 536 "#include \"c_main.h\"\n" 537 "#include \"a_other.h\"\n", 538 "c_main.cc", 0)); 539 } 540 541 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { 542 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 543 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 544 545 EXPECT_EQ("#include \"important_os_header.h\"\n" 546 "\n" 547 "#include \"c_main.h\"\n" 548 "\n" 549 "#include \"a_other.h\"\n", 550 sort("#include \"c_main.h\"\n" 551 "#include \"a_other.h\"\n" 552 "#include \"important_os_header.h\"\n", 553 "c_main.cc")); 554 555 // check stable when re-run 556 EXPECT_EQ("#include \"important_os_header.h\"\n" 557 "\n" 558 "#include \"c_main.h\"\n" 559 "\n" 560 "#include \"a_other.h\"\n", 561 sort("#include \"important_os_header.h\"\n" 562 "\n" 563 "#include \"c_main.h\"\n" 564 "\n" 565 "#include \"a_other.h\"\n", 566 "c_main.cc", 0)); 567 } 568 569 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 570 std::string Code = "#include <ccc>\n" // Start of line: 0 571 "#include <bbbbbb>\n" // Start of line: 15 572 "#include <a>\n"; // Start of line: 33 573 EXPECT_EQ(31u, newCursor(Code, 0)); 574 EXPECT_EQ(13u, newCursor(Code, 15)); 575 EXPECT_EQ(0u, newCursor(Code, 33)); 576 577 EXPECT_EQ(41u, newCursor(Code, 10)); 578 EXPECT_EQ(23u, newCursor(Code, 25)); 579 EXPECT_EQ(10u, newCursor(Code, 43)); 580 } 581 582 TEST_F(SortIncludesTest, DeduplicateIncludes) { 583 EXPECT_EQ("#include <a>\n" 584 "#include <b>\n" 585 "#include <c>\n", 586 sort("#include <a>\n" 587 "#include <b>\n" 588 "#include <b>\n" 589 "#include <b>\n" 590 "#include <b>\n" 591 "#include <c>\n")); 592 593 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 594 EXPECT_EQ("#include <a>\n" 595 "#include <b>\n" 596 "#include <c>\n", 597 sort("#include <a>\n" 598 "#include <b>\n" 599 "\n" 600 "#include <b>\n" 601 "\n" 602 "#include <b>\n" 603 "#include <c>\n")); 604 605 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 606 EXPECT_EQ("#include <a>\n" 607 "#include <b>\n" 608 "#include <c>\n", 609 sort("#include <a>\n" 610 "#include <b>\n" 611 "\n" 612 "#include <b>\n" 613 "\n" 614 "#include <b>\n" 615 "#include <c>\n")); 616 } 617 618 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 619 EXPECT_EQ("#include <a>\n" 620 "#include <b>\n" 621 "#include <c>\n", 622 sort("#include <b>\n" 623 "#include <a>\n" 624 "#include <b>\n" 625 "#include <b>\n" 626 "#include <c>\n" 627 "#include <b>\n")); 628 629 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 630 EXPECT_EQ("#include <a>\n" 631 "#include <b>\n" 632 "#include <c>\n", 633 sort("#include <b>\n" 634 "#include <a>\n" 635 "\n" 636 "#include <b>\n" 637 "\n" 638 "#include <c>\n" 639 "#include <b>\n")); 640 641 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 642 EXPECT_EQ("#include <a>\n" 643 "#include <b>\n" 644 "#include <c>\n", 645 sort("#include <b>\n" 646 "#include <a>\n" 647 "\n" 648 "#include <b>\n" 649 "\n" 650 "#include <c>\n" 651 "#include <b>\n")); 652 } 653 654 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 655 std::string Code = "#include <b>\n" // Start of line: 0 656 "#include <a>\n" // Start of line: 13 657 "#include <b>\n" // Start of line: 26 658 "#include <b>\n" // Start of line: 39 659 "#include <c>\n" // Start of line: 52 660 "#include <b>\n"; // Start of line: 65 661 std::string Expected = "#include <a>\n" // Start of line: 0 662 "#include <b>\n" // Start of line: 13 663 "#include <c>\n"; // Start of line: 26 664 EXPECT_EQ(Expected, sort(Code)); 665 // Cursor on 'i' in "#include <a>". 666 EXPECT_EQ(1u, newCursor(Code, 14)); 667 // Cursor on 'b' in "#include <b>". 668 EXPECT_EQ(23u, newCursor(Code, 10)); 669 EXPECT_EQ(23u, newCursor(Code, 36)); 670 EXPECT_EQ(23u, newCursor(Code, 49)); 671 EXPECT_EQ(23u, newCursor(Code, 36)); 672 EXPECT_EQ(23u, newCursor(Code, 75)); 673 // Cursor on '#' in "#include <c>". 674 EXPECT_EQ(26u, newCursor(Code, 52)); 675 } 676 677 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 678 EXPECT_EQ("#include <a>\n" 679 "#include <b>\n" 680 "\n" 681 "#include <b>\n" 682 "#include <c>\n", 683 sort("#include <a>\n" 684 "#include <b>\n" 685 "\n" 686 "#include <c>\n" 687 "#include <b>\n" 688 "#include <b>\n")); 689 } 690 691 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 692 std::string Code = "#include <a>\n" 693 "#include <b>\n" 694 "#include <a>\n" 695 "#include <a>\n" 696 "\n" 697 " int x ;"; 698 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 699 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); 700 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 701 EXPECT_EQ(1u, Ranges.size()); 702 EXPECT_EQ(0u, Ranges[0].getOffset()); 703 EXPECT_EQ(26u, Ranges[0].getLength()); 704 } 705 706 TEST_F(SortIncludesTest, DoNotSortLikelyXml) { 707 EXPECT_EQ("<!--;\n" 708 "#include <b>\n" 709 "#include <a>\n" 710 "-->", 711 sort("<!--;\n" 712 "#include <b>\n" 713 "#include <a>\n" 714 "-->", "input.h", 0)); 715 } 716 717 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { 718 Style.IncludeBlocks = Style.IBS_Regroup; 719 std::string Code = R"( 720 #include "b.h" 721 722 #include <a.h> 723 )"; 724 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 725 } 726 727 TEST_F(SortIncludesTest, 728 DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { 729 Style.IncludeBlocks = Style.IBS_Regroup; 730 std::string Code = "#include \"b.h\"\r\n" 731 "\r\n" 732 "#include <a.h>\r\n"; 733 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 734 } 735 736 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { 737 FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC); 738 739 EXPECT_EQ("#include <a.h>\n" 740 "#include <b.h>\n" 741 "#include \"a.h\"", 742 sort("#include <b.h>\n" 743 "#include <a.h>\n" 744 "#include \"a.h\"")); 745 } 746 747 } // end namespace 748 } // end namespace format 749 } // end namespace clang 750