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, false}, 76 {"^<sys/types\\.h>", 1, 1, false}, 77 {"^<sys.*/", 1, 2, false}, 78 {"^<uvm/", 2, 3, false}, 79 {"^<machine/", 3, 4, false}, 80 {"^<dev/", 4, 5, false}, 81 {"^<net.*/", 5, 6, false}, 82 {"^<protocols/", 5, 7, false}, 83 {"^<(fs|miscfs|msdosfs|nfs|ntfs|ufs)/", 6, 8, false}, 84 {"^<(x86|amd64|i386|xen)/", 7, 8, false}, 85 {"<path", 9, 11, false}, 86 {"^<[^/].*\\.h>", 8, 10, false}, 87 {"^\".*\\.h\"", 10, 12, false}}; 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, SupportOptionalCaseSensitiveMachting) { 604 Style.IncludeBlocks = clang::tooling::IncludeStyle::IBS_Regroup; 605 Style.IncludeCategories = {{"^\"", 1, 0, false}, 606 {"^<.*\\.h>$", 2, 0, false}, 607 {"^<Q[A-Z][^\\.]*>", 3, 0, false}, 608 {"^<Qt[^\\.]*>", 4, 0, false}, 609 {"^<", 5, 0, false}}; 610 611 StringRef UnsortedCode = "#include <QWidget>\n" 612 "#include \"qt.h\"\n" 613 "#include <algorithm>\n" 614 "#include <windows.h>\n" 615 "#include <QLabel>\n" 616 "#include \"qa.h\"\n" 617 "#include <queue>\n" 618 "#include <qtwhatever.h>\n" 619 "#include <QtGlobal>\n"; 620 621 EXPECT_EQ("#include \"qa.h\"\n" 622 "#include \"qt.h\"\n" 623 "\n" 624 "#include <qtwhatever.h>\n" 625 "#include <windows.h>\n" 626 "\n" 627 "#include <QLabel>\n" 628 "#include <QWidget>\n" 629 "#include <QtGlobal>\n" 630 "#include <queue>\n" 631 "\n" 632 "#include <algorithm>\n", 633 sort(UnsortedCode)); 634 635 Style.IncludeCategories[2].RegexIsCaseSensitive = true; 636 Style.IncludeCategories[3].RegexIsCaseSensitive = true; 637 EXPECT_EQ("#include \"qa.h\"\n" 638 "#include \"qt.h\"\n" 639 "\n" 640 "#include <qtwhatever.h>\n" 641 "#include <windows.h>\n" 642 "\n" 643 "#include <QLabel>\n" 644 "#include <QWidget>\n" 645 "\n" 646 "#include <QtGlobal>\n" 647 "\n" 648 "#include <algorithm>\n" 649 "#include <queue>\n", 650 sort(UnsortedCode)); 651 } 652 653 TEST_F(SortIncludesTest, NegativePriorities) { 654 Style.IncludeCategories = {{".*important_os_header.*", -1, 0, false}, 655 {".*", 1, 0, false}}; 656 EXPECT_EQ("#include \"important_os_header.h\"\n" 657 "#include \"c_main.h\"\n" 658 "#include \"a_other.h\"\n", 659 sort("#include \"c_main.h\"\n" 660 "#include \"a_other.h\"\n" 661 "#include \"important_os_header.h\"\n", 662 "c_main.cc")); 663 664 // check stable when re-run 665 EXPECT_EQ("#include \"important_os_header.h\"\n" 666 "#include \"c_main.h\"\n" 667 "#include \"a_other.h\"\n", 668 sort("#include \"important_os_header.h\"\n" 669 "#include \"c_main.h\"\n" 670 "#include \"a_other.h\"\n", 671 "c_main.cc", 0)); 672 } 673 674 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { 675 Style.IncludeCategories = {{".*important_os_header.*", -1, 0, false}, 676 {".*", 1, 0, false}}; 677 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 678 679 EXPECT_EQ("#include \"important_os_header.h\"\n" 680 "\n" 681 "#include \"c_main.h\"\n" 682 "\n" 683 "#include \"a_other.h\"\n", 684 sort("#include \"c_main.h\"\n" 685 "#include \"a_other.h\"\n" 686 "#include \"important_os_header.h\"\n", 687 "c_main.cc")); 688 689 // check stable when re-run 690 EXPECT_EQ("#include \"important_os_header.h\"\n" 691 "\n" 692 "#include \"c_main.h\"\n" 693 "\n" 694 "#include \"a_other.h\"\n", 695 sort("#include \"important_os_header.h\"\n" 696 "\n" 697 "#include \"c_main.h\"\n" 698 "\n" 699 "#include \"a_other.h\"\n", 700 "c_main.cc", 0)); 701 } 702 703 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 704 std::string Code = "#include <ccc>\n" // Start of line: 0 705 "#include <bbbbbb>\n" // Start of line: 15 706 "#include <a>\n"; // Start of line: 33 707 EXPECT_EQ(31u, newCursor(Code, 0)); 708 EXPECT_EQ(13u, newCursor(Code, 15)); 709 EXPECT_EQ(0u, newCursor(Code, 33)); 710 711 EXPECT_EQ(41u, newCursor(Code, 10)); 712 EXPECT_EQ(23u, newCursor(Code, 25)); 713 EXPECT_EQ(10u, newCursor(Code, 43)); 714 } 715 716 TEST_F(SortIncludesTest, DeduplicateIncludes) { 717 EXPECT_EQ("#include <a>\n" 718 "#include <b>\n" 719 "#include <c>\n", 720 sort("#include <a>\n" 721 "#include <b>\n" 722 "#include <b>\n" 723 "#include <b>\n" 724 "#include <b>\n" 725 "#include <c>\n")); 726 727 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 728 EXPECT_EQ("#include <a>\n" 729 "#include <b>\n" 730 "#include <c>\n", 731 sort("#include <a>\n" 732 "#include <b>\n" 733 "\n" 734 "#include <b>\n" 735 "\n" 736 "#include <b>\n" 737 "#include <c>\n")); 738 739 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 740 EXPECT_EQ("#include <a>\n" 741 "#include <b>\n" 742 "#include <c>\n", 743 sort("#include <a>\n" 744 "#include <b>\n" 745 "\n" 746 "#include <b>\n" 747 "\n" 748 "#include <b>\n" 749 "#include <c>\n")); 750 } 751 752 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 753 EXPECT_EQ("#include <a>\n" 754 "#include <b>\n" 755 "#include <c>\n", 756 sort("#include <b>\n" 757 "#include <a>\n" 758 "#include <b>\n" 759 "#include <b>\n" 760 "#include <c>\n" 761 "#include <b>\n")); 762 763 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 764 EXPECT_EQ("#include <a>\n" 765 "#include <b>\n" 766 "#include <c>\n", 767 sort("#include <b>\n" 768 "#include <a>\n" 769 "\n" 770 "#include <b>\n" 771 "\n" 772 "#include <c>\n" 773 "#include <b>\n")); 774 775 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 776 EXPECT_EQ("#include <a>\n" 777 "#include <b>\n" 778 "#include <c>\n", 779 sort("#include <b>\n" 780 "#include <a>\n" 781 "\n" 782 "#include <b>\n" 783 "\n" 784 "#include <c>\n" 785 "#include <b>\n")); 786 } 787 788 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 789 std::string Code = "#include <b>\n" // Start of line: 0 790 "#include <a>\n" // Start of line: 13 791 "#include <b>\n" // Start of line: 26 792 "#include <b>\n" // Start of line: 39 793 "#include <c>\n" // Start of line: 52 794 "#include <b>\n"; // Start of line: 65 795 std::string Expected = "#include <a>\n" // Start of line: 0 796 "#include <b>\n" // Start of line: 13 797 "#include <c>\n"; // Start of line: 26 798 EXPECT_EQ(Expected, sort(Code)); 799 // Cursor on 'i' in "#include <a>". 800 EXPECT_EQ(1u, newCursor(Code, 14)); 801 // Cursor on 'b' in "#include <b>". 802 EXPECT_EQ(23u, newCursor(Code, 10)); 803 EXPECT_EQ(23u, newCursor(Code, 36)); 804 EXPECT_EQ(23u, newCursor(Code, 49)); 805 EXPECT_EQ(23u, newCursor(Code, 36)); 806 EXPECT_EQ(23u, newCursor(Code, 75)); 807 // Cursor on '#' in "#include <c>". 808 EXPECT_EQ(26u, newCursor(Code, 52)); 809 } 810 811 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 812 EXPECT_EQ("#include <a>\n" 813 "#include <b>\n" 814 "\n" 815 "#include <b>\n" 816 "#include <c>\n", 817 sort("#include <a>\n" 818 "#include <b>\n" 819 "\n" 820 "#include <c>\n" 821 "#include <b>\n" 822 "#include <b>\n")); 823 } 824 825 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 826 std::string Code = "#include <a>\n" 827 "#include <b>\n" 828 "#include <a>\n" 829 "#include <a>\n" 830 "\n" 831 " int x ;"; 832 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 833 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); 834 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 835 EXPECT_EQ(1u, Ranges.size()); 836 EXPECT_EQ(0u, Ranges[0].getOffset()); 837 EXPECT_EQ(26u, Ranges[0].getLength()); 838 } 839 840 TEST_F(SortIncludesTest, DoNotSortLikelyXml) { 841 EXPECT_EQ("<!--;\n" 842 "#include <b>\n" 843 "#include <a>\n" 844 "-->", 845 sort("<!--;\n" 846 "#include <b>\n" 847 "#include <a>\n" 848 "-->", 849 "input.h", 0)); 850 } 851 852 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { 853 Style.IncludeBlocks = Style.IBS_Regroup; 854 std::string Code = R"( 855 #include "b.h" 856 857 #include <a.h> 858 )"; 859 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 860 } 861 862 TEST_F(SortIncludesTest, 863 DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { 864 Style.IncludeBlocks = Style.IBS_Regroup; 865 std::string Code = "#include \"b.h\"\r\n" 866 "\r\n" 867 "#include <a.h>\r\n"; 868 EXPECT_EQ(Code, sort(Code, "input.h", 0)); 869 } 870 871 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { 872 FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC); 873 874 EXPECT_EQ("#include <a.h>\n" 875 "#include <b.h>\n" 876 "#include \"a.h\"", 877 sort("#include <b.h>\n" 878 "#include <a.h>\n" 879 "#include \"a.h\"")); 880 } 881 882 } // end namespace 883 } // end namespace format 884 } // end namespace clang 885