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
25namespace clang {
26namespace tidy {
27namespace {
28
29class IncludeInserterCheckBase : public ClangTidyCheck {
30public:
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(NodeMatch: ast_matchers::declStmt().bind(ID: "stmt"), Action: this);
45 }
46
47 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
48 auto Diag = diag(Loc: Result.Nodes.getNodeAs<DeclStmt>(ID: "stmt")->getBeginLoc(),
49 Description: "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
60class NonSystemHeaderInserterCheck : public IncludeInserterCheckBase {
61public:
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
70class EarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase {
71public:
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
80class MultipleHeaderInserterCheck : public IncludeInserterCheckBase {
81public:
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
90class MultipleHeaderSingleInserterCheck : public IncludeInserterCheckBase {
91public:
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
103class CSystemIncludeInserterCheck : public IncludeInserterCheckBase {
104public:
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
113class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase {
114public:
115 CXXSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context)
116 : IncludeInserterCheckBase(CheckName, Context) {}
117
118 std::vector<StringRef> headersToInclude() const override { return {"<set>"}; }
119};
120
121class InvalidIncludeInserterCheck : public IncludeInserterCheckBase {
122public:
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
131class ObjCEarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase {
132public:
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
143class ObjCCategoryHeaderInserterCheck : public IncludeInserterCheckBase {
144public:
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
155class ObjCGeneratedHeaderInserterCheck : public IncludeInserterCheckBase {
156public:
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
167template <typename Check>
168std::string runCheckOnCode(StringRef Code, StringRef Filename) {
169 std::vector<ClangTidyError> Errors;
170 return test::runCheckOnCode<Check>(Code, &Errors, Filename, std::nullopt,
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
203TEST(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
212void 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
224void 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
233TEST(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
242void 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
255void 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
264TEST(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
273void 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
289void 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
299TEST(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
308void 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
320void 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
329TEST(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
339void 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
352void 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
361TEST(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
372void 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
380TEST(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
387void 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
398void 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
407TEST(IncludeInserterTest, InsertNonSystemIncludeAfterMainFileInclude) {
408 const char *PreCode = R"(
409#include "clang_tidy/tests/insert_includes_test_header.h"
410
411void 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
419void 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
428TEST(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
437void 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
449void 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
458TEST(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
466void 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
477void 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
486TEST(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
495void 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
507void 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
516TEST(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
522void 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
532void 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
541TEST(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
549void 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
561void 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
570TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeNonSystemInclude) {
571 const char *PreCode = R"(
572#include "path/to/a/header.h"
573
574void foo() {
575 int a = 0;
576})";
577 const char *PostCode = R"(
578#include <set>
579
580#include "path/to/a/header.h"
581
582void 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
592TEST(IncludeInserterTest, InsertCSystemIncludeBeforeCXXSystemInclude) {
593 const char *PreCode = R"(
594#include <set>
595
596#include "path/to/a/header.h"
597
598void 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
608void 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
618TEST(IncludeInserterTest, InsertIncludeIfThereWasNoneBefore) {
619 const char *PreCode = R"(
620void foo() {
621 int a = 0;
622})";
623 const char *PostCode = R"(#include <set>
624
625
626void 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
636TEST(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
648void 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
663void 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
672TEST(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
683void 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
698void 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
707TEST(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
716void 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
732void 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
741TEST(IncludeInserterTest, InsertHeaderObjectiveC) {
742 const char *PreCode = R"(
743#import "clang_tidy/tests/insert_includes_test_header.h"
744
745void 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
753void 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
763TEST(IncludeInserterTest, InsertCategoryHeaderObjectiveC) {
764 const char *PreCode = R"(
765#import "top_level_test_header.h"
766
767void 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
774void foo() {
775 int a = 0;
776})";
777
778 EXPECT_EQ(PostCode, runCheckOnCode<ObjCCategoryHeaderInserterCheck>(
779 PreCode, "top_level_test_header.mm"));
780}
781
782TEST(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
791void 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
804void 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

source code of clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp