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