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 EXPECT_EQ("#include \"a.h\"\n", sort("#include \"a.h\"\n" 293 " #include \"a.h\"\n")); 294 } 295 296 TEST_F(SortIncludesTest, TrailingWhitespace) { 297 EXPECT_EQ("#include \"a.h\"\n" 298 "#include \"b.h\"\n" 299 "#include \"c.h\"\n", 300 sort("#include \"a.h\" \n" 301 "#include \"c.h\" \n" 302 "#include \"b.h\" \n")); 303 EXPECT_EQ("#include \"a.h\"\n", sort("#include \"a.h\"\n" 304 "#include \"a.h\" \n")); 305 } 306 307 TEST_F(SortIncludesTest, GreaterInComment) { 308 EXPECT_EQ("#include \"a.h\"\n" 309 "#include \"b.h\" // >\n" 310 "#include \"c.h\"\n", 311 sort("#include \"a.h\"\n" 312 "#include \"c.h\"\n" 313 "#include \"b.h\" // >\n")); 314 } 315 316 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { 317 EXPECT_EQ("#include \"a.h\"\n" 318 "#include \"c.h\"\n" 319 "\n" 320 "#include \"b.h\"\n", 321 sort("#include \"a.h\"\n" 322 "#include \"c.h\"\n" 323 "\n" 324 "#include \"b.h\"\n", 325 "input.h", 0)); 326 } 327 328 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { 329 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 330 EXPECT_EQ("#include \"a.h\"\n" 331 "#include \"b.h\"\n" 332 "#include \"c.h\"\n", 333 sort("#include \"a.h\"\n" 334 "#include \"c.h\"\n" 335 "\n" 336 "#include \"b.h\"\n")); 337 } 338 339 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { 340 EXPECT_EQ("#include \"a.h\"\n" 341 "#include \"c.h\"\n" 342 "// comment\n" 343 "#include \"b.h\"\n", 344 sort("#include \"c.h\"\n" 345 "#include \"a.h\"\n" 346 "// comment\n" 347 "#include \"b.h\"\n")); 348 349 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 350 EXPECT_EQ("#include \"a.h\"\n" 351 "#include \"c.h\"\n" 352 "// comment\n" 353 "#include \"b.h\"\n", 354 sort("#include \"c.h\"\n" 355 "#include \"a.h\"\n" 356 "// comment\n" 357 "#include \"b.h\"\n")); 358 359 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 360 EXPECT_EQ("#include \"a.h\"\n" 361 "#include \"c.h\"\n" 362 "// comment\n" 363 "#include \"b.h\"\n", 364 sort("#include \"c.h\"\n" 365 "#include \"a.h\"\n" 366 "// comment\n" 367 "#include \"b.h\"\n")); 368 } 369 370 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { 371 EXPECT_EQ("#include \"a.h\"\n" 372 "#include \"c.h\"\n" 373 "#include <array>\n" 374 "#include <b.h>\n" 375 "#include <d.h>\n" 376 "#include <vector>\n", 377 sort("#include <vector>\n" 378 "#include <d.h>\n" 379 "#include <array>\n" 380 "#include <b.h>\n" 381 "#include \"c.h\"\n" 382 "#include \"a.h\"\n")); 383 384 FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); 385 EXPECT_EQ("#include <b.h>\n" 386 "#include <d.h>\n" 387 "\n" 388 "#include <array>\n" 389 "#include <vector>\n" 390 "\n" 391 "#include \"a.h\"\n" 392 "#include \"c.h\"\n", 393 sort("#include <vector>\n" 394 "#include <d.h>\n" 395 "#include <array>\n" 396 "#include <b.h>\n" 397 "#include \"c.h\"\n" 398 "#include \"a.h\"\n")); 399 } 400 401 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { 402 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 403 EXPECT_EQ("#include \"a.h\"\n" 404 "#include \"c.h\"\n" 405 "\n" 406 "#include <b.h>\n" 407 "#include <d.h>\n", 408 sort("#include <d.h>\n" 409 "#include <b.h>\n" 410 "#include \"c.h\"\n" 411 "#include \"a.h\"\n")); 412 } 413 414 TEST_F(SortIncludesTest, HandlesMultilineIncludes) { 415 EXPECT_EQ("#include \"a.h\"\n" 416 "#include \"b.h\"\n" 417 "#include \"c.h\"\n", 418 sort("#include \"a.h\"\n" 419 "#include \\\n" 420 "\"c.h\"\n" 421 "#include \"b.h\"\n")); 422 } 423 424 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { 425 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 426 EXPECT_EQ("#include \"llvm/a.h\"\n" 427 "#include \"b.h\"\n" 428 "#include \"c.h\"\n", 429 sort("#include \"llvm/a.h\"\n" 430 "#include \"c.h\"\n" 431 "#include \"b.h\"\n", 432 "a.cc")); 433 EXPECT_EQ("#include \"llvm/a.h\"\n" 434 "#include \"b.h\"\n" 435 "#include \"c.h\"\n", 436 sort("#include \"llvm/a.h\"\n" 437 "#include \"c.h\"\n" 438 "#include \"b.h\"\n", 439 "a_test.cc")); 440 EXPECT_EQ("#include \"llvm/input.h\"\n" 441 "#include \"b.h\"\n" 442 "#include \"c.h\"\n", 443 sort("#include \"llvm/input.h\"\n" 444 "#include \"c.h\"\n" 445 "#include \"b.h\"\n", 446 "input.mm")); 447 448 // Don't allow prefixes. 449 EXPECT_EQ("#include \"b.h\"\n" 450 "#include \"c.h\"\n" 451 "#include \"llvm/not_a.h\"\n", 452 sort("#include \"llvm/not_a.h\"\n" 453 "#include \"c.h\"\n" 454 "#include \"b.h\"\n", 455 "a.cc")); 456 457 // Don't do this for _main and other suffixes. 458 EXPECT_EQ("#include \"b.h\"\n" 459 "#include \"c.h\"\n" 460 "#include \"llvm/a.h\"\n", 461 sort("#include \"llvm/a.h\"\n" 462 "#include \"c.h\"\n" 463 "#include \"b.h\"\n", 464 "a_main.cc")); 465 466 // Don't do this in headers. 467 EXPECT_EQ("#include \"b.h\"\n" 468 "#include \"c.h\"\n" 469 "#include \"llvm/a.h\"\n", 470 sort("#include \"llvm/a.h\"\n" 471 "#include \"c.h\"\n" 472 "#include \"b.h\"\n", 473 "a.h")); 474 475 // Only do this in the first #include block. 476 EXPECT_EQ("#include <a>\n" 477 "\n" 478 "#include \"b.h\"\n" 479 "#include \"c.h\"\n" 480 "#include \"llvm/a.h\"\n", 481 sort("#include <a>\n" 482 "\n" 483 "#include \"llvm/a.h\"\n" 484 "#include \"c.h\"\n" 485 "#include \"b.h\"\n", 486 "a.cc")); 487 488 // Only recognize the first #include with a matching basename as main include. 489 EXPECT_EQ("#include \"a.h\"\n" 490 "#include \"b.h\"\n" 491 "#include \"c.h\"\n" 492 "#include \"llvm/a.h\"\n", 493 sort("#include \"b.h\"\n" 494 "#include \"a.h\"\n" 495 "#include \"c.h\"\n" 496 "#include \"llvm/a.h\"\n", 497 "a.cc")); 498 } 499 500 TEST_F(SortIncludesTest, LeavesMainHeaderFirstInAdditionalExtensions) { 501 Style.IncludeIsMainRegex = "([-_](test|unittest))?|(Impl)?$"; 502 EXPECT_EQ("#include \"b.h\"\n" 503 "#include \"c.h\"\n" 504 "#include \"llvm/a.h\"\n", 505 sort("#include \"llvm/a.h\"\n" 506 "#include \"c.h\"\n" 507 "#include \"b.h\"\n", 508 "a_test.xxx")); 509 EXPECT_EQ("#include \"b.h\"\n" 510 "#include \"c.h\"\n" 511 "#include \"llvm/a.h\"\n", 512 sort("#include \"llvm/a.h\"\n" 513 "#include \"c.h\"\n" 514 "#include \"b.h\"\n", 515 "aImpl.hpp")); 516 517 // .cpp extension is considered "main" by default 518 EXPECT_EQ("#include \"llvm/a.h\"\n" 519 "#include \"b.h\"\n" 520 "#include \"c.h\"\n", 521 sort("#include \"llvm/a.h\"\n" 522 "#include \"c.h\"\n" 523 "#include \"b.h\"\n", 524 "aImpl.cpp")); 525 EXPECT_EQ("#include \"llvm/a.h\"\n" 526 "#include \"b.h\"\n" 527 "#include \"c.h\"\n", 528 sort("#include \"llvm/a.h\"\n" 529 "#include \"c.h\"\n" 530 "#include \"b.h\"\n", 531 "a_test.cpp")); 532 533 // Allow additional filenames / extensions 534 Style.IncludeIsMainSourceRegex = "(Impl\\.hpp)|(\\.xxx)$"; 535 EXPECT_EQ("#include \"llvm/a.h\"\n" 536 "#include \"b.h\"\n" 537 "#include \"c.h\"\n", 538 sort("#include \"llvm/a.h\"\n" 539 "#include \"c.h\"\n" 540 "#include \"b.h\"\n", 541 "a_test.xxx")); 542 EXPECT_EQ("#include \"llvm/a.h\"\n" 543 "#include \"b.h\"\n" 544 "#include \"c.h\"\n", 545 sort("#include \"llvm/a.h\"\n" 546 "#include \"c.h\"\n" 547 "#include \"b.h\"\n", 548 "aImpl.hpp")); 549 } 550 551 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { 552 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 553 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 554 555 EXPECT_EQ("#include \"c.h\"\n" 556 "#include \"a.h\"\n" 557 "#include \"b.h\"\n", 558 sort("#include \"b.h\"\n" 559 "\n" 560 "#include \"a.h\"\n" 561 "#include \"c.h\"\n", 562 "c.cc")); 563 } 564 565 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { 566 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 567 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 568 569 EXPECT_EQ("#include \"a.h\"\n" 570 "\n" 571 "#include \"b.h\"\n" 572 "#include \"c.h\"\n", 573 sort("#include \"b.h\"\n" 574 "\n" 575 "#include \"a.h\"\n" 576 "#include \"c.h\"\n", 577 "a.cc")); 578 } 579 580 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { 581 // Setup an regex for main includes so we can cover those as well. 582 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 583 584 // Ensure both main header detection and grouping work in a case insensitive 585 // manner. 586 EXPECT_EQ("#include \"llvm/A.h\"\n" 587 "#include \"b.h\"\n" 588 "#include \"c.h\"\n" 589 "#include \"LLVM/z.h\"\n" 590 "#include \"llvm/X.h\"\n" 591 "#include \"GTest/GTest.h\"\n" 592 "#include \"gmock/gmock.h\"\n", 593 sort("#include \"c.h\"\n" 594 "#include \"b.h\"\n" 595 "#include \"GTest/GTest.h\"\n" 596 "#include \"llvm/A.h\"\n" 597 "#include \"gmock/gmock.h\"\n" 598 "#include \"llvm/X.h\"\n" 599 "#include \"LLVM/z.h\"\n", 600 "a_TEST.cc")); 601 } 602 603 TEST_F(SortIncludesTest, NegativePriorities) { 604 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 605 EXPECT_EQ("#include \"important_os_header.h\"\n" 606 "#include \"c_main.h\"\n" 607 "#include \"a_other.h\"\n", 608 sort("#include \"c_main.h\"\n" 609 "#include \"a_other.h\"\n" 610 "#include \"important_os_header.h\"\n", 611 "c_main.cc")); 612 613 // check stable when re-run 614 EXPECT_EQ("#include \"important_os_header.h\"\n" 615 "#include \"c_main.h\"\n" 616 "#include \"a_other.h\"\n", 617 sort("#include \"important_os_header.h\"\n" 618 "#include \"c_main.h\"\n" 619 "#include \"a_other.h\"\n", 620 "c_main.cc", 0)); 621 } 622 623 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { 624 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 625 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 626 627 EXPECT_EQ("#include \"important_os_header.h\"\n" 628 "\n" 629 "#include \"c_main.h\"\n" 630 "\n" 631 "#include \"a_other.h\"\n", 632 sort("#include \"c_main.h\"\n" 633 "#include \"a_other.h\"\n" 634 "#include \"important_os_header.h\"\n", 635 "c_main.cc")); 636 637 // check stable when re-run 638 EXPECT_EQ("#include \"important_os_header.h\"\n" 639 "\n" 640 "#include \"c_main.h\"\n" 641 "\n" 642 "#include \"a_other.h\"\n", 643 sort("#include \"important_os_header.h\"\n" 644 "\n" 645 "#include \"c_main.h\"\n" 646 "\n" 647 "#include \"a_other.h\"\n", 648 "c_main.cc", 0)); 649 } 650 651 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 652 std::string Code = "#include <ccc>\n" // Start of line: 0 653 "#include <bbbbbb>\n" // Start of line: 15 654 "#include <a>\n"; // Start of line: 33 655 EXPECT_EQ(31u, newCursor(Code, 0)); 656 EXPECT_EQ(13u, newCursor(Code, 15)); 657 EXPECT_EQ(0u, newCursor(Code, 33)); 658 659 EXPECT_EQ(41u, newCursor(Code, 10)); 660 EXPECT_EQ(23u, newCursor(Code, 25)); 661 EXPECT_EQ(10u, newCursor(Code, 43)); 662 } 663 664 TEST_F(SortIncludesTest, DeduplicateIncludes) { 665 EXPECT_EQ("#include <a>\n" 666 "#include <b>\n" 667 "#include <c>\n", 668 sort("#include <a>\n" 669 "#include <b>\n" 670 "#include <b>\n" 671 "#include <b>\n" 672 "#include <b>\n" 673 "#include <c>\n")); 674 675 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 676 EXPECT_EQ("#include <a>\n" 677 "#include <b>\n" 678 "#include <c>\n", 679 sort("#include <a>\n" 680 "#include <b>\n" 681 "\n" 682 "#include <b>\n" 683 "\n" 684 "#include <b>\n" 685 "#include <c>\n")); 686 687 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 688 EXPECT_EQ("#include <a>\n" 689 "#include <b>\n" 690 "#include <c>\n", 691 sort("#include <a>\n" 692 "#include <b>\n" 693 "\n" 694 "#include <b>\n" 695 "\n" 696 "#include <b>\n" 697 "#include <c>\n")); 698 } 699 700 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 701 EXPECT_EQ("#include <a>\n" 702 "#include <b>\n" 703 "#include <c>\n", 704 sort("#include <b>\n" 705 "#include <a>\n" 706 "#include <b>\n" 707 "#include <b>\n" 708 "#include <c>\n" 709 "#include <b>\n")); 710 711 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 712 EXPECT_EQ("#include <a>\n" 713 "#include <b>\n" 714 "#include <c>\n", 715 sort("#include <b>\n" 716 "#include <a>\n" 717 "\n" 718 "#include <b>\n" 719 "\n" 720 "#include <c>\n" 721 "#include <b>\n")); 722 723 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 724 EXPECT_EQ("#include <a>\n" 725 "#include <b>\n" 726 "#include <c>\n", 727 sort("#include <b>\n" 728 "#include <a>\n" 729 "\n" 730 "#include <b>\n" 731 "\n" 732 "#include <c>\n" 733 "#include <b>\n")); 734 } 735 736 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 737 std::string Code = "#include <b>\n" // Start of line: 0 738 "#include <a>\n" // Start of line: 13 739 "#include <b>\n" // Start of line: 26 740 "#include <b>\n" // Start of line: 39 741 "#include <c>\n" // Start of line: 52 742 "#include <b>\n"; // Start of line: 65 743 std::string Expected = "#include <a>\n" // Start of line: 0 744 "#include <b>\n" // Start of line: 13 745 "#include <c>\n"; // Start of line: 26 746 EXPECT_EQ(Expected, sort(Code)); 747 // Cursor on 'i' in "#include <a>". 748 EXPECT_EQ(1u, newCursor(Code, 14)); 749 // Cursor on 'b' in "#include <b>". 750 EXPECT_EQ(23u, newCursor(Code, 10)); 751 EXPECT_EQ(23u, newCursor(Code, 36)); 752 EXPECT_EQ(23u, newCursor(Code, 49)); 753 EXPECT_EQ(23u, newCursor(Code, 36)); 754 EXPECT_EQ(23u, newCursor(Code, 75)); 755 // Cursor on '#' in "#include <c>". 756 EXPECT_EQ(26u, newCursor(Code, 52)); 757 } 758 759 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 760 EXPECT_EQ("#include <a>\n" 761 "#include <b>\n" 762 "\n" 763 "#include <b>\n" 764 "#include <c>\n", 765 sort("#include <a>\n" 766 "#include <b>\n" 767 "\n" 768 "#include <c>\n" 769 "#include <b>\n" 770 "#include <b>\n")); 771 } 772 773 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 774 std::string Code = "#include <a>\n" 775 "#include <b>\n" 776 "#include <a>\n" 777 "#include <a>\n" 778 "\n" 779 " int x ;"; 780 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 781 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); 782 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 783 EXPECT_EQ(1u, Ranges.size()); 784 EXPECT_EQ(0u, Ranges[0].getOffset()); 785 EXPECT_EQ(26u, Ranges[0].getLength()); 786 } 787 788 TEST_F(SortIncludesTest, DoNotSortLikelyXml) { 789 EXPECT_EQ("<!--;\n" 790 "#include <b>\n" 791 "#include <a>\n" 792 "-->", 793 sort("<!--;\n" 794 "#include <b>\n" 795 "#include <a>\n" 796 "-->", 797 "input.h", 0)); 798 } 799 800 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { 801 Style.IncludeBlocks = Style.IBS_Regroup; 802 std::string Code = R"( 803 #include "b.h" 804 805 #include <a.h> 806 )"; 807 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 808 } 809 810 TEST_F(SortIncludesTest, 811 DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { 812 Style.IncludeBlocks = Style.IBS_Regroup; 813 std::string Code = "#include \"b.h\"\r\n" 814 "\r\n" 815 "#include <a.h>\r\n"; 816 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 817 } 818 819 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { 820 FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC); 821 822 EXPECT_EQ("#include <a.h>\n" 823 "#include <b.h>\n" 824 "#include \"a.h\"", 825 sort("#include <b.h>\n" 826 "#include <a.h>\n" 827 "#include \"a.h\"")); 828 } 829 830 } // end namespace 831 } // end namespace format 832 } // end namespace clang 833