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, NoMainFileHeader) { 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 164 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { 165 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 166 EXPECT_EQ("#include \"a.h\"\n" 167 "#include \"b.h\"\n" 168 "#include \"c.h\"\n", 169 sort("#include \"a.h\"\n" 170 "#include \"c.h\"\n" 171 "\n" 172 "\n" 173 "#include \"b.h\"\n")); 174 175 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 176 EXPECT_EQ("#include \"a.h\"\n" 177 "#include \"b.h\"\n" 178 "#include \"c.h\"\n", 179 sort("#include \"a.h\"\n" 180 "#include \"c.h\"\n" 181 "\n" 182 "\n" 183 "#include \"b.h\"\n")); 184 } 185 186 TEST_F(SortIncludesTest, SupportClangFormatOff) { 187 EXPECT_EQ("#include <a>\n" 188 "#include <b>\n" 189 "#include <c>\n" 190 "// clang-format off\n" 191 "#include <b>\n" 192 "#include <a>\n" 193 "#include <c>\n" 194 "// clang-format on\n", 195 sort("#include <b>\n" 196 "#include <a>\n" 197 "#include <c>\n" 198 "// clang-format off\n" 199 "#include <b>\n" 200 "#include <a>\n" 201 "#include <c>\n" 202 "// clang-format on\n")); 203 } 204 205 TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) { 206 EXPECT_EQ("#include <a>\n" 207 "#include <b>\n" 208 "#include <c>\n" 209 "/* clang-format off */\n" 210 "#include <b>\n" 211 "#include <a>\n" 212 "#include <c>\n" 213 "/* clang-format on */\n", 214 sort("#include <b>\n" 215 "#include <a>\n" 216 "#include <c>\n" 217 "/* clang-format off */\n" 218 "#include <b>\n" 219 "#include <a>\n" 220 "#include <c>\n" 221 "/* clang-format on */\n")); 222 223 // Not really turning it off 224 EXPECT_EQ("#include <a>\n" 225 "#include <b>\n" 226 "#include <c>\n" 227 "/* clang-format offically */\n" 228 "#include <a>\n" 229 "#include <b>\n" 230 "#include <c>\n" 231 "/* clang-format onwards */\n", 232 sort("#include <b>\n" 233 "#include <a>\n" 234 "#include <c>\n" 235 "/* clang-format offically */\n" 236 "#include <b>\n" 237 "#include <a>\n" 238 "#include <c>\n" 239 "/* clang-format onwards */\n", 240 "input.h", 2)); 241 } 242 243 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { 244 FmtStyle.SortIncludes = false; 245 EXPECT_EQ("#include \"a.h\"\n" 246 "#include \"c.h\"\n" 247 "#include \"b.h\"\n", 248 sort("#include \"a.h\"\n" 249 "#include \"c.h\"\n" 250 "#include \"b.h\"\n", 251 "input.h", 0)); 252 } 253 254 TEST_F(SortIncludesTest, MixIncludeAndImport) { 255 EXPECT_EQ("#include \"a.h\"\n" 256 "#import \"b.h\"\n" 257 "#include \"c.h\"\n", 258 sort("#include \"a.h\"\n" 259 "#include \"c.h\"\n" 260 "#import \"b.h\"\n")); 261 } 262 263 TEST_F(SortIncludesTest, FixTrailingComments) { 264 EXPECT_EQ("#include \"a.h\" // comment\n" 265 "#include \"bb.h\" // comment\n" 266 "#include \"ccc.h\"\n", 267 sort("#include \"a.h\" // comment\n" 268 "#include \"ccc.h\"\n" 269 "#include \"bb.h\" // comment\n")); 270 } 271 272 TEST_F(SortIncludesTest, LeadingWhitespace) { 273 EXPECT_EQ("#include \"a.h\"\n" 274 "#include \"b.h\"\n" 275 "#include \"c.h\"\n", 276 sort(" #include \"a.h\"\n" 277 " #include \"c.h\"\n" 278 " #include \"b.h\"\n")); 279 EXPECT_EQ("#include \"a.h\"\n" 280 "#include \"b.h\"\n" 281 "#include \"c.h\"\n", 282 sort("# include \"a.h\"\n" 283 "# include \"c.h\"\n" 284 "# include \"b.h\"\n")); 285 } 286 287 TEST_F(SortIncludesTest, GreaterInComment) { 288 EXPECT_EQ("#include \"a.h\"\n" 289 "#include \"b.h\" // >\n" 290 "#include \"c.h\"\n", 291 sort("#include \"a.h\"\n" 292 "#include \"c.h\"\n" 293 "#include \"b.h\" // >\n")); 294 } 295 296 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { 297 EXPECT_EQ("#include \"a.h\"\n" 298 "#include \"c.h\"\n" 299 "\n" 300 "#include \"b.h\"\n", 301 sort("#include \"a.h\"\n" 302 "#include \"c.h\"\n" 303 "\n" 304 "#include \"b.h\"\n", 305 "input.h", 0)); 306 } 307 308 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { 309 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 310 EXPECT_EQ("#include \"a.h\"\n" 311 "#include \"b.h\"\n" 312 "#include \"c.h\"\n", 313 sort("#include \"a.h\"\n" 314 "#include \"c.h\"\n" 315 "\n" 316 "#include \"b.h\"\n")); 317 } 318 319 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { 320 EXPECT_EQ("#include \"a.h\"\n" 321 "#include \"c.h\"\n" 322 "// comment\n" 323 "#include \"b.h\"\n", 324 sort("#include \"c.h\"\n" 325 "#include \"a.h\"\n" 326 "// comment\n" 327 "#include \"b.h\"\n")); 328 329 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 330 EXPECT_EQ("#include \"a.h\"\n" 331 "#include \"c.h\"\n" 332 "// comment\n" 333 "#include \"b.h\"\n", 334 sort("#include \"c.h\"\n" 335 "#include \"a.h\"\n" 336 "// comment\n" 337 "#include \"b.h\"\n")); 338 339 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 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 350 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { 351 EXPECT_EQ("#include \"a.h\"\n" 352 "#include \"c.h\"\n" 353 "#include <array>\n" 354 "#include <b.h>\n" 355 "#include <d.h>\n" 356 "#include <vector>\n", 357 sort("#include <vector>\n" 358 "#include <d.h>\n" 359 "#include <array>\n" 360 "#include <b.h>\n" 361 "#include \"c.h\"\n" 362 "#include \"a.h\"\n")); 363 364 FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); 365 EXPECT_EQ("#include <b.h>\n" 366 "#include <d.h>\n" 367 "\n" 368 "#include <array>\n" 369 "#include <vector>\n" 370 "\n" 371 "#include \"a.h\"\n" 372 "#include \"c.h\"\n", 373 sort("#include <vector>\n" 374 "#include <d.h>\n" 375 "#include <array>\n" 376 "#include <b.h>\n" 377 "#include \"c.h\"\n" 378 "#include \"a.h\"\n")); 379 } 380 381 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { 382 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 383 EXPECT_EQ("#include \"a.h\"\n" 384 "#include \"c.h\"\n" 385 "\n" 386 "#include <b.h>\n" 387 "#include <d.h>\n", 388 sort("#include <d.h>\n" 389 "#include <b.h>\n" 390 "#include \"c.h\"\n" 391 "#include \"a.h\"\n")); 392 } 393 394 TEST_F(SortIncludesTest, HandlesMultilineIncludes) { 395 EXPECT_EQ("#include \"a.h\"\n" 396 "#include \"b.h\"\n" 397 "#include \"c.h\"\n", 398 sort("#include \"a.h\"\n" 399 "#include \\\n" 400 "\"c.h\"\n" 401 "#include \"b.h\"\n")); 402 } 403 404 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { 405 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 406 EXPECT_EQ("#include \"llvm/a.h\"\n" 407 "#include \"b.h\"\n" 408 "#include \"c.h\"\n", 409 sort("#include \"llvm/a.h\"\n" 410 "#include \"c.h\"\n" 411 "#include \"b.h\"\n", 412 "a.cc")); 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_test.cc")); 420 EXPECT_EQ("#include \"llvm/input.h\"\n" 421 "#include \"b.h\"\n" 422 "#include \"c.h\"\n", 423 sort("#include \"llvm/input.h\"\n" 424 "#include \"c.h\"\n" 425 "#include \"b.h\"\n", 426 "input.mm")); 427 428 // Don't allow prefixes. 429 EXPECT_EQ("#include \"b.h\"\n" 430 "#include \"c.h\"\n" 431 "#include \"llvm/not_a.h\"\n", 432 sort("#include \"llvm/not_a.h\"\n" 433 "#include \"c.h\"\n" 434 "#include \"b.h\"\n", 435 "a.cc")); 436 437 // Don't do this for _main and other suffixes. 438 EXPECT_EQ("#include \"b.h\"\n" 439 "#include \"c.h\"\n" 440 "#include \"llvm/a.h\"\n", 441 sort("#include \"llvm/a.h\"\n" 442 "#include \"c.h\"\n" 443 "#include \"b.h\"\n", 444 "a_main.cc")); 445 446 // Don't do this in headers. 447 EXPECT_EQ("#include \"b.h\"\n" 448 "#include \"c.h\"\n" 449 "#include \"llvm/a.h\"\n", 450 sort("#include \"llvm/a.h\"\n" 451 "#include \"c.h\"\n" 452 "#include \"b.h\"\n", 453 "a.h")); 454 455 // Only do this in the first #include block. 456 EXPECT_EQ("#include <a>\n" 457 "\n" 458 "#include \"b.h\"\n" 459 "#include \"c.h\"\n" 460 "#include \"llvm/a.h\"\n", 461 sort("#include <a>\n" 462 "\n" 463 "#include \"llvm/a.h\"\n" 464 "#include \"c.h\"\n" 465 "#include \"b.h\"\n", 466 "a.cc")); 467 468 // Only recognize the first #include with a matching basename as main include. 469 EXPECT_EQ("#include \"a.h\"\n" 470 "#include \"b.h\"\n" 471 "#include \"c.h\"\n" 472 "#include \"llvm/a.h\"\n", 473 sort("#include \"b.h\"\n" 474 "#include \"a.h\"\n" 475 "#include \"c.h\"\n" 476 "#include \"llvm/a.h\"\n", 477 "a.cc")); 478 } 479 480 TEST_F(SortIncludesTest, LeavesMainHeaderFirstInAdditionalExtensions) { 481 Style.IncludeIsMainRegex = "([-_](test|unittest))?|(Impl)?$"; 482 EXPECT_EQ("#include \"b.h\"\n" 483 "#include \"c.h\"\n" 484 "#include \"llvm/a.h\"\n", 485 sort("#include \"llvm/a.h\"\n" 486 "#include \"c.h\"\n" 487 "#include \"b.h\"\n", 488 "a_test.xxx")); 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 "aImpl.hpp")); 496 497 // .cpp extension is considered "main" by default 498 EXPECT_EQ("#include \"llvm/a.h\"\n" 499 "#include \"b.h\"\n" 500 "#include \"c.h\"\n", 501 sort("#include \"llvm/a.h\"\n" 502 "#include \"c.h\"\n" 503 "#include \"b.h\"\n", 504 "aImpl.cpp")); 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 "a_test.cpp")); 512 513 // Allow additional filenames / extensions 514 Style.IncludeIsMainSourceRegex = "(Impl\\.hpp)|(\\.xxx)$"; 515 EXPECT_EQ("#include \"llvm/a.h\"\n" 516 "#include \"b.h\"\n" 517 "#include \"c.h\"\n", 518 sort("#include \"llvm/a.h\"\n" 519 "#include \"c.h\"\n" 520 "#include \"b.h\"\n", 521 "a_test.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 "aImpl.hpp")); 529 } 530 531 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { 532 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 533 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 534 535 EXPECT_EQ("#include \"c.h\"\n" 536 "#include \"a.h\"\n" 537 "#include \"b.h\"\n", 538 sort("#include \"b.h\"\n" 539 "\n" 540 "#include \"a.h\"\n" 541 "#include \"c.h\"\n", 542 "c.cc")); 543 } 544 545 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { 546 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 547 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 548 549 EXPECT_EQ("#include \"a.h\"\n" 550 "\n" 551 "#include \"b.h\"\n" 552 "#include \"c.h\"\n", 553 sort("#include \"b.h\"\n" 554 "\n" 555 "#include \"a.h\"\n" 556 "#include \"c.h\"\n", 557 "a.cc")); 558 } 559 560 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { 561 // Setup an regex for main includes so we can cover those as well. 562 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 563 564 // Ensure both main header detection and grouping work in a case insensitive 565 // manner. 566 EXPECT_EQ("#include \"llvm/A.h\"\n" 567 "#include \"b.h\"\n" 568 "#include \"c.h\"\n" 569 "#include \"LLVM/z.h\"\n" 570 "#include \"llvm/X.h\"\n" 571 "#include \"GTest/GTest.h\"\n" 572 "#include \"gmock/gmock.h\"\n", 573 sort("#include \"c.h\"\n" 574 "#include \"b.h\"\n" 575 "#include \"GTest/GTest.h\"\n" 576 "#include \"llvm/A.h\"\n" 577 "#include \"gmock/gmock.h\"\n" 578 "#include \"llvm/X.h\"\n" 579 "#include \"LLVM/z.h\"\n", 580 "a_TEST.cc")); 581 } 582 583 TEST_F(SortIncludesTest, NegativePriorities) { 584 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 585 EXPECT_EQ("#include \"important_os_header.h\"\n" 586 "#include \"c_main.h\"\n" 587 "#include \"a_other.h\"\n", 588 sort("#include \"c_main.h\"\n" 589 "#include \"a_other.h\"\n" 590 "#include \"important_os_header.h\"\n", 591 "c_main.cc")); 592 593 // check stable when re-run 594 EXPECT_EQ("#include \"important_os_header.h\"\n" 595 "#include \"c_main.h\"\n" 596 "#include \"a_other.h\"\n", 597 sort("#include \"important_os_header.h\"\n" 598 "#include \"c_main.h\"\n" 599 "#include \"a_other.h\"\n", 600 "c_main.cc", 0)); 601 } 602 603 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { 604 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 605 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 606 607 EXPECT_EQ("#include \"important_os_header.h\"\n" 608 "\n" 609 "#include \"c_main.h\"\n" 610 "\n" 611 "#include \"a_other.h\"\n", 612 sort("#include \"c_main.h\"\n" 613 "#include \"a_other.h\"\n" 614 "#include \"important_os_header.h\"\n", 615 "c_main.cc")); 616 617 // check stable when re-run 618 EXPECT_EQ("#include \"important_os_header.h\"\n" 619 "\n" 620 "#include \"c_main.h\"\n" 621 "\n" 622 "#include \"a_other.h\"\n", 623 sort("#include \"important_os_header.h\"\n" 624 "\n" 625 "#include \"c_main.h\"\n" 626 "\n" 627 "#include \"a_other.h\"\n", 628 "c_main.cc", 0)); 629 } 630 631 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 632 std::string Code = "#include <ccc>\n" // Start of line: 0 633 "#include <bbbbbb>\n" // Start of line: 15 634 "#include <a>\n"; // Start of line: 33 635 EXPECT_EQ(31u, newCursor(Code, 0)); 636 EXPECT_EQ(13u, newCursor(Code, 15)); 637 EXPECT_EQ(0u, newCursor(Code, 33)); 638 639 EXPECT_EQ(41u, newCursor(Code, 10)); 640 EXPECT_EQ(23u, newCursor(Code, 25)); 641 EXPECT_EQ(10u, newCursor(Code, 43)); 642 } 643 644 TEST_F(SortIncludesTest, DeduplicateIncludes) { 645 EXPECT_EQ("#include <a>\n" 646 "#include <b>\n" 647 "#include <c>\n", 648 sort("#include <a>\n" 649 "#include <b>\n" 650 "#include <b>\n" 651 "#include <b>\n" 652 "#include <b>\n" 653 "#include <c>\n")); 654 655 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 656 EXPECT_EQ("#include <a>\n" 657 "#include <b>\n" 658 "#include <c>\n", 659 sort("#include <a>\n" 660 "#include <b>\n" 661 "\n" 662 "#include <b>\n" 663 "\n" 664 "#include <b>\n" 665 "#include <c>\n")); 666 667 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 668 EXPECT_EQ("#include <a>\n" 669 "#include <b>\n" 670 "#include <c>\n", 671 sort("#include <a>\n" 672 "#include <b>\n" 673 "\n" 674 "#include <b>\n" 675 "\n" 676 "#include <b>\n" 677 "#include <c>\n")); 678 } 679 680 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 681 EXPECT_EQ("#include <a>\n" 682 "#include <b>\n" 683 "#include <c>\n", 684 sort("#include <b>\n" 685 "#include <a>\n" 686 "#include <b>\n" 687 "#include <b>\n" 688 "#include <c>\n" 689 "#include <b>\n")); 690 691 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 692 EXPECT_EQ("#include <a>\n" 693 "#include <b>\n" 694 "#include <c>\n", 695 sort("#include <b>\n" 696 "#include <a>\n" 697 "\n" 698 "#include <b>\n" 699 "\n" 700 "#include <c>\n" 701 "#include <b>\n")); 702 703 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 704 EXPECT_EQ("#include <a>\n" 705 "#include <b>\n" 706 "#include <c>\n", 707 sort("#include <b>\n" 708 "#include <a>\n" 709 "\n" 710 "#include <b>\n" 711 "\n" 712 "#include <c>\n" 713 "#include <b>\n")); 714 } 715 716 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 717 std::string Code = "#include <b>\n" // Start of line: 0 718 "#include <a>\n" // Start of line: 13 719 "#include <b>\n" // Start of line: 26 720 "#include <b>\n" // Start of line: 39 721 "#include <c>\n" // Start of line: 52 722 "#include <b>\n"; // Start of line: 65 723 std::string Expected = "#include <a>\n" // Start of line: 0 724 "#include <b>\n" // Start of line: 13 725 "#include <c>\n"; // Start of line: 26 726 EXPECT_EQ(Expected, sort(Code)); 727 // Cursor on 'i' in "#include <a>". 728 EXPECT_EQ(1u, newCursor(Code, 14)); 729 // Cursor on 'b' in "#include <b>". 730 EXPECT_EQ(23u, newCursor(Code, 10)); 731 EXPECT_EQ(23u, newCursor(Code, 36)); 732 EXPECT_EQ(23u, newCursor(Code, 49)); 733 EXPECT_EQ(23u, newCursor(Code, 36)); 734 EXPECT_EQ(23u, newCursor(Code, 75)); 735 // Cursor on '#' in "#include <c>". 736 EXPECT_EQ(26u, newCursor(Code, 52)); 737 } 738 739 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 740 EXPECT_EQ("#include <a>\n" 741 "#include <b>\n" 742 "\n" 743 "#include <b>\n" 744 "#include <c>\n", 745 sort("#include <a>\n" 746 "#include <b>\n" 747 "\n" 748 "#include <c>\n" 749 "#include <b>\n" 750 "#include <b>\n")); 751 } 752 753 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 754 std::string Code = "#include <a>\n" 755 "#include <b>\n" 756 "#include <a>\n" 757 "#include <a>\n" 758 "\n" 759 " int x ;"; 760 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 761 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); 762 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 763 EXPECT_EQ(1u, Ranges.size()); 764 EXPECT_EQ(0u, Ranges[0].getOffset()); 765 EXPECT_EQ(26u, Ranges[0].getLength()); 766 } 767 768 TEST_F(SortIncludesTest, DoNotSortLikelyXml) { 769 EXPECT_EQ("<!--;\n" 770 "#include <b>\n" 771 "#include <a>\n" 772 "-->", 773 sort("<!--;\n" 774 "#include <b>\n" 775 "#include <a>\n" 776 "-->", 777 "input.h", 0)); 778 } 779 780 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { 781 Style.IncludeBlocks = Style.IBS_Regroup; 782 std::string Code = R"( 783 #include "b.h" 784 785 #include <a.h> 786 )"; 787 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 788 } 789 790 TEST_F(SortIncludesTest, 791 DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { 792 Style.IncludeBlocks = Style.IBS_Regroup; 793 std::string Code = "#include \"b.h\"\r\n" 794 "\r\n" 795 "#include <a.h>\r\n"; 796 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 797 } 798 799 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { 800 FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC); 801 802 EXPECT_EQ("#include <a.h>\n" 803 "#include <b.h>\n" 804 "#include \"a.h\"", 805 sort("#include <b.h>\n" 806 "#include <a.h>\n" 807 "#include \"a.h\"")); 808 } 809 810 } // end namespace 811 } // end namespace format 812 } // end namespace clang 813