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