blob: 635d7ebb1e9f3a1a77127c6b7b5ca9fedb8df32f [file] [log] [blame]
Eric Liu7129e632018-05-14 20:17:53 +00001//===- unittest/Tooling/CleanupTest.cpp - Include insertion/deletion tests ===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Eric Liu7129e632018-05-14 20:17:53 +00006//
7//===----------------------------------------------------------------------===//
8
Eric Liu44564ac2018-06-04 09:04:12 +00009#include "clang/Tooling/Inclusions/HeaderIncludes.h"
Eric Liu7129e632018-05-14 20:17:53 +000010#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
Eric Liu7129e632018-05-14 20:17:53 +000017namespace clang {
18namespace tooling {
19namespace {
20
21class HeaderIncludesTest : public ::testing::Test {
22protected:
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 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
47TEST_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
54TEST_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
70TEST_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
94TEST_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
107TEST_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
118TEST_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
131TEST_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
146TEST_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
159TEST_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
180TEST_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
195TEST_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
212TEST_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
223TEST_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
234TEST_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
251TEST_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
268TEST_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
289TEST_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
300TEST_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
Eric Liu24739612019-01-29 14:40:01 +0000315TEST_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
Eric Liu7129e632018-05-14 20:17:53 +0000326TEST_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
339TEST_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
350TEST_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
371TEST_F(HeaderIncludesTest, EmptyCode) {
372 std::string Code = "";
373 std::string Expected = "#include <vector>\n";
374 EXPECT_EQ(Expected, insert(Code, "<vector>"));
375}
376
377TEST_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
383TEST_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
392TEST_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
400TEST_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
411TEST_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
424TEST_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
437TEST_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
448TEST_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
467TEST_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
490TEST_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
499TEST_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
508TEST_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
514TEST_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
523TEST_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