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