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