1//===- unittest/Tooling/CleanupTest.cpp - Include insertion/deletion 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 "clang/Tooling/Inclusions/HeaderIncludes.h"
10#include "../Tooling/ReplacementTest.h"
11#include "../Tooling/RewriterTestContext.h"
12#include "clang/Format/Format.h"
13#include "clang/Tooling/Core/Replacement.h"
14
15#include "gtest/gtest.h"
16
17namespace clang {
18namespace tooling {
19namespace {
20
21class HeaderIncludesTest : public ::testing::Test {
22protected:
23 std::string insert(llvm::StringRef Code, llvm::StringRef Header,
24 IncludeDirective Directive = IncludeDirective::Include) {
25 HeaderIncludes Includes(FileName, Code, Style);
26 assert(Header.starts_with("\"") || Header.starts_with("<"));
27 auto R = Includes.insert(Header: Header.trim(Chars: "\"<>"), IsAngled: Header.starts_with(Prefix: "<"),
28 Directive);
29 if (!R)
30 return std::string(Code);
31 auto Result = applyAllReplacements(Code, Replaces: Replacements(*R));
32 EXPECT_TRUE(static_cast<bool>(Result));
33 return *Result;
34 }
35
36 std::string remove(llvm::StringRef Code, llvm::StringRef Header) {
37 HeaderIncludes Includes(FileName, Code, Style);
38 assert(Header.starts_with("\"") || Header.starts_with("<"));
39 auto Replaces =
40 Includes.remove(Header: Header.trim(Chars: "\"<>"), IsAngled: Header.starts_with(Prefix: "<"));
41 auto Result = applyAllReplacements(Code, Replaces);
42 EXPECT_TRUE(static_cast<bool>(Result));
43 return *Result;
44 }
45
46 std::string FileName = "fix.cpp";
47 IncludeStyle Style = format::getLLVMStyle().IncludeStyle;
48};
49
50TEST_F(HeaderIncludesTest, NoExistingIncludeWithoutDefine) {
51 std::string Code = "int main() {}";
52 std::string Expected = "#include \"a.h\"\n"
53 "int main() {}";
54 EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
55}
56
57TEST_F(HeaderIncludesTest, RepeatedIncludes) {
58 std::string Code;
59 for (int i = 0; i < 100; ++i) {
60 Code += "#include \"a.h\"\n";
61 }
62 std::string Expected = Code + "#include \"a2.h\"\n";
63 EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
64}
65
66TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
67 std::string Code = "#include \"a.h\"\n";
68 std::string Expected = Code + "#import \"a.h\"\n";
69 EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
70}
71
72TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
73 std::string Code = "#import \"a.h\"\n";
74 EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
75}
76
77TEST_F(HeaderIncludesTest, DeleteImportAndSameInclude) {
78 std::string Code = R"cpp(
79#include <abc.h>
80#import <abc.h>
81int x;)cpp";
82 EXPECT_EQ("\nint x;", remove(Code, "<abc.h>"));
83}
84
85TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
86 std::string Code = "#ifndef A_H\n"
87 "#define A_H\n"
88 "class A {};\n"
89 "#define MMM 123\n"
90 "#endif";
91 std::string Expected = "#ifndef A_H\n"
92 "#define A_H\n"
93 "#include \"b.h\"\n"
94 "class A {};\n"
95 "#define MMM 123\n"
96 "#endif";
97
98 EXPECT_EQ(Expected, insert(Code, "\"b.h\""));
99}
100
101TEST_F(HeaderIncludesTest, InsertBeforeCategoryWithLowerPriority) {
102 std::string Code = "#ifndef A_H\n"
103 "#define A_H\n"
104 "\n"
105 "\n"
106 "\n"
107 "#include <vector>\n"
108 "class A {};\n"
109 "#define MMM 123\n"
110 "#endif";
111 std::string Expected = "#ifndef A_H\n"
112 "#define A_H\n"
113 "\n"
114 "\n"
115 "\n"
116 "#include \"a.h\"\n"
117 "#include <vector>\n"
118 "class A {};\n"
119 "#define MMM 123\n"
120 "#endif";
121
122 EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
123}
124
125TEST_F(HeaderIncludesTest, InsertAfterMainHeader) {
126 std::string Code = "#include \"fix.h\"\n"
127 "\n"
128 "int main() {}";
129 std::string Expected = "#include \"fix.h\"\n"
130 "#include <a>\n"
131 "\n"
132 "int main() {}";
133 Style = format::getGoogleStyle(Language: format::FormatStyle::LanguageKind::LK_Cpp)
134 .IncludeStyle;
135 EXPECT_EQ(Expected, insert(Code, "<a>"));
136
137 FileName = "fix.cu.cpp";
138 EXPECT_EQ(Expected, insert(Code, "<a>"));
139
140 FileName = "fix_test.cu.cpp";
141 EXPECT_EQ(Expected, insert(Code, "<a>"));
142
143 FileName = "bar.cpp";
144 EXPECT_NE(Expected, insert(Code, "<a>")) << "Not main header";
145}
146
147TEST_F(HeaderIncludesTest, InsertMainHeader) {
148 Style = format::getGoogleStyle(Language: format::FormatStyle::LanguageKind::LK_Cpp)
149 .IncludeStyle;
150 FileName = "fix.cpp";
151 EXPECT_EQ(R"cpp(#include "fix.h"
152#include "a.h")cpp", insert("#include \"a.h\"", "\"fix.h\""));
153
154 // Respect the original main-file header.
155 EXPECT_EQ(R"cpp(#include "z/fix.h"
156#include "a/fix.h"
157)cpp", insert("#include \"z/fix.h\"", "\"a/fix.h\""));
158}
159
160TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
161 std::string Code = "#include <memory>\n"
162 "\n"
163 "int main() {}";
164 std::string Expected = "#include \"z.h\"\n"
165 "#include <memory>\n"
166 "\n"
167 "int main() {}";
168 EXPECT_EQ(Expected, insert(Code, "\"z.h\""));
169}
170
171TEST_F(HeaderIncludesTest, InsertAfterSystemHeaderGoogle) {
172 std::string Code = "#include <memory>\n"
173 "\n"
174 "int main() {}";
175 std::string Expected = "#include <memory>\n"
176 "#include \"z.h\"\n"
177 "\n"
178 "int main() {}";
179 Style = format::getGoogleStyle(Language: format::FormatStyle::LanguageKind::LK_Cpp)
180 .IncludeStyle;
181 EXPECT_EQ(Expected, insert(Code, "\"z.h\""));
182}
183
184TEST_F(HeaderIncludesTest, InsertOneIncludeLLVMStyle) {
185 std::string Code = "#include \"x/fix.h\"\n"
186 "#include \"a.h\"\n"
187 "#include \"b.h\"\n"
188 "#include \"clang/Format/Format.h\"\n"
189 "#include <memory>\n";
190 std::string Expected = "#include \"x/fix.h\"\n"
191 "#include \"a.h\"\n"
192 "#include \"b.h\"\n"
193 "#include \"clang/Format/Format.h\"\n"
194 "#include \"llvm/x/y.h\"\n"
195 "#include <memory>\n";
196 EXPECT_EQ(Expected, insert(Code, "\"llvm/x/y.h\""));
197}
198
199TEST_F(HeaderIncludesTest, InsertIntoBlockSorted) {
200 std::string Code = "#include \"x/fix.h\"\n"
201 "#include \"a.h\"\n"
202 "#include \"c.h\"\n"
203 "#include <memory>\n";
204 std::string Expected = "#include \"x/fix.h\"\n"
205 "#include \"a.h\"\n"
206 "#include \"b.h\"\n"
207 "#include \"c.h\"\n"
208 "#include <memory>\n";
209 EXPECT_EQ(Expected, insert(Code, "\"b.h\""));
210}
211
212TEST_F(HeaderIncludesTest, InsertIntoFirstBlockOfSameKind) {
213 std::string Code = "#include \"x/fix.h\"\n"
214 "#include \"c.h\"\n"
215 "#include \"e.h\"\n"
216 "#include \"f.h\"\n"
217 "#include <memory>\n"
218 "#include <vector>\n"
219 "#include \"m.h\"\n"
220 "#include \"n.h\"\n";
221 std::string Expected = "#include \"x/fix.h\"\n"
222 "#include \"c.h\"\n"
223 "#include \"d.h\"\n"
224 "#include \"e.h\"\n"
225 "#include \"f.h\"\n"
226 "#include <memory>\n"
227 "#include <vector>\n"
228 "#include \"m.h\"\n"
229 "#include \"n.h\"\n";
230 EXPECT_EQ(Expected, insert(Code, "\"d.h\""));
231}
232
233TEST_F(HeaderIncludesTest, InsertIntoSystemBlockSorted) {
234 std::string Code = "#include \"x/fix.h\"\n"
235 "#include \"a.h\"\n"
236 "#include \"c.h\"\n"
237 "#include <a>\n"
238 "#include <z>\n";
239 std::string Expected = "#include \"x/fix.h\"\n"
240 "#include \"a.h\"\n"
241 "#include \"c.h\"\n"
242 "#include <a>\n"
243 "#include <vector>\n"
244 "#include <z>\n";
245 EXPECT_EQ(Expected, insert(Code, "<vector>"));
246}
247
248TEST_F(HeaderIncludesTest, InsertNewSystemIncludeGoogleStyle) {
249 std::string Code = "#include \"x/fix.h\"\n"
250 "\n"
251 "#include \"y/a.h\"\n"
252 "#include \"z/b.h\"\n";
253 // FIXME: inserting after the empty line following the main header might be
254 // preferred.
255 std::string Expected = "#include \"x/fix.h\"\n"
256 "#include <vector>\n"
257 "\n"
258 "#include \"y/a.h\"\n"
259 "#include \"z/b.h\"\n";
260 Style = format::getGoogleStyle(Language: format::FormatStyle::LanguageKind::LK_Cpp)
261 .IncludeStyle;
262 EXPECT_EQ(Expected, insert(Code, "<vector>"));
263}
264
265TEST_F(HeaderIncludesTest, NotConfusedByDefine) {
266 std::string Code = "void f() {}\n"
267 "#define A \\\n"
268 " int i;";
269 std::string Expected = "#include <vector>\n"
270 "void f() {}\n"
271 "#define A \\\n"
272 " int i;";
273 EXPECT_EQ(Expected, insert(Code, "<vector>"));
274}
275
276TEST_F(HeaderIncludesTest, SkippedTopComment) {
277 std::string Code = "// comment\n"
278 "\n"
279 " // comment\n";
280 std::string Expected = "// comment\n"
281 "\n"
282 " // comment\n"
283 "#include <vector>\n";
284 EXPECT_EQ(Expected, insert(Code, "<vector>"));
285}
286
287TEST_F(HeaderIncludesTest, SkippedMixedComments) {
288 std::string Code = "// comment\n"
289 "// comment \\\n"
290 " comment continued\n"
291 "/*\n"
292 "* comment\n"
293 "*/\n";
294 std::string Expected = "// comment\n"
295 "// comment \\\n"
296 " comment continued\n"
297 "/*\n"
298 "* comment\n"
299 "*/\n"
300 "#include <vector>\n";
301 EXPECT_EQ(Expected, insert(Code, "<vector>"));
302}
303
304TEST_F(HeaderIncludesTest, MultipleBlockCommentsInOneLine) {
305 std::string Code = "/*\n"
306 "* comment\n"
307 "*/ /* comment\n"
308 "*/\n"
309 "\n\n"
310 "/* c1 */ /*c2 */\n";
311 std::string Expected = "/*\n"
312 "* comment\n"
313 "*/ /* comment\n"
314 "*/\n"
315 "\n\n"
316 "/* c1 */ /*c2 */\n"
317 "#include <vector>\n";
318 EXPECT_EQ(Expected, insert(Code, "<vector>"));
319}
320
321TEST_F(HeaderIncludesTest, CodeAfterComments) {
322 std::string Code = "/*\n"
323 "* comment\n"
324 "*/ /* comment\n"
325 "*/\n"
326 "\n\n"
327 "/* c1 */ /*c2 */\n"
328 "\n"
329 "int x;\n";
330 std::string Expected = "/*\n"
331 "* comment\n"
332 "*/ /* comment\n"
333 "*/\n"
334 "\n\n"
335 "/* c1 */ /*c2 */\n"
336 "\n"
337 "#include <vector>\n"
338 "int x;\n";
339 EXPECT_EQ(Expected, insert(Code, "<vector>"));
340}
341
342TEST_F(HeaderIncludesTest, FakeHeaderGuardIfDef) {
343 std::string Code = "// comment \n"
344 "#ifdef X\n"
345 "#define X\n";
346 std::string Expected = "// comment \n"
347 "#include <vector>\n"
348 "#ifdef X\n"
349 "#define X\n";
350 EXPECT_EQ(Expected, insert(Code, "<vector>"));
351}
352
353TEST_F(HeaderIncludesTest, RealHeaderGuardAfterComments) {
354 std::string Code = "// comment \n"
355 "#ifndef X\n"
356 "#define X\n"
357 "int x;\n"
358 "#define Y 1\n";
359 std::string Expected = "// comment \n"
360 "#ifndef X\n"
361 "#define X\n"
362 "#include <vector>\n"
363 "int x;\n"
364 "#define Y 1\n";
365 EXPECT_EQ(Expected, insert(Code, "<vector>"));
366}
367
368TEST_F(HeaderIncludesTest, PragmaOnce) {
369 std::string Code = "// comment \n"
370 "#pragma once\n"
371 "int x;\n";
372 std::string Expected = "// comment \n"
373 "#pragma once\n"
374 "#include <vector>\n"
375 "int x;\n";
376 EXPECT_EQ(Expected, insert(Code, "<vector>"));
377}
378
379TEST_F(HeaderIncludesTest, IfNDefWithNoDefine) {
380 std::string Code = "// comment \n"
381 "#ifndef X\n"
382 "int x;\n"
383 "#define Y 1\n";
384 std::string Expected = "// comment \n"
385 "#include <vector>\n"
386 "#ifndef X\n"
387 "int x;\n"
388 "#define Y 1\n";
389 EXPECT_EQ(Expected, insert(Code, "<vector>"));
390}
391
392TEST_F(HeaderIncludesTest, FakeHeaderGuard) {
393 std::string Code = "// comment \n"
394 "#ifndef X\n"
395 "#define 1\n";
396 std::string Expected = "// comment \n"
397 "#include <vector>\n"
398 "#ifndef X\n"
399 "#define 1\n";
400 EXPECT_EQ(Expected, insert(Code, "<vector>"));
401}
402
403TEST_F(HeaderIncludesTest, FakeHeaderGuardIfnDef) {
404 std::string Code = "#ifndef A_H\n"
405 "#define A_H 1\n"
406 "#endif";
407 std::string Expected = "#include \"b.h\"\n"
408 "#ifndef A_H\n"
409 "#define A_H 1\n"
410 "#endif";
411
412 EXPECT_EQ(Expected, insert(Code, "\"b.h\""));
413}
414
415TEST_F(HeaderIncludesTest, HeaderGuardWithComment) {
416 std::string Code = "// comment \n"
417 "#ifndef X // comment\n"
418 "// comment\n"
419 "/* comment\n"
420 "*/\n"
421 "/* comment */ #define X\n"
422 "int x;\n"
423 "#define Y 1\n";
424 std::string Expected = "// comment \n"
425 "#ifndef X // comment\n"
426 "// comment\n"
427 "/* comment\n"
428 "*/\n"
429 "/* comment */ #define X\n"
430 "#include <vector>\n"
431 "int x;\n"
432 "#define Y 1\n";
433 EXPECT_EQ(Expected, insert(Code, "<vector>"));
434}
435
436TEST_F(HeaderIncludesTest, EmptyCode) {
437 std::string Code = "";
438 std::string Expected = "#include <vector>\n";
439 EXPECT_EQ(Expected, insert(Code, "<vector>"));
440}
441
442TEST_F(HeaderIncludesTest, NoNewLineAtTheEndOfCode) {
443 std::string Code = "#include <map>";
444 std::string Expected = "#include <map>\n#include <vector>\n";
445 EXPECT_EQ(Expected, insert(Code, "<vector>"));
446}
447
448TEST_F(HeaderIncludesTest, SkipExistingHeaders) {
449 std::string Code = "#include \"a.h\"\n"
450 "#include <vector>\n";
451 std::string Expected = "#include \"a.h\"\n"
452 "#include <vector>\n";
453 EXPECT_EQ(Expected, insert(Code, "<vector>"));
454 EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
455}
456
457TEST_F(HeaderIncludesTest, AddIncludesWithDifferentForms) {
458 std::string Code = "#include <vector>\n";
459 // FIXME: this might not be the best behavior.
460 std::string Expected = "#include \"vector\"\n"
461 "#include <vector>\n";
462 EXPECT_EQ(Expected, insert(Code, "\"vector\""));
463}
464
465TEST_F(HeaderIncludesTest, NoInsertionAfterCode) {
466 std::string Code = "#include \"a.h\"\n"
467 "void f() {}\n"
468 "#include \"b.h\"\n";
469 std::string Expected = "#include \"a.h\"\n"
470 "#include \"c.h\"\n"
471 "void f() {}\n"
472 "#include \"b.h\"\n";
473 EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
474}
475
476TEST_F(HeaderIncludesTest, NoInsertionInStringLiteral) {
477 std::string Code = "#include \"a.h\"\n"
478 "const char[] = R\"(\n"
479 "#include \"b.h\"\n"
480 ")\";\n";
481 std::string Expected = "#include \"a.h\"\n"
482 "#include \"c.h\"\n"
483 "const char[] = R\"(\n"
484 "#include \"b.h\"\n"
485 ")\";\n";
486 EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
487}
488
489TEST_F(HeaderIncludesTest, NoInsertionAfterOtherDirective) {
490 std::string Code = "#include \"a.h\"\n"
491 "#ifdef X\n"
492 "#include \"b.h\"\n"
493 "#endif\n";
494 std::string Expected = "#include \"a.h\"\n"
495 "#include \"c.h\"\n"
496 "#ifdef X\n"
497 "#include \"b.h\"\n"
498 "#endif\n";
499 EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
500}
501
502TEST_F(HeaderIncludesTest, CanInsertAfterLongSystemInclude) {
503 std::string Code = "#include \"a.h\"\n"
504 "// comment\n\n"
505 "#include <a/b/c/d/e.h>\n";
506 std::string Expected = "#include \"a.h\"\n"
507 "// comment\n\n"
508 "#include <a/b/c/d/e.h>\n"
509 "#include <x.h>\n";
510 EXPECT_EQ(Expected, insert(Code, "<x.h>"));
511}
512
513TEST_F(HeaderIncludesTest, CanInsertAfterComment) {
514 std::string Code = "#include \"a.h\"\n"
515 "// Comment\n"
516 "\n"
517 "/* Comment */\n"
518 "// Comment\n"
519 "\n"
520 "#include \"b.h\"\n";
521 std::string Expected = "#include \"a.h\"\n"
522 "// Comment\n"
523 "\n"
524 "/* Comment */\n"
525 "// Comment\n"
526 "\n"
527 "#include \"b.h\"\n"
528 "#include \"c.h\"\n";
529 EXPECT_EQ(Expected, insert(Code, "\"c.h\""));
530}
531
532TEST_F(HeaderIncludesTest, LongCommentsInTheBeginningOfFile) {
533 std::string Code = "// Loooooooooooooooooooooooooong comment\n"
534 "// Loooooooooooooooooooooooooong comment\n"
535 "// Loooooooooooooooooooooooooong comment\n"
536 "#include <string>\n"
537 "#include <vector>\n"
538 "\n"
539 "#include \"a.h\"\n"
540 "#include \"b.h\"\n";
541 std::string Expected = "// Loooooooooooooooooooooooooong comment\n"
542 "// Loooooooooooooooooooooooooong comment\n"
543 "// Loooooooooooooooooooooooooong comment\n"
544 "#include <string>\n"
545 "#include <vector>\n"
546 "\n"
547 "#include \"a.h\"\n"
548 "#include \"b.h\"\n"
549 "#include \"third.h\"\n";
550 Style = format::getGoogleStyle(Language: format::FormatStyle::LanguageKind::LK_Cpp)
551 .IncludeStyle;
552 EXPECT_EQ(Expected, insert(Code, "\"third.h\""));
553}
554
555TEST_F(HeaderIncludesTest, SimpleDeleteInclude) {
556 std::string Code = "#include \"abc.h\"\n"
557 "#include \"xyz.h\" // comment\n"
558 "int x;\n";
559 std::string Expected = "#include \"abc.h\"\n"
560 "int x;\n";
561 EXPECT_EQ(Expected, remove(Code, "\"xyz.h\""));
562}
563
564TEST_F(HeaderIncludesTest, DeleteQuotedOnly) {
565 std::string Code = "#include \"abc.h\"\n"
566 "#include <abc.h>\n"
567 "int x;\n";
568 std::string Expected = "#include <abc.h>\n"
569 "int x;\n";
570 EXPECT_EQ(Expected, remove(Code, "\"abc.h\""));
571}
572
573TEST_F(HeaderIncludesTest, DeleteAllCode) {
574 std::string Code = "#include \"xyz.h\"\n";
575 std::string Expected = "";
576 EXPECT_EQ(Expected, remove(Code, "\"xyz.h\""));
577}
578
579TEST_F(HeaderIncludesTest, DeleteOnlyIncludesWithSameQuote) {
580 std::string Code = "#include \"xyz.h\"\n"
581 "#include \"xyz\"\n"
582 "#include <xyz.h>\n";
583 std::string Expected = "#include \"xyz.h\"\n"
584 "#include \"xyz\"\n";
585 EXPECT_EQ(Expected, remove(Code, "<xyz.h>"));
586}
587
588TEST_F(HeaderIncludesTest, CanDeleteAfterCode) {
589 std::string Code = "#include \"a.h\"\n"
590 "void f() {}\n"
591 "#include \"b.h\"\n";
592 std::string Expected = "#include \"a.h\"\n"
593 "void f() {}\n";
594 EXPECT_EQ(Expected, remove(Code, "\"b.h\""));
595}
596
597} // namespace
598} // namespace tooling
599} // namespace clang
600

source code of clang/unittests/Tooling/HeaderIncludesTest.cpp