742 lines · cpp
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-exception6//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.trim("\"<>"), Header.starts_with("<"),28 Directive);29 if (!R)30 return std::string(Code);31 auto Result = applyAllReplacements(Code, 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.trim("\"<>"), Header.starts_with("<"));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(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(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(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 be254 // 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(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(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 597TEST_F(HeaderIncludesTest, InsertInGlobalModuleFragment) {598 // Ensure header insertions go only in the global module fragment599 std::string Code = R"cpp(// comments600 601// more comments602 603module;604export module foo;605 606int main() {607 std::vector<int> ints {};608})cpp";609 std::string Expected = R"cpp(// comments610 611// more comments612 613module;614#include <vector>615export module foo;616 617int main() {618 std::vector<int> ints {};619})cpp";620 621 auto InsertedCode = insert(Code, "<vector>");622 EXPECT_EQ(Expected, insert(Code, "<vector>"));623}624 625TEST_F(HeaderIncludesTest, InsertInGlobalModuleFragmentWithPP) {626 // Ensure header insertions go only in the global module fragment627 std::string Code = R"cpp(// comments628 629// more comments630 631// some more comments632 633module;634 635#ifndef MACRO_NAME636#define MACRO_NAME637#endif638 639// comment640 641#ifndef MACRO_NAME642#define MACRO_NAME643#endif644 645// more comment646 647int main() {648 std::vector<int> ints {};649})cpp";650 std::string Expected = R"cpp(// comments651 652// more comments653 654// some more comments655 656module;657 658#include <vector>659#ifndef MACRO_NAME660#define MACRO_NAME661#endif662 663// comment664 665#ifndef MACRO_NAME666#define MACRO_NAME667#endif668 669// more comment670 671int main() {672 std::vector<int> ints {};673})cpp";674 675 EXPECT_EQ(Expected, insert(Code, "<vector>"));676}677 678TEST_F(HeaderIncludesTest, InsertInGlobalModuleFragmentWithPPIncludes) {679 // Ensure header insertions go only in the global module fragment680 std::string Code = R"cpp(// comments681 682// more comments683 684// some more comments685 686module;687 688#include "header.h"689 690#include <string>691 692#ifndef MACRO_NAME693#define MACRO_NAME694#endif695 696// comment697 698#ifndef MACRO_NAME699#define MACRO_NAME700#endif701 702// more comment703 704int main() {705 std::vector<int> ints {};706})cpp";707 std::string Expected = R"cpp(// comments708 709// more comments710 711// some more comments712 713module;714 715#include "header.h"716 717#include <string>718#include <vector>719 720#ifndef MACRO_NAME721#define MACRO_NAME722#endif723 724// comment725 726#ifndef MACRO_NAME727#define MACRO_NAME728#endif729 730// more comment731 732int main() {733 std::vector<int> ints {};734})cpp";735 736 EXPECT_EQ(Expected, insert(Code, "<vector>"));737}738 739} // namespace740} // namespace tooling741} // namespace clang742