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