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