1 //===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "FormatTestUtils.h" 11 #include "clang/Format/Format.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 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName); 30 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 31 auto Sorted = applyAllReplacements(Code, Replaces); 32 EXPECT_TRUE(static_cast<bool>(Sorted)); 33 auto Result = applyAllReplacements( 34 *Sorted, reformat(FmtStyle, *Sorted, Ranges, FileName)); 35 EXPECT_TRUE(static_cast<bool>(Result)); 36 return *Result; 37 } 38 39 std::string sort(StringRef Code, StringRef FileName = "input.cpp") { 40 return sort(Code, GetCodeRange(Code), FileName); 41 } 42 43 unsigned newCursor(llvm::StringRef Code, unsigned Cursor) { 44 sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.cpp", &Cursor); 45 return Cursor; 46 } 47 48 FormatStyle FmtStyle = getLLVMStyle(); 49 tooling::IncludeStyle &Style = FmtStyle.IncludeStyle; 50 }; 51 52 TEST_F(SortIncludesTest, BasicSorting) { 53 EXPECT_EQ("#include \"a.h\"\n" 54 "#include \"b.h\"\n" 55 "#include \"c.h\"\n", 56 sort("#include \"a.h\"\n" 57 "#include \"c.h\"\n" 58 "#include \"b.h\"\n")); 59 60 EXPECT_EQ("// comment\n" 61 "#include <a>\n" 62 "#include <b>\n", 63 sort("// comment\n" 64 "#include <b>\n" 65 "#include <a>\n", 66 {tooling::Range(25, 1)})); 67 } 68 69 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) { 70 // Identical #includes have led to a failure with an unstable sort. 71 std::string Code = "#include <a>\n" 72 "#include <b>\n" 73 "#include <c>\n" 74 "#include <d>\n" 75 "#include <e>\n" 76 "#include <f>\n"; 77 EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty()); 78 } 79 80 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { 81 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 82 EXPECT_EQ("#include \"a.h\"\n" 83 "#include \"b.h\"\n" 84 "#include \"c.h\"\n", 85 sort("#include \"a.h\"\n" 86 "#include \"c.h\"\n" 87 "\n" 88 "\n" 89 "#include \"b.h\"\n")); 90 91 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 92 EXPECT_EQ("#include \"a.h\"\n" 93 "#include \"b.h\"\n" 94 "#include \"c.h\"\n", 95 sort("#include \"a.h\"\n" 96 "#include \"c.h\"\n" 97 "\n" 98 "\n" 99 "#include \"b.h\"\n")); 100 } 101 102 TEST_F(SortIncludesTest, SupportClangFormatOff) { 103 EXPECT_EQ("#include <a>\n" 104 "#include <b>\n" 105 "#include <c>\n" 106 "// clang-format off\n" 107 "#include <b>\n" 108 "#include <a>\n" 109 "#include <c>\n" 110 "// clang-format on\n", 111 sort("#include <b>\n" 112 "#include <a>\n" 113 "#include <c>\n" 114 "// clang-format off\n" 115 "#include <b>\n" 116 "#include <a>\n" 117 "#include <c>\n" 118 "// clang-format on\n")); 119 } 120 121 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { 122 FmtStyle.SortIncludes = false; 123 EXPECT_EQ("#include \"a.h\"\n" 124 "#include \"c.h\"\n" 125 "#include \"b.h\"\n", 126 sort("#include \"a.h\"\n" 127 "#include \"c.h\"\n" 128 "#include \"b.h\"\n")); 129 } 130 131 TEST_F(SortIncludesTest, MixIncludeAndImport) { 132 EXPECT_EQ("#include \"a.h\"\n" 133 "#import \"b.h\"\n" 134 "#include \"c.h\"\n", 135 sort("#include \"a.h\"\n" 136 "#include \"c.h\"\n" 137 "#import \"b.h\"\n")); 138 } 139 140 TEST_F(SortIncludesTest, FixTrailingComments) { 141 EXPECT_EQ("#include \"a.h\" // comment\n" 142 "#include \"bb.h\" // comment\n" 143 "#include \"ccc.h\"\n", 144 sort("#include \"a.h\" // comment\n" 145 "#include \"ccc.h\"\n" 146 "#include \"bb.h\" // comment\n")); 147 } 148 149 TEST_F(SortIncludesTest, LeadingWhitespace) { 150 EXPECT_EQ("#include \"a.h\"\n" 151 "#include \"b.h\"\n" 152 "#include \"c.h\"\n", 153 sort(" #include \"a.h\"\n" 154 " #include \"c.h\"\n" 155 " #include \"b.h\"\n")); 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 "# include \"b.h\"\n")); 162 } 163 164 TEST_F(SortIncludesTest, GreaterInComment) { 165 EXPECT_EQ("#include \"a.h\"\n" 166 "#include \"b.h\" // >\n" 167 "#include \"c.h\"\n", 168 sort("#include \"a.h\"\n" 169 "#include \"c.h\"\n" 170 "#include \"b.h\" // >\n")); 171 } 172 173 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { 174 EXPECT_EQ("#include \"a.h\"\n" 175 "#include \"c.h\"\n" 176 "\n" 177 "#include \"b.h\"\n", 178 sort("#include \"a.h\"\n" 179 "#include \"c.h\"\n" 180 "\n" 181 "#include \"b.h\"\n")); 182 } 183 184 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { 185 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 186 EXPECT_EQ("#include \"a.h\"\n" 187 "#include \"b.h\"\n" 188 "#include \"c.h\"\n", 189 sort("#include \"a.h\"\n" 190 "#include \"c.h\"\n" 191 "\n" 192 "#include \"b.h\"\n")); 193 } 194 195 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { 196 EXPECT_EQ("#include \"a.h\"\n" 197 "#include \"c.h\"\n" 198 "// comment\n" 199 "#include \"b.h\"\n", 200 sort("#include \"c.h\"\n" 201 "#include \"a.h\"\n" 202 "// comment\n" 203 "#include \"b.h\"\n")); 204 205 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 206 EXPECT_EQ("#include \"a.h\"\n" 207 "#include \"c.h\"\n" 208 "// comment\n" 209 "#include \"b.h\"\n", 210 sort("#include \"c.h\"\n" 211 "#include \"a.h\"\n" 212 "// comment\n" 213 "#include \"b.h\"\n")); 214 215 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 216 EXPECT_EQ("#include \"a.h\"\n" 217 "#include \"c.h\"\n" 218 "// comment\n" 219 "#include \"b.h\"\n", 220 sort("#include \"c.h\"\n" 221 "#include \"a.h\"\n" 222 "// comment\n" 223 "#include \"b.h\"\n")); 224 } 225 226 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { 227 EXPECT_EQ("#include \"a.h\"\n" 228 "#include \"c.h\"\n" 229 "#include <b.h>\n" 230 "#include <d.h>\n", 231 sort("#include <d.h>\n" 232 "#include <b.h>\n" 233 "#include \"c.h\"\n" 234 "#include \"a.h\"\n")); 235 236 FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); 237 EXPECT_EQ("#include <b.h>\n" 238 "#include <d.h>\n" 239 "#include \"a.h\"\n" 240 "#include \"c.h\"\n", 241 sort("#include <d.h>\n" 242 "#include <b.h>\n" 243 "#include \"c.h\"\n" 244 "#include \"a.h\"\n")); 245 } 246 247 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { 248 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 249 EXPECT_EQ("#include \"a.h\"\n" 250 "#include \"c.h\"\n" 251 "\n" 252 "#include <b.h>\n" 253 "#include <d.h>\n", 254 sort("#include <d.h>\n" 255 "#include <b.h>\n" 256 "#include \"c.h\"\n" 257 "#include \"a.h\"\n")); 258 } 259 260 TEST_F(SortIncludesTest, HandlesMultilineIncludes) { 261 EXPECT_EQ("#include \"a.h\"\n" 262 "#include \"b.h\"\n" 263 "#include \"c.h\"\n", 264 sort("#include \"a.h\"\n" 265 "#include \\\n" 266 "\"c.h\"\n" 267 "#include \"b.h\"\n")); 268 } 269 270 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { 271 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 272 EXPECT_EQ("#include \"llvm/a.h\"\n" 273 "#include \"b.h\"\n" 274 "#include \"c.h\"\n", 275 sort("#include \"llvm/a.h\"\n" 276 "#include \"c.h\"\n" 277 "#include \"b.h\"\n", 278 "a.cc")); 279 EXPECT_EQ("#include \"llvm/a.h\"\n" 280 "#include \"b.h\"\n" 281 "#include \"c.h\"\n", 282 sort("#include \"llvm/a.h\"\n" 283 "#include \"c.h\"\n" 284 "#include \"b.h\"\n", 285 "a_test.cc")); 286 EXPECT_EQ("#include \"llvm/input.h\"\n" 287 "#include \"b.h\"\n" 288 "#include \"c.h\"\n", 289 sort("#include \"llvm/input.h\"\n" 290 "#include \"c.h\"\n" 291 "#include \"b.h\"\n", 292 "input.mm")); 293 294 // Don't allow prefixes. 295 EXPECT_EQ("#include \"b.h\"\n" 296 "#include \"c.h\"\n" 297 "#include \"llvm/not_a.h\"\n", 298 sort("#include \"llvm/not_a.h\"\n" 299 "#include \"c.h\"\n" 300 "#include \"b.h\"\n", 301 "a.cc")); 302 303 // Don't do this for _main and other suffixes. 304 EXPECT_EQ("#include \"b.h\"\n" 305 "#include \"c.h\"\n" 306 "#include \"llvm/a.h\"\n", 307 sort("#include \"llvm/a.h\"\n" 308 "#include \"c.h\"\n" 309 "#include \"b.h\"\n", 310 "a_main.cc")); 311 312 // Don't do this in headers. 313 EXPECT_EQ("#include \"b.h\"\n" 314 "#include \"c.h\"\n" 315 "#include \"llvm/a.h\"\n", 316 sort("#include \"llvm/a.h\"\n" 317 "#include \"c.h\"\n" 318 "#include \"b.h\"\n", 319 "a.h")); 320 321 // Only do this in the first #include block. 322 EXPECT_EQ("#include <a>\n" 323 "\n" 324 "#include \"b.h\"\n" 325 "#include \"c.h\"\n" 326 "#include \"llvm/a.h\"\n", 327 sort("#include <a>\n" 328 "\n" 329 "#include \"llvm/a.h\"\n" 330 "#include \"c.h\"\n" 331 "#include \"b.h\"\n", 332 "a.cc")); 333 334 // Only recognize the first #include with a matching basename as main include. 335 EXPECT_EQ("#include \"a.h\"\n" 336 "#include \"b.h\"\n" 337 "#include \"c.h\"\n" 338 "#include \"llvm/a.h\"\n", 339 sort("#include \"b.h\"\n" 340 "#include \"a.h\"\n" 341 "#include \"c.h\"\n" 342 "#include \"llvm/a.h\"\n", 343 "a.cc")); 344 } 345 346 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { 347 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 348 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 349 350 EXPECT_EQ("#include \"c.h\"\n" 351 "#include \"a.h\"\n" 352 "#include \"b.h\"\n", 353 sort("#include \"b.h\"\n" 354 "\n" 355 "#include \"a.h\"\n" 356 "#include \"c.h\"\n", 357 "c.cc")); 358 } 359 360 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { 361 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 362 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 363 364 EXPECT_EQ("#include \"a.h\"\n" 365 "\n" 366 "#include \"b.h\"\n" 367 "#include \"c.h\"\n", 368 sort("#include \"b.h\"\n" 369 "\n" 370 "#include \"a.h\"\n" 371 "#include \"c.h\"\n", 372 "a.cc")); 373 } 374 375 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { 376 // Setup an regex for main includes so we can cover those as well. 377 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 378 379 // Ensure both main header detection and grouping work in a case insensitive 380 // manner. 381 EXPECT_EQ("#include \"llvm/A.h\"\n" 382 "#include \"b.h\"\n" 383 "#include \"c.h\"\n" 384 "#include \"LLVM/z.h\"\n" 385 "#include \"llvm/X.h\"\n" 386 "#include \"GTest/GTest.h\"\n" 387 "#include \"gmock/gmock.h\"\n", 388 sort("#include \"c.h\"\n" 389 "#include \"b.h\"\n" 390 "#include \"GTest/GTest.h\"\n" 391 "#include \"llvm/A.h\"\n" 392 "#include \"gmock/gmock.h\"\n" 393 "#include \"llvm/X.h\"\n" 394 "#include \"LLVM/z.h\"\n", 395 "a_TEST.cc")); 396 } 397 398 TEST_F(SortIncludesTest, NegativePriorities) { 399 Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}}; 400 EXPECT_EQ("#include \"important_os_header.h\"\n" 401 "#include \"c_main.h\"\n" 402 "#include \"a_other.h\"\n", 403 sort("#include \"c_main.h\"\n" 404 "#include \"a_other.h\"\n" 405 "#include \"important_os_header.h\"\n", 406 "c_main.cc")); 407 408 // check stable when re-run 409 EXPECT_EQ("#include \"important_os_header.h\"\n" 410 "#include \"c_main.h\"\n" 411 "#include \"a_other.h\"\n", 412 sort("#include \"important_os_header.h\"\n" 413 "#include \"c_main.h\"\n" 414 "#include \"a_other.h\"\n", 415 "c_main.cc")); 416 } 417 418 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { 419 Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}}; 420 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 421 422 EXPECT_EQ("#include \"important_os_header.h\"\n" 423 "\n" 424 "#include \"c_main.h\"\n" 425 "\n" 426 "#include \"a_other.h\"\n", 427 sort("#include \"c_main.h\"\n" 428 "#include \"a_other.h\"\n" 429 "#include \"important_os_header.h\"\n", 430 "c_main.cc")); 431 432 // check stable when re-run 433 EXPECT_EQ("#include \"important_os_header.h\"\n" 434 "\n" 435 "#include \"c_main.h\"\n" 436 "\n" 437 "#include \"a_other.h\"\n", 438 sort("#include \"important_os_header.h\"\n" 439 "\n" 440 "#include \"c_main.h\"\n" 441 "\n" 442 "#include \"a_other.h\"\n", 443 "c_main.cc")); 444 } 445 446 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 447 std::string Code = "#include <ccc>\n" // Start of line: 0 448 "#include <bbbbbb>\n" // Start of line: 15 449 "#include <a>\n"; // Start of line: 33 450 EXPECT_EQ(31u, newCursor(Code, 0)); 451 EXPECT_EQ(13u, newCursor(Code, 15)); 452 EXPECT_EQ(0u, newCursor(Code, 33)); 453 454 EXPECT_EQ(41u, newCursor(Code, 10)); 455 EXPECT_EQ(23u, newCursor(Code, 25)); 456 EXPECT_EQ(10u, newCursor(Code, 43)); 457 } 458 459 TEST_F(SortIncludesTest, DeduplicateIncludes) { 460 EXPECT_EQ("#include <a>\n" 461 "#include <b>\n" 462 "#include <c>\n", 463 sort("#include <a>\n" 464 "#include <b>\n" 465 "#include <b>\n" 466 "#include <b>\n" 467 "#include <b>\n" 468 "#include <c>\n")); 469 470 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 471 EXPECT_EQ("#include <a>\n" 472 "#include <b>\n" 473 "#include <c>\n", 474 sort("#include <a>\n" 475 "#include <b>\n" 476 "\n" 477 "#include <b>\n" 478 "\n" 479 "#include <b>\n" 480 "#include <c>\n")); 481 482 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 483 EXPECT_EQ("#include <a>\n" 484 "#include <b>\n" 485 "#include <c>\n", 486 sort("#include <a>\n" 487 "#include <b>\n" 488 "\n" 489 "#include <b>\n" 490 "\n" 491 "#include <b>\n" 492 "#include <c>\n")); 493 } 494 495 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 496 EXPECT_EQ("#include <a>\n" 497 "#include <b>\n" 498 "#include <c>\n", 499 sort("#include <b>\n" 500 "#include <a>\n" 501 "#include <b>\n" 502 "#include <b>\n" 503 "#include <c>\n" 504 "#include <b>\n")); 505 506 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; 507 EXPECT_EQ("#include <a>\n" 508 "#include <b>\n" 509 "#include <c>\n", 510 sort("#include <b>\n" 511 "#include <a>\n" 512 "\n" 513 "#include <b>\n" 514 "\n" 515 "#include <c>\n" 516 "#include <b>\n")); 517 518 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 519 EXPECT_EQ("#include <a>\n" 520 "#include <b>\n" 521 "#include <c>\n", 522 sort("#include <b>\n" 523 "#include <a>\n" 524 "\n" 525 "#include <b>\n" 526 "\n" 527 "#include <c>\n" 528 "#include <b>\n")); 529 } 530 531 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 532 std::string Code = "#include <b>\n" // Start of line: 0 533 "#include <a>\n" // Start of line: 13 534 "#include <b>\n" // Start of line: 26 535 "#include <b>\n" // Start of line: 39 536 "#include <c>\n" // Start of line: 52 537 "#include <b>\n"; // Start of line: 65 538 std::string Expected = "#include <a>\n" // Start of line: 0 539 "#include <b>\n" // Start of line: 13 540 "#include <c>\n"; // Start of line: 26 541 EXPECT_EQ(Expected, sort(Code)); 542 // Cursor on 'i' in "#include <a>". 543 EXPECT_EQ(1u, newCursor(Code, 14)); 544 // Cursor on 'b' in "#include <b>". 545 EXPECT_EQ(23u, newCursor(Code, 10)); 546 EXPECT_EQ(23u, newCursor(Code, 36)); 547 EXPECT_EQ(23u, newCursor(Code, 49)); 548 EXPECT_EQ(23u, newCursor(Code, 36)); 549 EXPECT_EQ(23u, newCursor(Code, 75)); 550 // Cursor on '#' in "#include <c>". 551 EXPECT_EQ(26u, newCursor(Code, 52)); 552 } 553 554 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 555 EXPECT_EQ("#include <a>\n" 556 "#include <b>\n" 557 "\n" 558 "#include <b>\n" 559 "#include <c>\n", 560 sort("#include <a>\n" 561 "#include <b>\n" 562 "\n" 563 "#include <c>\n" 564 "#include <b>\n" 565 "#include <b>\n")); 566 } 567 568 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 569 std::string Code = "#include <a>\n" 570 "#include <b>\n" 571 "#include <a>\n" 572 "#include <a>\n" 573 "\n" 574 " int x ;"; 575 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 576 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); 577 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 578 EXPECT_EQ(1u, Ranges.size()); 579 EXPECT_EQ(0u, Ranges[0].getOffset()); 580 EXPECT_EQ(26u, Ranges[0].getLength()); 581 } 582 583 TEST_F(SortIncludesTest, DoNotSortLikelyXml) { 584 EXPECT_EQ("<!--;\n" 585 "#include <b>\n" 586 "#include <a>\n" 587 "-->", 588 sort("<!--;\n" 589 "#include <b>\n" 590 "#include <a>\n" 591 "-->")); 592 } 593 594 } // end namespace 595 } // end namespace format 596 } // end namespace clang 597