1 //===---- IncludeInserterTest.cpp - clang-tidy ----------------------------===// 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 "../clang-tidy/utils/IncludeInserter.h" 10 #include "clang/Lex/Preprocessor.h" 11 #include "clang/Frontend/CompilerInstance.h" 12 #include "ClangTidyTest.h" 13 #include "gtest/gtest.h" 14 15 // FIXME: Canonicalize paths correctly on windows. 16 // Currently, adding virtual files will canonicalize the paths before 17 // storing the virtual entries. 18 // When resolving virtual entries in the FileManager, the paths (for 19 // example coming from a #include directive) are not canonicalized 20 // to native paths; thus, the virtual file is not found. 21 // This needs to be fixed in the FileManager before we can make 22 // clang-tidy tests work. 23 #if !defined(_WIN32) 24 25 namespace clang { 26 namespace tidy { 27 namespace { 28 29 class IncludeInserterCheckBase : public ClangTidyCheck { 30 public: 31 IncludeInserterCheckBase(StringRef CheckName, ClangTidyContext *Context, 32 utils::IncludeSorter::IncludeStyle Style = 33 utils::IncludeSorter::IS_Google, 34 bool SelfContainedDiags = false) 35 : ClangTidyCheck(CheckName, Context), 36 Inserter(Style, SelfContainedDiags) {} 37 38 void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, 39 Preprocessor *ModuleExpanderPP) override { 40 Inserter.registerPreprocessor(PP); 41 } 42 43 void registerMatchers(ast_matchers::MatchFinder *Finder) override { 44 Finder->addMatcher(ast_matchers::declStmt().bind("stmt"), this); 45 } 46 47 void check(const ast_matchers::MatchFinder::MatchResult &Result) override { 48 auto Diag = diag(Result.Nodes.getNodeAs<DeclStmt>("stmt")->getBeginLoc(), 49 "foo, bar"); 50 for (StringRef Header : headersToInclude()) { 51 Diag << Inserter.createMainFileIncludeInsertion(Header); 52 } 53 } 54 55 virtual std::vector<StringRef> headersToInclude() const = 0; 56 57 utils::IncludeInserter Inserter; 58 }; 59 60 class NonSystemHeaderInserterCheck : public IncludeInserterCheckBase { 61 public: 62 NonSystemHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) 63 : IncludeInserterCheckBase(CheckName, Context) {} 64 65 std::vector<StringRef> headersToInclude() const override { 66 return {"path/to/header.h"}; 67 } 68 }; 69 70 class EarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase { 71 public: 72 EarlyInAlphabetHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) 73 : IncludeInserterCheckBase(CheckName, Context) {} 74 75 std::vector<StringRef> headersToInclude() const override { 76 return {"a/header.h"}; 77 } 78 }; 79 80 class MultipleHeaderInserterCheck : public IncludeInserterCheckBase { 81 public: 82 MultipleHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) 83 : IncludeInserterCheckBase(CheckName, Context) {} 84 85 std::vector<StringRef> headersToInclude() const override { 86 return {"path/to/header.h", "path/to/header2.h", "path/to/header.h"}; 87 } 88 }; 89 90 class MultipleHeaderSingleInserterCheck : public IncludeInserterCheckBase { 91 public: 92 MultipleHeaderSingleInserterCheck(StringRef CheckName, 93 ClangTidyContext *Context) 94 : IncludeInserterCheckBase(CheckName, Context, 95 utils::IncludeSorter::IS_Google, 96 /*SelfContainedDiags=*/true) {} 97 98 std::vector<StringRef> headersToInclude() const override { 99 return {"path/to/header.h", "path/to/header2.h", "path/to/header.h"}; 100 } 101 }; 102 103 class CSystemIncludeInserterCheck : public IncludeInserterCheckBase { 104 public: 105 CSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) 106 : IncludeInserterCheckBase(CheckName, Context) {} 107 108 std::vector<StringRef> headersToInclude() const override { 109 return {"<stdlib.h>"}; 110 } 111 }; 112 113 class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase { 114 public: 115 CXXSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) 116 : IncludeInserterCheckBase(CheckName, Context) {} 117 118 std::vector<StringRef> headersToInclude() const override { return {"<set>"}; } 119 }; 120 121 class InvalidIncludeInserterCheck : public IncludeInserterCheckBase { 122 public: 123 InvalidIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) 124 : IncludeInserterCheckBase(CheckName, Context) {} 125 126 std::vector<StringRef> headersToInclude() const override { 127 return {"a.h", "<stdlib.h", "cstdlib>", "b.h", "<c.h>", "<d>"}; 128 } 129 }; 130 131 class ObjCEarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase { 132 public: 133 ObjCEarlyInAlphabetHeaderInserterCheck(StringRef CheckName, 134 ClangTidyContext *Context) 135 : IncludeInserterCheckBase(CheckName, Context, 136 utils::IncludeSorter::IS_Google_ObjC) {} 137 138 std::vector<StringRef> headersToInclude() const override { 139 return {"a/header.h"}; 140 } 141 }; 142 143 class ObjCCategoryHeaderInserterCheck : public IncludeInserterCheckBase { 144 public: 145 ObjCCategoryHeaderInserterCheck(StringRef CheckName, 146 ClangTidyContext *Context) 147 : IncludeInserterCheckBase(CheckName, Context, 148 utils::IncludeSorter::IS_Google_ObjC) {} 149 150 std::vector<StringRef> headersToInclude() const override { 151 return {"top_level_test_header+foo.h"}; 152 } 153 }; 154 155 class ObjCGeneratedHeaderInserterCheck : public IncludeInserterCheckBase { 156 public: 157 ObjCGeneratedHeaderInserterCheck(StringRef CheckName, 158 ClangTidyContext *Context) 159 : IncludeInserterCheckBase(CheckName, Context, 160 utils::IncludeSorter::IS_Google_ObjC) {} 161 162 std::vector<StringRef> headersToInclude() const override { 163 return {"clang_tidy/tests/generated_file.proto.h"}; 164 } 165 }; 166 167 template <typename Check> 168 std::string runCheckOnCode(StringRef Code, StringRef Filename) { 169 std::vector<ClangTidyError> Errors; 170 return test::runCheckOnCode<Check>(Code, &Errors, Filename, {}, 171 ClangTidyOptions(), 172 {// Main file include 173 {"clang_tidy/tests/" 174 "insert_includes_test_header.h", 175 "\n"}, 176 // Top-level main file include + 177 // category. 178 {"top_level_test_header.h", "\n"}, 179 {"top_level_test_header+foo.h", "\n"}, 180 // ObjC category. 181 {"clang_tidy/tests/" 182 "insert_includes_test_header+foo.h", 183 "\n"}, 184 // Non system headers 185 {"a/header.h", "\n"}, 186 {"path/to/a/header.h", "\n"}, 187 {"path/to/z/header.h", "\n"}, 188 {"path/to/header.h", "\n"}, 189 {"path/to/header2.h", "\n"}, 190 // Generated headers 191 {"clang_tidy/tests/" 192 "generated_file.proto.h", 193 "\n"}, 194 // Fake system headers. 195 {"stdlib.h", "\n"}, 196 {"unistd.h", "\n"}, 197 {"list", "\n"}, 198 {"map", "\n"}, 199 {"set", "\n"}, 200 {"vector", "\n"}}); 201 } 202 203 TEST(IncludeInserterTest, InsertAfterLastNonSystemInclude) { 204 const char *PreCode = R"( 205 #include "clang_tidy/tests/insert_includes_test_header.h" 206 207 #include <list> 208 #include <map> 209 210 #include "path/to/a/header.h" 211 212 void foo() { 213 int a = 0; 214 })"; 215 const char *PostCode = R"( 216 #include "clang_tidy/tests/insert_includes_test_header.h" 217 218 #include <list> 219 #include <map> 220 221 #include "path/to/a/header.h" 222 #include "path/to/header.h" 223 224 void foo() { 225 int a = 0; 226 })"; 227 228 EXPECT_EQ(PostCode, 229 runCheckOnCode<NonSystemHeaderInserterCheck>( 230 PreCode, "clang_tidy/tests/insert_includes_test_input2.cc")); 231 } 232 233 TEST(IncludeInserterTest, InsertMultipleIncludesAndDeduplicate) { 234 const char *PreCode = R"( 235 #include "clang_tidy/tests/insert_includes_test_header.h" 236 237 #include <list> 238 #include <map> 239 240 #include "path/to/a/header.h" 241 242 void foo() { 243 int a = 0; 244 })"; 245 const char *PostCode = R"( 246 #include "clang_tidy/tests/insert_includes_test_header.h" 247 248 #include <list> 249 #include <map> 250 251 #include "path/to/a/header.h" 252 #include "path/to/header.h" 253 #include "path/to/header2.h" 254 255 void foo() { 256 int a = 0; 257 })"; 258 259 EXPECT_EQ(PostCode, 260 runCheckOnCode<MultipleHeaderInserterCheck>( 261 PreCode, "clang_tidy/tests/insert_includes_test_input2.cc")); 262 } 263 264 TEST(IncludeInserterTest, InsertMultipleIncludesNoDeduplicate) { 265 const char *PreCode = R"( 266 #include "clang_tidy/tests/insert_includes_test_header.h" 267 268 #include <list> 269 #include <map> 270 271 #include "path/to/a/header.h" 272 273 void foo() { 274 int a = 0; 275 })"; 276 // FIXME: ClangFormat bug - https://bugs.llvm.org/show_bug.cgi?id=49298 277 // clang-format off 278 const char *PostCode = R"( 279 #include "clang_tidy/tests/insert_includes_test_header.h" 280 281 #include <list> 282 #include <map> 283 284 #include "path/to/a/header.h" 285 #include "path/to/header.h" 286 #include "path/to/header2.h" 287 #include "path/to/header.h" 288 289 void foo() { 290 int a = 0; 291 })"; 292 // clang-format on 293 294 EXPECT_EQ(PostCode, 295 runCheckOnCode<MultipleHeaderSingleInserterCheck>( 296 PreCode, "clang_tidy/tests/insert_includes_test_input2.cc")); 297 } 298 299 TEST(IncludeInserterTest, InsertBeforeFirstNonSystemInclude) { 300 const char *PreCode = R"( 301 #include "clang_tidy/tests/insert_includes_test_header.h" 302 303 #include <list> 304 #include <map> 305 306 #include "path/to/z/header.h" 307 308 void foo() { 309 int a = 0; 310 })"; 311 const char *PostCode = R"( 312 #include "clang_tidy/tests/insert_includes_test_header.h" 313 314 #include <list> 315 #include <map> 316 317 #include "path/to/header.h" 318 #include "path/to/z/header.h" 319 320 void foo() { 321 int a = 0; 322 })"; 323 324 EXPECT_EQ(PostCode, 325 runCheckOnCode<NonSystemHeaderInserterCheck>( 326 PreCode, "clang_tidy/tests/insert_includes_test_input2.cc")); 327 } 328 329 TEST(IncludeInserterTest, InsertBetweenNonSystemIncludes) { 330 const char *PreCode = R"( 331 #include "clang_tidy/tests/insert_includes_test_header.h" 332 333 #include <list> 334 #include <map> 335 336 #include "path/to/a/header.h" 337 #include "path/to/z/header.h" 338 339 void foo() { 340 int a = 0; 341 })"; 342 const char *PostCode = R"( 343 #include "clang_tidy/tests/insert_includes_test_header.h" 344 345 #include <list> 346 #include <map> 347 348 #include "path/to/a/header.h" 349 #include "path/to/header.h" 350 #include "path/to/z/header.h" 351 352 void foo() { 353 int a = 0; 354 })"; 355 356 EXPECT_EQ(PostCode, 357 runCheckOnCode<NonSystemHeaderInserterCheck>( 358 PreCode, "clang_tidy/tests/insert_includes_test_input2.cc")); 359 } 360 361 TEST(IncludeInserterTest, NonSystemIncludeAlreadyIncluded) { 362 const char *PreCode = R"( 363 #include "clang_tidy/tests/insert_includes_test_header.h" 364 365 #include <list> 366 #include <map> 367 368 #include "path/to/a/header.h" 369 #include "path/to/header.h" 370 #include "path/to/z/header.h" 371 372 void foo() { 373 int a = 0; 374 })"; 375 EXPECT_EQ(PreCode, 376 runCheckOnCode<NonSystemHeaderInserterCheck>( 377 PreCode, "clang_tidy/tests/insert_includes_test_input2.cc")); 378 } 379 380 TEST(IncludeInserterTest, InsertNonSystemIncludeAfterLastCXXSystemInclude) { 381 const char *PreCode = R"( 382 #include "clang_tidy/tests/insert_includes_test_header.h" 383 384 #include <list> 385 #include <map> 386 387 void foo() { 388 int a = 0; 389 })"; 390 const char *PostCode = R"( 391 #include "clang_tidy/tests/insert_includes_test_header.h" 392 393 #include <list> 394 #include <map> 395 396 #include "path/to/header.h" 397 398 void foo() { 399 int a = 0; 400 })"; 401 402 EXPECT_EQ(PostCode, 403 runCheckOnCode<NonSystemHeaderInserterCheck>( 404 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 405 } 406 407 TEST(IncludeInserterTest, InsertNonSystemIncludeAfterMainFileInclude) { 408 const char *PreCode = R"( 409 #include "clang_tidy/tests/insert_includes_test_header.h" 410 411 void foo() { 412 int a = 0; 413 })"; 414 const char *PostCode = R"( 415 #include "clang_tidy/tests/insert_includes_test_header.h" 416 417 #include "path/to/header.h" 418 419 void foo() { 420 int a = 0; 421 })"; 422 423 EXPECT_EQ(PostCode, 424 runCheckOnCode<NonSystemHeaderInserterCheck>( 425 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 426 } 427 428 TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterLastCXXSystemInclude) { 429 const char *PreCode = R"( 430 #include "clang_tidy/tests/insert_includes_test_header.h" 431 432 #include <list> 433 #include <map> 434 435 #include "path/to/a/header.h" 436 437 void foo() { 438 int a = 0; 439 })"; 440 const char *PostCode = R"( 441 #include "clang_tidy/tests/insert_includes_test_header.h" 442 443 #include <list> 444 #include <map> 445 #include <set> 446 447 #include "path/to/a/header.h" 448 449 void foo() { 450 int a = 0; 451 })"; 452 453 EXPECT_EQ(PostCode, 454 runCheckOnCode<CXXSystemIncludeInserterCheck>( 455 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 456 } 457 458 TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeFirstCXXSystemInclude) { 459 const char *PreCode = R"( 460 #include "clang_tidy/tests/insert_includes_test_header.h" 461 462 #include <vector> 463 464 #include "path/to/a/header.h" 465 466 void foo() { 467 int a = 0; 468 })"; 469 const char *PostCode = R"( 470 #include "clang_tidy/tests/insert_includes_test_header.h" 471 472 #include <set> 473 #include <vector> 474 475 #include "path/to/a/header.h" 476 477 void foo() { 478 int a = 0; 479 })"; 480 481 EXPECT_EQ(PostCode, 482 runCheckOnCode<CXXSystemIncludeInserterCheck>( 483 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 484 } 485 486 TEST(IncludeInserterTest, InsertCXXSystemIncludeBetweenCXXSystemIncludes) { 487 const char *PreCode = R"( 488 #include "clang_tidy/tests/insert_includes_test_header.h" 489 490 #include <map> 491 #include <vector> 492 493 #include "path/to/a/header.h" 494 495 void foo() { 496 int a = 0; 497 })"; 498 const char *PostCode = R"( 499 #include "clang_tidy/tests/insert_includes_test_header.h" 500 501 #include <map> 502 #include <set> 503 #include <vector> 504 505 #include "path/to/a/header.h" 506 507 void foo() { 508 int a = 0; 509 })"; 510 511 EXPECT_EQ(PostCode, 512 runCheckOnCode<CXXSystemIncludeInserterCheck>( 513 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 514 } 515 516 TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterMainFileInclude) { 517 const char *PreCode = R"( 518 #include "clang_tidy/tests/insert_includes_test_header.h" 519 520 #include "path/to/a/header.h" 521 522 void foo() { 523 int a = 0; 524 })"; 525 const char *PostCode = R"( 526 #include "clang_tidy/tests/insert_includes_test_header.h" 527 528 #include <set> 529 530 #include "path/to/a/header.h" 531 532 void foo() { 533 int a = 0; 534 })"; 535 536 EXPECT_EQ(PostCode, 537 runCheckOnCode<CXXSystemIncludeInserterCheck>( 538 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 539 } 540 541 TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterCSystemInclude) { 542 const char *PreCode = R"( 543 #include "clang_tidy/tests/insert_includes_test_header.h" 544 545 #include <stdlib.h> 546 547 #include "path/to/a/header.h" 548 549 void foo() { 550 int a = 0; 551 })"; 552 const char *PostCode = R"( 553 #include "clang_tidy/tests/insert_includes_test_header.h" 554 555 #include <stdlib.h> 556 557 #include <set> 558 559 #include "path/to/a/header.h" 560 561 void foo() { 562 int a = 0; 563 })"; 564 565 EXPECT_EQ(PostCode, 566 runCheckOnCode<CXXSystemIncludeInserterCheck>( 567 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 568 } 569 570 TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeNonSystemInclude) { 571 const char *PreCode = R"( 572 #include "path/to/a/header.h" 573 574 void foo() { 575 int a = 0; 576 })"; 577 const char *PostCode = R"( 578 #include <set> 579 580 #include "path/to/a/header.h" 581 582 void foo() { 583 int a = 0; 584 })"; 585 586 EXPECT_EQ( 587 PostCode, 588 runCheckOnCode<CXXSystemIncludeInserterCheck>( 589 PreCode, "repo/clang_tidy/tests/insert_includes_test_header.cc")); 590 } 591 592 TEST(IncludeInserterTest, InsertCSystemIncludeBeforeCXXSystemInclude) { 593 const char *PreCode = R"( 594 #include <set> 595 596 #include "path/to/a/header.h" 597 598 void foo() { 599 int a = 0; 600 })"; 601 const char *PostCode = R"( 602 #include <stdlib.h> 603 604 #include <set> 605 606 #include "path/to/a/header.h" 607 608 void foo() { 609 int a = 0; 610 })"; 611 612 EXPECT_EQ( 613 PostCode, 614 runCheckOnCode<CSystemIncludeInserterCheck>( 615 PreCode, "repo/clang_tidy/tests/insert_includes_test_header.cc")); 616 } 617 618 TEST(IncludeInserterTest, InsertIncludeIfThereWasNoneBefore) { 619 const char *PreCode = R"( 620 void foo() { 621 int a = 0; 622 })"; 623 const char *PostCode = R"(#include <set> 624 625 626 void foo() { 627 int a = 0; 628 })"; 629 630 EXPECT_EQ( 631 PostCode, 632 runCheckOnCode<CXXSystemIncludeInserterCheck>( 633 PreCode, "repo/clang_tidy/tests/insert_includes_test_header.cc")); 634 } 635 636 TEST(IncludeInserterTest, DontInsertDuplicateIncludeEvenIfMiscategorized) { 637 const char *PreCode = R"( 638 #include "clang_tidy/tests/insert_includes_test_header.h" 639 640 #include <map> 641 #include <set> 642 #include <vector> 643 644 #include "a/header.h" 645 #include "path/to/a/header.h" 646 #include "path/to/header.h" 647 648 void foo() { 649 int a = 0; 650 })"; 651 652 const char *PostCode = R"( 653 #include "clang_tidy/tests/insert_includes_test_header.h" 654 655 #include <map> 656 #include <set> 657 #include <vector> 658 659 #include "a/header.h" 660 #include "path/to/a/header.h" 661 #include "path/to/header.h" 662 663 void foo() { 664 int a = 0; 665 })"; 666 667 EXPECT_EQ(PostCode, runCheckOnCode<EarlyInAlphabetHeaderInserterCheck>( 668 PreCode, "workspace_folder/clang_tidy/tests/" 669 "insert_includes_test_header.cc")); 670 } 671 672 TEST(IncludeInserterTest, HandleOrderInSubdirectory) { 673 const char *PreCode = R"( 674 #include "clang_tidy/tests/insert_includes_test_header.h" 675 676 #include <map> 677 #include <set> 678 #include <vector> 679 680 #include "path/to/a/header.h" 681 #include "path/to/header.h" 682 683 void foo() { 684 int a = 0; 685 })"; 686 687 const char *PostCode = R"( 688 #include "clang_tidy/tests/insert_includes_test_header.h" 689 690 #include <map> 691 #include <set> 692 #include <vector> 693 694 #include "a/header.h" 695 #include "path/to/a/header.h" 696 #include "path/to/header.h" 697 698 void foo() { 699 int a = 0; 700 })"; 701 702 EXPECT_EQ(PostCode, runCheckOnCode<EarlyInAlphabetHeaderInserterCheck>( 703 PreCode, "workspace_folder/clang_tidy/tests/" 704 "insert_includes_test_header.cc")); 705 } 706 707 TEST(IncludeInserterTest, InvalidHeaderName) { 708 const char *PreCode = R"( 709 #include "clang_tidy/tests/insert_includes_test_header.h" 710 711 #include <list> 712 #include <map> 713 714 #include "path/to/a/header.h" 715 716 void foo() { 717 int a = 0; 718 })"; 719 const char *PostCode = R"( 720 #include "clang_tidy/tests/insert_includes_test_header.h" 721 722 #include <c.h> 723 724 #include <d> 725 #include <list> 726 #include <map> 727 728 #include "a.h" 729 #include "b.h" 730 #include "path/to/a/header.h" 731 732 void foo() { 733 int a = 0; 734 })"; 735 736 EXPECT_EQ(PostCode, 737 runCheckOnCode<InvalidIncludeInserterCheck>( 738 PreCode, "clang_tidy/tests/insert_includes_test_header.cc")); 739 } 740 741 TEST(IncludeInserterTest, InsertHeaderObjectiveC) { 742 const char *PreCode = R"( 743 #import "clang_tidy/tests/insert_includes_test_header.h" 744 745 void foo() { 746 int a = 0; 747 })"; 748 const char *PostCode = R"( 749 #import "clang_tidy/tests/insert_includes_test_header.h" 750 751 #import "a/header.h" 752 753 void foo() { 754 int a = 0; 755 })"; 756 757 EXPECT_EQ( 758 PostCode, 759 runCheckOnCode<ObjCEarlyInAlphabetHeaderInserterCheck>( 760 PreCode, "repo/clang_tidy/tests/insert_includes_test_header.mm")); 761 } 762 763 TEST(IncludeInserterTest, InsertCategoryHeaderObjectiveC) { 764 const char *PreCode = R"( 765 #import "top_level_test_header.h" 766 767 void foo() { 768 int a = 0; 769 })"; 770 const char *PostCode = R"( 771 #import "top_level_test_header.h" 772 #import "top_level_test_header+foo.h" 773 774 void foo() { 775 int a = 0; 776 })"; 777 778 EXPECT_EQ(PostCode, runCheckOnCode<ObjCCategoryHeaderInserterCheck>( 779 PreCode, "top_level_test_header.mm")); 780 } 781 782 TEST(IncludeInserterTest, InsertGeneratedHeaderObjectiveC) { 783 const char *PreCode = R"( 784 #import "clang_tidy/tests/insert_includes_test_header.h" 785 786 #include <list> 787 #include <map> 788 789 #include "path/to/a/header.h" 790 791 void foo() { 792 int a = 0; 793 })"; 794 const char *PostCode = R"( 795 #import "clang_tidy/tests/insert_includes_test_header.h" 796 797 #include <list> 798 #include <map> 799 800 #include "path/to/a/header.h" 801 802 #import "clang_tidy/tests/generated_file.proto.h" 803 804 void foo() { 805 int a = 0; 806 })"; 807 808 EXPECT_EQ( 809 PostCode, 810 runCheckOnCode<ObjCGeneratedHeaderInserterCheck>( 811 PreCode, "repo/clang_tidy/tests/insert_includes_test_header.mm")); 812 } 813 814 } // anonymous namespace 815 } // namespace tidy 816 } // namespace clang 817 818 #endif 819