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, LeavesMainHeaderFirstInAdditionalExtensions) { 470 Style.IncludeIsMainRegex = "([-_](test|unittest))?|(Impl)?$"; 471 EXPECT_EQ("#include \"b.h\"\n" 472 "#include \"c.h\"\n" 473 "#include \"llvm/a.h\"\n", 474 sort("#include \"llvm/a.h\"\n" 475 "#include \"c.h\"\n" 476 "#include \"b.h\"\n", 477 "a_test.xxx")); 478 EXPECT_EQ("#include \"b.h\"\n" 479 "#include \"c.h\"\n" 480 "#include \"llvm/a.h\"\n", 481 sort("#include \"llvm/a.h\"\n" 482 "#include \"c.h\"\n" 483 "#include \"b.h\"\n", 484 "aImpl.hpp")); 485 486 // .cpp extension is considered "main" by default 487 EXPECT_EQ("#include \"llvm/a.h\"\n" 488 "#include \"b.h\"\n" 489 "#include \"c.h\"\n", 490 sort("#include \"llvm/a.h\"\n" 491 "#include \"c.h\"\n" 492 "#include \"b.h\"\n", 493 "aImpl.cpp")); 494 EXPECT_EQ("#include \"llvm/a.h\"\n" 495 "#include \"b.h\"\n" 496 "#include \"c.h\"\n", 497 sort("#include \"llvm/a.h\"\n" 498 "#include \"c.h\"\n" 499 "#include \"b.h\"\n", 500 "a_test.cpp")); 501 502 // Allow additional filenames / extensions 503 Style.IncludeIsMainSourceRegex = "(Impl\\.hpp)|(\\.xxx)$"; 504 EXPECT_EQ("#include \"llvm/a.h\"\n" 505 "#include \"b.h\"\n" 506 "#include \"c.h\"\n", 507 sort("#include \"llvm/a.h\"\n" 508 "#include \"c.h\"\n" 509 "#include \"b.h\"\n", 510 "a_test.xxx")); 511 EXPECT_EQ("#include \"llvm/a.h\"\n" 512 "#include \"b.h\"\n" 513 "#include \"c.h\"\n", 514 sort("#include \"llvm/a.h\"\n" 515 "#include \"c.h\"\n" 516 "#include \"b.h\"\n", 517 "aImpl.hpp")); 518 } 519 520 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { 521 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 522 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 523 524 EXPECT_EQ("#include \"c.h\"\n" 525 "#include \"a.h\"\n" 526 "#include \"b.h\"\n", 527 sort("#include \"b.h\"\n" 528 "\n" 529 "#include \"a.h\"\n" 530 "#include \"c.h\"\n", 531 "c.cc")); 532 } 533 534 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { 535 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 536 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 537 538 EXPECT_EQ("#include \"a.h\"\n" 539 "\n" 540 "#include \"b.h\"\n" 541 "#include \"c.h\"\n", 542 sort("#include \"b.h\"\n" 543 "\n" 544 "#include \"a.h\"\n" 545 "#include \"c.h\"\n", 546 "a.cc")); 547 } 548 549 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { 550 // Setup an regex for main includes so we can cover those as well. 551 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 552 553 // Ensure both main header detection and grouping work in a case insensitive 554 // manner. 555 EXPECT_EQ("#include \"llvm/A.h\"\n" 556 "#include \"b.h\"\n" 557 "#include \"c.h\"\n" 558 "#include \"LLVM/z.h\"\n" 559 "#include \"llvm/X.h\"\n" 560 "#include \"GTest/GTest.h\"\n" 561 "#include \"gmock/gmock.h\"\n", 562 sort("#include \"c.h\"\n" 563 "#include \"b.h\"\n" 564 "#include \"GTest/GTest.h\"\n" 565 "#include \"llvm/A.h\"\n" 566 "#include \"gmock/gmock.h\"\n" 567 "#include \"llvm/X.h\"\n" 568 "#include \"LLVM/z.h\"\n", 569 "a_TEST.cc")); 570 } 571 572 TEST_F(SortIncludesTest, NegativePriorities) { 573 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 574 EXPECT_EQ("#include \"important_os_header.h\"\n" 575 "#include \"c_main.h\"\n" 576 "#include \"a_other.h\"\n", 577 sort("#include \"c_main.h\"\n" 578 "#include \"a_other.h\"\n" 579 "#include \"important_os_header.h\"\n", 580 "c_main.cc")); 581 582 // check stable when re-run 583 EXPECT_EQ("#include \"important_os_header.h\"\n" 584 "#include \"c_main.h\"\n" 585 "#include \"a_other.h\"\n", 586 sort("#include \"important_os_header.h\"\n" 587 "#include \"c_main.h\"\n" 588 "#include \"a_other.h\"\n", 589 "c_main.cc", 0)); 590 } 591 592 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { 593 Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; 594 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 595 596 EXPECT_EQ("#include \"important_os_header.h\"\n" 597 "\n" 598 "#include \"c_main.h\"\n" 599 "\n" 600 "#include \"a_other.h\"\n", 601 sort("#include \"c_main.h\"\n" 602 "#include \"a_other.h\"\n" 603 "#include \"important_os_header.h\"\n", 604 "c_main.cc")); 605 606 // check stable when re-run 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 \"important_os_header.h\"\n" 613 "\n" 614 "#include \"c_main.h\"\n" 615 "\n" 616 "#include \"a_other.h\"\n", 617 "c_main.cc", 0)); 618 } 619 620 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 621 std::string Code = "#include <ccc>\n" // Start of line: 0 622 "#include <bbbbbb>\n" // Start of line: 15 623 "#include <a>\n"; // Start of line: 33 624 EXPECT_EQ(31u, newCursor(Code, 0)); 625 EXPECT_EQ(13u, newCursor(Code, 15)); 626 EXPECT_EQ(0u, newCursor(Code, 33)); 627 628 EXPECT_EQ(41u, newCursor(Code, 10)); 629 EXPECT_EQ(23u, newCursor(Code, 25)); 630 EXPECT_EQ(10u, newCursor(Code, 43)); 631 } 632 633 TEST_F(SortIncludesTest, DeduplicateIncludes) { 634 EXPECT_EQ("#include <a>\n" 635 "#include <b>\n" 636 "#include <c>\n", 637 sort("#include <a>\n" 638 "#include <b>\n" 639 "#include <b>\n" 640 "#include <b>\n" 641 "#include <b>\n" 642 "#include <c>\n")); 643 644 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 645 EXPECT_EQ("#include <a>\n" 646 "#include <b>\n" 647 "#include <c>\n", 648 sort("#include <a>\n" 649 "#include <b>\n" 650 "\n" 651 "#include <b>\n" 652 "\n" 653 "#include <b>\n" 654 "#include <c>\n")); 655 656 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 657 EXPECT_EQ("#include <a>\n" 658 "#include <b>\n" 659 "#include <c>\n", 660 sort("#include <a>\n" 661 "#include <b>\n" 662 "\n" 663 "#include <b>\n" 664 "\n" 665 "#include <b>\n" 666 "#include <c>\n")); 667 } 668 669 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 670 EXPECT_EQ("#include <a>\n" 671 "#include <b>\n" 672 "#include <c>\n", 673 sort("#include <b>\n" 674 "#include <a>\n" 675 "#include <b>\n" 676 "#include <b>\n" 677 "#include <c>\n" 678 "#include <b>\n")); 679 680 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 681 EXPECT_EQ("#include <a>\n" 682 "#include <b>\n" 683 "#include <c>\n", 684 sort("#include <b>\n" 685 "#include <a>\n" 686 "\n" 687 "#include <b>\n" 688 "\n" 689 "#include <c>\n" 690 "#include <b>\n")); 691 692 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 693 EXPECT_EQ("#include <a>\n" 694 "#include <b>\n" 695 "#include <c>\n", 696 sort("#include <b>\n" 697 "#include <a>\n" 698 "\n" 699 "#include <b>\n" 700 "\n" 701 "#include <c>\n" 702 "#include <b>\n")); 703 } 704 705 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 706 std::string Code = "#include <b>\n" // Start of line: 0 707 "#include <a>\n" // Start of line: 13 708 "#include <b>\n" // Start of line: 26 709 "#include <b>\n" // Start of line: 39 710 "#include <c>\n" // Start of line: 52 711 "#include <b>\n"; // Start of line: 65 712 std::string Expected = "#include <a>\n" // Start of line: 0 713 "#include <b>\n" // Start of line: 13 714 "#include <c>\n"; // Start of line: 26 715 EXPECT_EQ(Expected, sort(Code)); 716 // Cursor on 'i' in "#include <a>". 717 EXPECT_EQ(1u, newCursor(Code, 14)); 718 // Cursor on 'b' in "#include <b>". 719 EXPECT_EQ(23u, newCursor(Code, 10)); 720 EXPECT_EQ(23u, newCursor(Code, 36)); 721 EXPECT_EQ(23u, newCursor(Code, 49)); 722 EXPECT_EQ(23u, newCursor(Code, 36)); 723 EXPECT_EQ(23u, newCursor(Code, 75)); 724 // Cursor on '#' in "#include <c>". 725 EXPECT_EQ(26u, newCursor(Code, 52)); 726 } 727 728 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 729 EXPECT_EQ("#include <a>\n" 730 "#include <b>\n" 731 "\n" 732 "#include <b>\n" 733 "#include <c>\n", 734 sort("#include <a>\n" 735 "#include <b>\n" 736 "\n" 737 "#include <c>\n" 738 "#include <b>\n" 739 "#include <b>\n")); 740 } 741 742 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 743 std::string Code = "#include <a>\n" 744 "#include <b>\n" 745 "#include <a>\n" 746 "#include <a>\n" 747 "\n" 748 " int x ;"; 749 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 750 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); 751 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 752 EXPECT_EQ(1u, Ranges.size()); 753 EXPECT_EQ(0u, Ranges[0].getOffset()); 754 EXPECT_EQ(26u, Ranges[0].getLength()); 755 } 756 757 TEST_F(SortIncludesTest, DoNotSortLikelyXml) { 758 EXPECT_EQ("<!--;\n" 759 "#include <b>\n" 760 "#include <a>\n" 761 "-->", 762 sort("<!--;\n" 763 "#include <b>\n" 764 "#include <a>\n" 765 "-->", "input.h", 0)); 766 } 767 768 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { 769 Style.IncludeBlocks = Style.IBS_Regroup; 770 std::string Code = R"( 771 #include "b.h" 772 773 #include <a.h> 774 )"; 775 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 776 } 777 778 TEST_F(SortIncludesTest, 779 DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { 780 Style.IncludeBlocks = Style.IBS_Regroup; 781 std::string Code = "#include \"b.h\"\r\n" 782 "\r\n" 783 "#include <a.h>\r\n"; 784 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 785 } 786 787 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { 788 FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC); 789 790 EXPECT_EQ("#include <a.h>\n" 791 "#include <b.h>\n" 792 "#include \"a.h\"", 793 sort("#include <b.h>\n" 794 "#include <a.h>\n" 795 "#include \"a.h\"")); 796 } 797 798 } // end namespace 799 } // end namespace format 800 } // end namespace clang 801