1 //===- unittest/Format/CleanupTest.cpp - Code cleanup unit 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 10 #include "clang/Format/Format.h" 11 12 #include "../Tooling/ReplacementTest.h" 13 #include "../Tooling/RewriterTestContext.h" 14 #include "clang/Tooling/Core/Replacement.h" 15 16 #include "gtest/gtest.h" 17 18 using clang::tooling::ReplacementTest; 19 using clang::tooling::toReplacements; 20 21 namespace clang { 22 namespace format { 23 namespace { 24 25 class CleanupTest : public ::testing::Test { 26 protected: 27 std::string cleanup(llvm::StringRef Code, 28 const std::vector<tooling::Range> &Ranges, 29 const FormatStyle &Style = getLLVMStyle()) { 30 tooling::Replacements Replaces = format::cleanup(Style, Code, Ranges); 31 32 auto Result = applyAllReplacements(Code, Replaces); 33 EXPECT_TRUE(static_cast<bool>(Result)); 34 return *Result; 35 } 36 37 // Returns code after cleanup around \p Offsets. 38 std::string cleanupAroundOffsets(llvm::ArrayRef<unsigned> Offsets, 39 llvm::StringRef Code, 40 const FormatStyle &Style = getLLVMStyle()) { 41 std::vector<tooling::Range> Ranges; 42 for (auto Offset : Offsets) 43 Ranges.push_back(tooling::Range(Offset, 0)); 44 return cleanup(Code, Ranges, Style); 45 } 46 }; 47 48 TEST_F(CleanupTest, DeleteEmptyNamespaces) { 49 std::string Code = "namespace A {\n" 50 "namespace B {\n" 51 "} // namespace B\n" 52 "} // namespace A\n\n" 53 "namespace C {\n" 54 "namespace D { int i; }\n" 55 "inline namespace E { namespace { } }\n" 56 "}"; 57 std::string Expected = "\n\n\n\n\nnamespace C {\n" 58 "namespace D { int i; }\n \n" 59 "}"; 60 EXPECT_EQ(Expected, cleanupAroundOffsets({28, 91, 132}, Code)); 61 } 62 63 TEST_F(CleanupTest, NamespaceWithSyntaxError) { 64 std::string Code = "namespace A {\n" 65 "namespace B {\n" // missing r_brace 66 "} // namespace A\n\n" 67 "namespace C {\n" 68 "namespace D int i; }\n" 69 "inline namespace E { namespace { } }\n" 70 "}"; 71 std::string Expected = "namespace A {\n" 72 "\n\n\nnamespace C {\n" 73 "namespace D int i; }\n \n" 74 "}"; 75 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 76 EXPECT_EQ(Expected, cleanup(Code, Ranges)); 77 } 78 79 TEST_F(CleanupTest, EmptyNamespaceNotAffected) { 80 std::string Code = "namespace A {\n\n" 81 "namespace {\n\n}}"; 82 // Even though the namespaces are empty, but the inner most empty namespace 83 // block is not affected by the changed ranges. 84 std::string Expected = "namespace A {\n\n" 85 "namespace {\n\n}}"; 86 // Set the changed range to be the second "\n". 87 EXPECT_EQ(Expected, cleanupAroundOffsets({14}, Code)); 88 } 89 90 TEST_F(CleanupTest, EmptyNamespaceWithCommentsNoBreakBeforeBrace) { 91 std::string Code = "namespace A {\n" 92 "namespace B {\n" 93 "// Yo\n" 94 "} // namespace B\n" 95 "} // namespace A\n" 96 "namespace C { // Yo\n" 97 "}"; 98 std::string Expected = "\n\n\n\n\n\n"; 99 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 100 std::string Result = cleanup(Code, Ranges); 101 EXPECT_EQ(Expected, Result); 102 } 103 104 TEST_F(CleanupTest, EmptyNamespaceWithCommentsBreakBeforeBrace) { 105 std::string Code = "namespace A\n" 106 "/* Yo */ {\n" 107 "namespace B\n" 108 "{\n" 109 "// Yo\n" 110 "} // namespace B\n" 111 "} // namespace A\n" 112 "namespace C\n" 113 "{ // Yo\n" 114 "}\n"; 115 std::string Expected = "\n\n\n\n\n\n\n\n\n\n"; 116 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 117 FormatStyle Style = getLLVMStyle(); 118 Style.BraceWrapping.AfterNamespace = true; 119 std::string Result = cleanup(Code, Ranges, Style); 120 EXPECT_EQ(Expected, Result); 121 } 122 123 TEST_F(CleanupTest, EmptyNamespaceAroundConditionalCompilation) { 124 std::string Code = "#ifdef A\n" 125 "int a;\n" 126 "int b;\n" 127 "#else\n" 128 "#endif\n" 129 "namespace {}"; 130 std::string Expected = "#ifdef A\n" 131 "int a;\n" 132 "int b;\n" 133 "#else\n" 134 "#endif\n"; 135 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 136 FormatStyle Style = getLLVMStyle(); 137 std::string Result = cleanup(Code, Ranges, Style); 138 EXPECT_EQ(Expected, Result); 139 } 140 141 TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) { 142 std::string Code = "class A {\nA() : , {} };"; 143 std::string Expected = "class A {\nA() {} };"; 144 EXPECT_EQ(Expected, cleanupAroundOffsets({17, 19}, Code)); 145 146 Code = "class A {\nA() : x(1), {} };"; 147 Expected = "class A {\nA() : x(1) {} };"; 148 EXPECT_EQ(Expected, cleanupAroundOffsets({23}, Code)); 149 150 Code = "class A {\nA() :,,,,{} };"; 151 Expected = "class A {\nA() {} };"; 152 EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code)); 153 } 154 155 TEST_F(CleanupTest, CtorInitializationSimpleRedundantColon) { 156 std::string Code = "class A {\nA() : =default; };"; 157 std::string Expected = "class A {\nA() =default; };"; 158 EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code)); 159 160 Code = "class A {\nA() : , =default; };"; 161 Expected = "class A {\nA() =default; };"; 162 EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code)); 163 } 164 165 TEST_F(CleanupTest, ListRedundantComma) { 166 std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }"; 167 std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }"; 168 EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code)); 169 170 Code = "int main() { f(1,,2,3,,4);}"; 171 Expected = "int main() { f(1,2,3,4);}"; 172 EXPECT_EQ(Expected, cleanupAroundOffsets({17, 22}, Code)); 173 } 174 175 TEST_F(CleanupTest, NoCleanupsForJavaScript) { 176 std::string Code = "function f() { var x = [a, b, , c]; }"; 177 std::string Expected = "function f() { var x = [a, b, , c]; }"; 178 const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript); 179 180 EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code, Style)); 181 } 182 183 TEST_F(CleanupTest, TrailingCommaInParens) { 184 std::string Code = "int main() { f(,1,,2,3,f(1,2,),4,,);}"; 185 std::string Expected = "int main() { f(1,2,3,f(1,2),4);}"; 186 EXPECT_EQ(Expected, cleanupAroundOffsets({15, 18, 29, 33}, Code)); 187 } 188 189 TEST_F(CleanupTest, TrailingCommaInBraces) { 190 // Trainling comma is allowed in brace list. 191 // If there was trailing comma in the original code, then trailing comma is 192 // preserved. In this example, element between the last two commas is deleted 193 // causing the second-last comma to be redundant. 194 std::string Code = "void f() { std::vector<int> v = {1,2,3,,}; }"; 195 std::string Expected = "void f() { std::vector<int> v = {1,2,3,}; }"; 196 EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code)); 197 198 // If there was no trailing comma in the original code, then trainling comma 199 // introduced by replacements should be cleaned up. In this example, the 200 // element after the last comma is deleted causing the last comma to be 201 // redundant. 202 Code = "void f() { std::vector<int> v = {1,2,3,}; }"; 203 // FIXME: redundant trailing comma should be removed. 204 Expected = "void f() { std::vector<int> v = {1,2,3,}; }"; 205 EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code)); 206 207 // Still no trailing comma in the original code, but two elements are deleted, 208 // which makes it seems like there was trailing comma. 209 Code = "void f() { std::vector<int> v = {1, 2, 3, , }; }"; 210 // FIXME: redundant trailing comma should also be removed. 211 Expected = "void f() { std::vector<int> v = {1, 2, 3, }; }"; 212 EXPECT_EQ(Expected, cleanupAroundOffsets({42, 44}, Code)); 213 } 214 215 TEST_F(CleanupTest, CtorInitializationBracesInParens) { 216 std::string Code = "class A {\nA() : x({1}),, {} };"; 217 std::string Expected = "class A {\nA() : x({1}) {} };"; 218 EXPECT_EQ(Expected, cleanupAroundOffsets({24, 26}, Code)); 219 } 220 221 TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) { 222 std::string Code = 223 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };"; 224 std::string Expected = 225 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };"; 226 // Set the affected range to be "int x = 0", which does not intercept the 227 // constructor initialization list. 228 std::vector<tooling::Range> Ranges(1, tooling::Range(42, 9)); 229 std::string Result = cleanup(Code, Ranges); 230 EXPECT_EQ(Expected, Result); 231 232 Code = "class A {\nA() : x(1), {} };"; 233 Expected = "class A {\nA() : x(1), {} };"; 234 // No range. Fixer should do nothing. 235 Ranges.clear(); 236 Result = cleanup(Code, Ranges); 237 EXPECT_EQ(Expected, Result); 238 } 239 240 TEST_F(CleanupTest, RemoveCommentsAroundDeleteCode) { 241 std::string Code = 242 "class A {\nA() : x({1}), /* comment */, /* comment */ {} };"; 243 std::string Expected = "class A {\nA() : x({1}) {} };"; 244 EXPECT_EQ(Expected, cleanupAroundOffsets({25, 40}, Code)); 245 246 Code = "class A {\nA() : x({1}), // comment\n {} };"; 247 Expected = "class A {\nA() : x({1})\n {} };"; 248 EXPECT_EQ(Expected, cleanupAroundOffsets({25}, Code)); 249 250 Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };"; 251 Expected = "class A {\nA() : x({1}), y(1){} };"; 252 EXPECT_EQ(Expected, cleanupAroundOffsets({38}, Code)); 253 254 Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };"; 255 Expected = "class A {\nA() : x({1}), \n y(1){} };"; 256 EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code)); 257 258 Code = "class A {\nA() : , // comment\n y(1),{} };"; 259 Expected = "class A {\nA() : // comment\n y(1){} };"; 260 EXPECT_EQ(Expected, cleanupAroundOffsets({17}, Code)); 261 262 Code = "class A {\nA() // comment\n : ,,{} };"; 263 Expected = "class A {\nA() // comment\n {} };"; 264 EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code)); 265 266 Code = "class A {\nA() // comment\n : ,,=default; };"; 267 Expected = "class A {\nA() // comment\n =default; };"; 268 EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code)); 269 } 270 271 TEST_F(CleanupTest, CtorInitializerInNamespace) { 272 std::string Code = "namespace A {\n" 273 "namespace B {\n" // missing r_brace 274 "} // namespace A\n\n" 275 "namespace C {\n" 276 "class A { A() : x(0),, {} };\n" 277 "inline namespace E { namespace { } }\n" 278 "}"; 279 std::string Expected = "namespace A {\n" 280 "\n\n\nnamespace C {\n" 281 "class A { A() : x(0) {} };\n \n" 282 "}"; 283 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 284 std::string Result = cleanup(Code, Ranges); 285 EXPECT_EQ(Expected, Result); 286 } 287 288 class CleanUpReplacementsTest : public ReplacementTest { 289 protected: 290 tooling::Replacement createReplacement(unsigned Offset, unsigned Length, 291 StringRef Text) { 292 return tooling::Replacement(FileName, Offset, Length, Text); 293 } 294 295 tooling::Replacement createInsertion(StringRef IncludeDirective) { 296 return createReplacement(UINT_MAX, 0, IncludeDirective); 297 } 298 299 tooling::Replacement createDeletion(StringRef HeaderName) { 300 return createReplacement(UINT_MAX, 1, HeaderName); 301 } 302 303 inline std::string apply(StringRef Code, 304 const tooling::Replacements &Replaces) { 305 auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style); 306 EXPECT_TRUE(static_cast<bool>(CleanReplaces)) 307 << llvm::toString(CleanReplaces.takeError()) << "\n"; 308 auto Result = applyAllReplacements(Code, *CleanReplaces); 309 EXPECT_TRUE(static_cast<bool>(Result)); 310 return *Result; 311 } 312 313 inline std::string formatAndApply(StringRef Code, 314 const tooling::Replacements &Replaces) { 315 auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style); 316 EXPECT_TRUE(static_cast<bool>(CleanReplaces)) 317 << llvm::toString(CleanReplaces.takeError()) << "\n"; 318 auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style); 319 EXPECT_TRUE(static_cast<bool>(FormattedReplaces)) 320 << llvm::toString(FormattedReplaces.takeError()) << "\n"; 321 auto Result = applyAllReplacements(Code, *FormattedReplaces); 322 EXPECT_TRUE(static_cast<bool>(Result)); 323 return *Result; 324 } 325 326 int getOffset(StringRef Code, int Line, int Column) { 327 RewriterTestContext Context; 328 FileID ID = Context.createInMemoryFile(FileName, Code); 329 auto DecomposedLocation = 330 Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column)); 331 return DecomposedLocation.second; 332 } 333 334 const std::string FileName = "fix.cpp"; 335 FormatStyle Style = getLLVMStyle(); 336 }; 337 338 TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) { 339 std::string Code = "namespace A {\n" 340 "namespace B {\n" 341 " int x;\n" 342 "} // namespace B\n" 343 "} // namespace A\n" 344 "\n" 345 "namespace C {\n" 346 "namespace D { int i; }\n" 347 "inline namespace E { namespace { int y; } }\n" 348 "int x= 0;" 349 "}"; 350 std::string Expected = "\n\nnamespace C {\n" 351 "namespace D { int i; }\n\n" 352 "int x= 0;" 353 "}"; 354 tooling::Replacements Replaces = 355 toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""), 356 createReplacement(getOffset(Code, 9, 34), 6, "")}); 357 358 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 359 } 360 361 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) { 362 std::string Code = "int main() {}"; 363 std::string Expected = "#include \"a.h\"\n" 364 "int main() {}"; 365 tooling::Replacements Replaces = 366 toReplacements({createInsertion("#include \"a.h\"")}); 367 EXPECT_EQ(Expected, apply(Code, Replaces)); 368 } 369 370 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) { 371 std::string Code = "#ifndef A_H\n" 372 "#define A_H\n" 373 "class A {};\n" 374 "#define MMM 123\n" 375 "#endif"; 376 std::string Expected = "#ifndef A_H\n" 377 "#define A_H\n" 378 "#include \"b.h\"\n" 379 "class A {};\n" 380 "#define MMM 123\n" 381 "#endif"; 382 383 tooling::Replacements Replaces = 384 toReplacements({createInsertion("#include \"b.h\"")}); 385 EXPECT_EQ(Expected, apply(Code, Replaces)); 386 } 387 388 TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) { 389 std::string Code = "#ifndef A_H\n" 390 "#define A_H\n" 391 "\n" 392 "\n" 393 "\n" 394 "#include <vector>\n" 395 "class A {};\n" 396 "#define MMM 123\n" 397 "#endif"; 398 std::string Expected = "#ifndef A_H\n" 399 "#define A_H\n" 400 "\n" 401 "\n" 402 "\n" 403 "#include \"a.h\"\n" 404 "#include <vector>\n" 405 "class A {};\n" 406 "#define MMM 123\n" 407 "#endif"; 408 409 tooling::Replacements Replaces = 410 toReplacements({createInsertion("#include \"a.h\"")}); 411 EXPECT_EQ(Expected, apply(Code, Replaces)); 412 } 413 414 TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) { 415 std::string Code = "#include \"fix.h\"\n" 416 "\n" 417 "int main() {}"; 418 std::string Expected = "#include \"fix.h\"\n" 419 "#include <a>\n" 420 "\n" 421 "int main() {}"; 422 tooling::Replacements Replaces = 423 toReplacements({createInsertion("#include <a>")}); 424 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 425 EXPECT_EQ(Expected, apply(Code, Replaces)); 426 } 427 428 TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) { 429 std::string Code = "#include <memory>\n" 430 "\n" 431 "int main() {}"; 432 std::string Expected = "#include \"z.h\"\n" 433 "#include <memory>\n" 434 "\n" 435 "int main() {}"; 436 tooling::Replacements Replaces = 437 toReplacements({createInsertion("#include \"z.h\"")}); 438 EXPECT_EQ(Expected, apply(Code, Replaces)); 439 } 440 441 TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) { 442 std::string Code = "#include <memory>\n" 443 "\n" 444 "int main() {}"; 445 std::string Expected = "#include <memory>\n" 446 "#include \"z.h\"\n" 447 "\n" 448 "int main() {}"; 449 tooling::Replacements Replaces = 450 toReplacements({createInsertion("#include \"z.h\"")}); 451 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 452 EXPECT_EQ(Expected, apply(Code, Replaces)); 453 } 454 455 TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) { 456 std::string Code = "#include \"x/fix.h\"\n" 457 "#include \"a.h\"\n" 458 "#include \"b.h\"\n" 459 "#include \"clang/Format/Format.h\"\n" 460 "#include <memory>\n"; 461 std::string Expected = "#include \"x/fix.h\"\n" 462 "#include \"a.h\"\n" 463 "#include \"b.h\"\n" 464 "#include \"d.h\"\n" 465 "#include \"clang/Format/Format.h\"\n" 466 "#include \"llvm/x/y.h\"\n" 467 "#include <memory>\n"; 468 tooling::Replacements Replaces = 469 toReplacements({createInsertion("#include \"d.h\""), 470 createInsertion("#include \"llvm/x/y.h\"")}); 471 EXPECT_EQ(Expected, apply(Code, Replaces)); 472 } 473 474 TEST_F(CleanUpReplacementsTest, InsertIntoBlockSorted) { 475 std::string Code = "#include \"x/fix.h\"\n" 476 "#include \"a.h\"\n" 477 "#include \"c.h\"\n" 478 "#include <memory>\n"; 479 std::string Expected = "#include \"x/fix.h\"\n" 480 "#include \"a.h\"\n" 481 "#include \"b.h\"\n" 482 "#include \"c.h\"\n" 483 "#include <memory>\n"; 484 tooling::Replacements Replaces = 485 toReplacements({createInsertion("#include \"b.h\"")}); 486 EXPECT_EQ(Expected, apply(Code, Replaces)); 487 } 488 489 TEST_F(CleanUpReplacementsTest, InsertIntoFirstBlockOfSameKind) { 490 std::string Code = "#include \"x/fix.h\"\n" 491 "#include \"c.h\"\n" 492 "#include \"e.h\"\n" 493 "#include \"f.h\"\n" 494 "#include <memory>\n" 495 "#include <vector>\n" 496 "#include \"m.h\"\n" 497 "#include \"n.h\"\n"; 498 std::string Expected = "#include \"x/fix.h\"\n" 499 "#include \"c.h\"\n" 500 "#include \"d.h\"\n" 501 "#include \"e.h\"\n" 502 "#include \"f.h\"\n" 503 "#include <memory>\n" 504 "#include <vector>\n" 505 "#include \"m.h\"\n" 506 "#include \"n.h\"\n"; 507 tooling::Replacements Replaces = 508 toReplacements({createInsertion("#include \"d.h\"")}); 509 EXPECT_EQ(Expected, apply(Code, Replaces)); 510 } 511 512 TEST_F(CleanUpReplacementsTest, InsertIntoSystemBlockSorted) { 513 std::string Code = "#include \"x/fix.h\"\n" 514 "#include \"a.h\"\n" 515 "#include \"c.h\"\n" 516 "#include <a>\n" 517 "#include <z>\n"; 518 std::string Expected = "#include \"x/fix.h\"\n" 519 "#include \"a.h\"\n" 520 "#include \"c.h\"\n" 521 "#include <a>\n" 522 "#include <vector>\n" 523 "#include <z>\n"; 524 tooling::Replacements Replaces = 525 toReplacements({createInsertion("#include <vector>")}); 526 EXPECT_EQ(Expected, apply(Code, Replaces)); 527 } 528 529 530 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) { 531 std::string Code = "#include \"x/fix.h\"\n" 532 "#include \"a.h\"\n" 533 "#include \"b.h\"\n" 534 "#include \"z.h\"\n" 535 "#include \"clang/Format/Format.h\"\n" 536 "#include <memory>\n"; 537 std::string Expected = "#include \"x/fix.h\"\n" 538 "#include \"a.h\"\n" 539 "#include \"b.h\"\n" 540 "#include \"new/new.h\"\n" 541 "#include \"z.h\"\n" 542 "#include \"clang/Format/Format.h\"\n" 543 "#include <list>\n" 544 "#include <memory>\n"; 545 tooling::Replacements Replaces = 546 toReplacements({createInsertion("#include <list>"), 547 createInsertion("#include \"new/new.h\"")}); 548 EXPECT_EQ(Expected, apply(Code, Replaces)); 549 } 550 551 TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) { 552 std::string Code = "#include \"x/fix.h\"\n" 553 "\n" 554 "#include \"y/a.h\"\n" 555 "#include \"z/b.h\"\n"; 556 // FIXME: inserting after the empty line following the main header might be 557 // preferred. 558 std::string Expected = "#include \"x/fix.h\"\n" 559 "#include <vector>\n" 560 "\n" 561 "#include \"y/a.h\"\n" 562 "#include \"z/b.h\"\n"; 563 tooling::Replacements Replaces = 564 toReplacements({createInsertion("#include <vector>")}); 565 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 566 EXPECT_EQ(Expected, apply(Code, Replaces)); 567 } 568 569 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) { 570 std::string Code = "#include \"x/fix.h\"\n" 571 "\n" 572 "#include <vector>\n" 573 "\n" 574 "#include \"y/a.h\"\n" 575 "#include \"z/b.h\"\n"; 576 std::string Expected = "#include \"x/fix.h\"\n" 577 "\n" 578 "#include <list>\n" 579 "#include <vector>\n" 580 "\n" 581 "#include \"x/x.h\"\n" 582 "#include \"y/a.h\"\n" 583 "#include \"z/b.h\"\n"; 584 tooling::Replacements Replaces = 585 toReplacements({createInsertion("#include <list>"), 586 createInsertion("#include \"x/x.h\"")}); 587 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 588 EXPECT_EQ(Expected, apply(Code, Replaces)); 589 } 590 591 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) { 592 std::string Code = "\nint x;"; 593 std::string Expected = "\n#include \"fix.h\"\n" 594 "#include \"a.h\"\n" 595 "#include \"b.h\"\n" 596 "#include \"c.h\"\n" 597 "#include <list>\n" 598 "#include <vector>\n" 599 "int x;"; 600 tooling::Replacements Replaces = toReplacements( 601 {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""), 602 createInsertion("#include \"b.h\""), 603 createInsertion("#include <vector>"), createInsertion("#include <list>"), 604 createInsertion("#include \"fix.h\"")}); 605 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 606 } 607 608 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) { 609 std::string Code = "\nint x;"; 610 std::string Expected = "\n#include \"fix.h\"\n" 611 "#include <list>\n" 612 "#include <vector>\n" 613 "#include \"a.h\"\n" 614 "#include \"b.h\"\n" 615 "#include \"c.h\"\n" 616 "int x;"; 617 tooling::Replacements Replaces = toReplacements( 618 {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""), 619 createInsertion("#include \"b.h\""), 620 createInsertion("#include <vector>"), createInsertion("#include <list>"), 621 createInsertion("#include \"fix.h\"")}); 622 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 623 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 624 } 625 626 TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) { 627 std::string Code = "\n" 628 "int x;\n" 629 "int a;\n" 630 "int a;\n" 631 "int a;"; 632 633 std::string Expected = "\n#include \"x.h\"\n" 634 "#include \"y.h\"\n" 635 "#include \"clang/x/x.h\"\n" 636 "#include <list>\n" 637 "#include <vector>\n" 638 "int x;\n" 639 "int a;\n" 640 "int b;\n" 641 "int a;"; 642 tooling::Replacements Replaces = toReplacements( 643 {createReplacement(getOffset(Code, 4, 8), 1, "b"), 644 createInsertion("#include <vector>"), createInsertion("#include <list>"), 645 createInsertion("#include \"clang/x/x.h\""), 646 createInsertion("#include \"y.h\""), 647 createInsertion("#include \"x.h\"")}); 648 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 649 } 650 651 TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) { 652 std::string Code = "void f() {}\n" 653 "#define A \\\n" 654 " int i;"; 655 std::string Expected = "#include <vector>\n" 656 "void f() {}\n" 657 "#define A \\\n" 658 " int i;"; 659 tooling::Replacements Replaces = 660 toReplacements({createInsertion("#include <vector>")}); 661 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 662 } 663 664 TEST_F(CleanUpReplacementsTest, SkippedTopComment) { 665 std::string Code = "// comment\n" 666 "\n" 667 " // comment\n"; 668 std::string Expected = "// comment\n" 669 "\n" 670 " // comment\n" 671 "#include <vector>\n"; 672 tooling::Replacements Replaces = 673 toReplacements({createInsertion("#include <vector>")}); 674 EXPECT_EQ(Expected, apply(Code, Replaces)); 675 } 676 677 TEST_F(CleanUpReplacementsTest, SkippedMixedComments) { 678 std::string Code = "// comment\n" 679 "// comment \\\n" 680 " comment continued\n" 681 "/*\n" 682 "* comment\n" 683 "*/\n"; 684 std::string Expected = "// comment\n" 685 "// comment \\\n" 686 " comment continued\n" 687 "/*\n" 688 "* comment\n" 689 "*/\n" 690 "#include <vector>\n"; 691 tooling::Replacements Replaces = 692 toReplacements({createInsertion("#include <vector>")}); 693 EXPECT_EQ(Expected, apply(Code, Replaces)); 694 } 695 696 TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) { 697 std::string Code = "/*\n" 698 "* comment\n" 699 "*/ /* comment\n" 700 "*/\n" 701 "\n\n" 702 "/* c1 */ /*c2 */\n"; 703 std::string Expected = "/*\n" 704 "* comment\n" 705 "*/ /* comment\n" 706 "*/\n" 707 "\n\n" 708 "/* c1 */ /*c2 */\n" 709 "#include <vector>\n"; 710 tooling::Replacements Replaces = 711 toReplacements({createInsertion("#include <vector>")}); 712 EXPECT_EQ(Expected, apply(Code, Replaces)); 713 } 714 715 TEST_F(CleanUpReplacementsTest, CodeAfterComments) { 716 std::string Code = "/*\n" 717 "* comment\n" 718 "*/ /* comment\n" 719 "*/\n" 720 "\n\n" 721 "/* c1 */ /*c2 */\n" 722 "\n" 723 "int x;\n"; 724 std::string Expected = "/*\n" 725 "* comment\n" 726 "*/ /* comment\n" 727 "*/\n" 728 "\n\n" 729 "/* c1 */ /*c2 */\n" 730 "\n" 731 "#include <vector>\n" 732 "int x;\n"; 733 tooling::Replacements Replaces = 734 toReplacements({createInsertion("#include <vector>")}); 735 EXPECT_EQ(Expected, apply(Code, Replaces)); 736 } 737 738 TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) { 739 std::string Code = "// comment \n" 740 "#ifdef X\n" 741 "#define X\n"; 742 std::string Expected = "// comment \n" 743 "#include <vector>\n" 744 "#ifdef X\n" 745 "#define X\n"; 746 tooling::Replacements Replaces = 747 toReplacements({createInsertion("#include <vector>")}); 748 EXPECT_EQ(Expected, apply(Code, Replaces)); 749 } 750 751 TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) { 752 std::string Code = "// comment \n" 753 "#ifndef X\n" 754 "#define X\n" 755 "int x;\n" 756 "#define Y 1\n"; 757 std::string Expected = "// comment \n" 758 "#ifndef X\n" 759 "#define X\n" 760 "#include <vector>\n" 761 "int x;\n" 762 "#define Y 1\n"; 763 tooling::Replacements Replaces = 764 toReplacements({createInsertion("#include <vector>")}); 765 EXPECT_EQ(Expected, apply(Code, Replaces)); 766 } 767 768 TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) { 769 std::string Code = "// comment \n" 770 "#ifndef X\n" 771 "int x;\n" 772 "#define Y 1\n"; 773 std::string Expected = "// comment \n" 774 "#include <vector>\n" 775 "#ifndef X\n" 776 "int x;\n" 777 "#define Y 1\n"; 778 tooling::Replacements Replaces = 779 toReplacements({createInsertion("#include <vector>")}); 780 EXPECT_EQ(Expected, apply(Code, Replaces)); 781 } 782 783 TEST_F(CleanUpReplacementsTest, FakeHeaderGuard) { 784 std::string Code = "// comment \n" 785 "#ifndef X\n" 786 "#define 1\n"; 787 std::string Expected = "// comment \n" 788 "#include <vector>\n" 789 "#ifndef X\n" 790 "#define 1\n"; 791 tooling::Replacements Replaces = 792 toReplacements({createInsertion("#include <vector>")}); 793 EXPECT_EQ(Expected, apply(Code, Replaces)); 794 } 795 796 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) { 797 std::string Code = "// comment \n" 798 "#ifndef X // comment\n" 799 "// comment\n" 800 "/* comment\n" 801 "*/\n" 802 "/* comment */ #define X\n" 803 "int x;\n" 804 "#define Y 1\n"; 805 std::string Expected = "// comment \n" 806 "#ifndef X // comment\n" 807 "// comment\n" 808 "/* comment\n" 809 "*/\n" 810 "/* comment */ #define X\n" 811 "#include <vector>\n" 812 "int x;\n" 813 "#define Y 1\n"; 814 tooling::Replacements Replaces = 815 toReplacements({createInsertion("#include <vector>")}); 816 EXPECT_EQ(Expected, apply(Code, Replaces)); 817 } 818 819 TEST_F(CleanUpReplacementsTest, EmptyCode) { 820 std::string Code = ""; 821 std::string Expected = "#include <vector>\n"; 822 tooling::Replacements Replaces = 823 toReplacements({createInsertion("#include <vector>")}); 824 EXPECT_EQ(Expected, apply(Code, Replaces)); 825 } 826 827 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) { 828 std::string Code = "#include <map>"; 829 std::string Expected = "#include <map>\n#include <vector>\n"; 830 tooling::Replacements Replaces = 831 toReplacements({createInsertion("#include <vector>")}); 832 EXPECT_EQ(Expected, apply(Code, Replaces)); 833 } 834 835 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) { 836 std::string Code = "#include <map>"; 837 // FIXME: a better behavior is to only append on newline to Code, but this 838 // case should be rare in practice. 839 std::string Expected = 840 "#include <map>\n#include <string>\n\n#include <vector>\n"; 841 tooling::Replacements Replaces = 842 toReplacements({createInsertion("#include <string>"), 843 createInsertion("#include <vector>")}); 844 EXPECT_EQ(Expected, apply(Code, Replaces)); 845 } 846 847 TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) { 848 std::string Code = "#include \"a.h\"\n" 849 "#include <vector>\n"; 850 std::string Expected = "#include \"a.h\"\n" 851 "#include <vector>\n"; 852 tooling::Replacements Replaces = 853 toReplacements({createInsertion("#include <vector>"), 854 createInsertion("#include \"a.h\"")}); 855 EXPECT_EQ(Expected, apply(Code, Replaces)); 856 } 857 858 TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) { 859 std::string Code = "#include \"a.h\"\n" 860 "#include <vector>\n"; 861 // FIXME: this might not be the best behavior. 862 std::string Expected = "#include \"a.h\"\n" 863 "#include \"vector\"\n" 864 "#include <a.h>\n" 865 "#include <vector>\n"; 866 tooling::Replacements Replaces = 867 toReplacements({createInsertion("#include \"vector\""), 868 createInsertion("#include <a.h>")}); 869 EXPECT_EQ(Expected, apply(Code, Replaces)); 870 } 871 872 TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) { 873 std::string Code = "#include \"abc.h\"\n" 874 "#include \"xyz.h\" // comment\n" 875 "#include \"xyz\"\n" 876 "int x;\n"; 877 std::string Expected = "#include \"xyz\"\n" 878 "int x;\n"; 879 tooling::Replacements Replaces = 880 toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")}); 881 EXPECT_EQ(Expected, apply(Code, Replaces)); 882 } 883 884 TEST_F(CleanUpReplacementsTest, DeleteAllCode) { 885 std::string Code = "#include \"xyz.h\"\n" 886 "#include <xyz.h>"; 887 std::string Expected = ""; 888 tooling::Replacements Replaces = 889 toReplacements({createDeletion("\"xyz.h\""), createDeletion("<xyz.h>")}); 890 EXPECT_EQ(Expected, apply(Code, Replaces)); 891 } 892 893 TEST_F(CleanUpReplacementsTest, DeleteOnlyIncludesWithSameQuote) { 894 std::string Code = "#include \"xyz.h\"\n" 895 "#include \"xyz\"\n" 896 "#include <xyz.h>\n"; 897 std::string Expected = "#include \"xyz.h\"\n" 898 "#include \"xyz\"\n"; 899 tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")}); 900 EXPECT_EQ(Expected, apply(Code, Replaces)); 901 } 902 903 TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) { 904 std::string Code = "#include \"xyz.h\"\n" 905 "#include \"xyz\"\n" 906 "#include <xyz.h>"; 907 std::string Expected = "#include \"xyz.h\"\n" 908 "#include \"xyz\"\n"; 909 tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")}); 910 EXPECT_EQ(Expected, apply(Code, Replaces)); 911 } 912 913 TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) { 914 std::string Code = "#include \"a.h\"\n" 915 "\n" 916 "#include <vector>\n"; 917 std::string Expected = "#include \"a.h\"\n" 918 "\n" 919 "#include <map>\n"; 920 tooling::Replacements Replaces = toReplacements( 921 {createDeletion("<vector>"), createInsertion("#include <map>")}); 922 EXPECT_EQ(Expected, apply(Code, Replaces)); 923 } 924 925 TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) { 926 std::string Code = "#include \"a.h\"\n" 927 "void f() {}\n" 928 "#include \"b.h\"\n"; 929 std::string Expected = "#include \"a.h\"\n" 930 "#include \"c.h\"\n" 931 "void f() {}\n" 932 "#include \"b.h\"\n"; 933 tooling::Replacements Replaces = toReplacements( 934 {createInsertion("#include \"c.h\"")}); 935 EXPECT_EQ(Expected, apply(Code, Replaces)); 936 } 937 938 TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) { 939 std::string Code = "#include \"a.h\"\n" 940 "const char[] = R\"(\n" 941 "#include \"b.h\"\n" 942 ")\";\n"; 943 std::string Expected = "#include \"a.h\"\n" 944 "#include \"c.h\"\n" 945 "const char[] = R\"(\n" 946 "#include \"b.h\"\n" 947 ")\";\n"; 948 tooling::Replacements Replaces = 949 toReplacements({createInsertion("#include \"c.h\"")}); 950 EXPECT_EQ(Expected, apply(Code, Replaces)); 951 } 952 953 TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) { 954 std::string Code = "#include \"a.h\"\n" 955 "#ifdef X\n" 956 "#include \"b.h\"\n" 957 "#endif\n"; 958 std::string Expected = "#include \"a.h\"\n" 959 "#include \"c.h\"\n" 960 "#ifdef X\n" 961 "#include \"b.h\"\n" 962 "#endif\n"; 963 tooling::Replacements Replaces = toReplacements( 964 {createInsertion("#include \"c.h\"")}); 965 EXPECT_EQ(Expected, apply(Code, Replaces)); 966 } 967 968 TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) { 969 std::string Code = "#include \"a.h\"\n" 970 "// comment\n\n" 971 "#include <a/b/c/d/e.h>\n"; 972 std::string Expected = "#include \"a.h\"\n" 973 "// comment\n\n" 974 "#include <a/b/c/d/e.h>\n" 975 "#include <x.h>\n"; 976 tooling::Replacements Replaces = 977 toReplacements({createInsertion("#include <x.h>")}); 978 EXPECT_EQ(Expected, apply(Code, Replaces)); 979 } 980 981 TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) { 982 std::string Code = "#include \"a.h\"\n" 983 "// Comment\n" 984 "\n" 985 "/* Comment */\n" 986 "// Comment\n" 987 "\n" 988 "#include \"b.h\"\n"; 989 std::string Expected = "#include \"a.h\"\n" 990 "// Comment\n" 991 "\n" 992 "/* Comment */\n" 993 "// Comment\n" 994 "\n" 995 "#include \"b.h\"\n" 996 "#include \"c.h\"\n"; 997 tooling::Replacements Replaces = 998 toReplacements({createInsertion("#include \"c.h\"")}); 999 EXPECT_EQ(Expected, apply(Code, Replaces)); 1000 } 1001 1002 TEST_F(CleanUpReplacementsTest, LongCommentsInTheBeginningOfFile) { 1003 std::string Code = "// Loooooooooooooooooooooooooong comment\n" 1004 "// Loooooooooooooooooooooooooong comment\n" 1005 "// Loooooooooooooooooooooooooong comment\n" 1006 "#include <string>\n" 1007 "#include <vector>\n" 1008 "\n" 1009 "#include \"a.h\"\n" 1010 "#include \"b.h\"\n"; 1011 std::string Expected = "// Loooooooooooooooooooooooooong comment\n" 1012 "// Loooooooooooooooooooooooooong comment\n" 1013 "// Loooooooooooooooooooooooooong comment\n" 1014 "#include <string>\n" 1015 "#include <vector>\n" 1016 "\n" 1017 "#include \"a.h\"\n" 1018 "#include \"b.h\"\n" 1019 "#include \"third.h\"\n"; 1020 tooling::Replacements Replaces = 1021 toReplacements({createInsertion("#include \"third.h\"")}); 1022 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 1023 EXPECT_EQ(Expected, apply(Code, Replaces)); 1024 } 1025 1026 TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) { 1027 std::string Code = "#include \"a.h\"\n" 1028 "void f() {}\n" 1029 "#include \"b.h\"\n"; 1030 std::string Expected = "#include \"a.h\"\n" 1031 "void f() {}\n"; 1032 tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")}); 1033 EXPECT_EQ(Expected, apply(Code, Replaces)); 1034 } 1035 1036 } // end namespace 1037 } // end namespace format 1038 } // end namespace clang 1039