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