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, FakeHeaderGuard) { 718 std::string Code = "// comment \n" 719 "#ifndef X\n" 720 "#define 1\n"; 721 std::string Expected = "// comment \n" 722 "#include <vector>\n" 723 "#ifndef X\n" 724 "#define 1\n"; 725 tooling::Replacements Replaces = 726 toReplacements({createInsertion("#include <vector>")}); 727 EXPECT_EQ(Expected, apply(Code, Replaces)); 728 } 729 730 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) { 731 std::string Code = "// comment \n" 732 "#ifndef X // comment\n" 733 "// comment\n" 734 "/* comment\n" 735 "*/\n" 736 "/* comment */ #define X\n" 737 "int x;\n" 738 "#define Y 1\n"; 739 std::string Expected = "// comment \n" 740 "#ifndef X // comment\n" 741 "// comment\n" 742 "/* comment\n" 743 "*/\n" 744 "/* comment */ #define X\n" 745 "#include <vector>\n" 746 "int x;\n" 747 "#define Y 1\n"; 748 tooling::Replacements Replaces = 749 toReplacements({createInsertion("#include <vector>")}); 750 EXPECT_EQ(Expected, apply(Code, Replaces)); 751 } 752 753 TEST_F(CleanUpReplacementsTest, EmptyCode) { 754 std::string Code = ""; 755 std::string Expected = "#include <vector>\n"; 756 tooling::Replacements Replaces = 757 toReplacements({createInsertion("#include <vector>")}); 758 EXPECT_EQ(Expected, apply(Code, Replaces)); 759 } 760 761 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) { 762 std::string Code = "#include <map>"; 763 std::string Expected = "#include <map>\n#include <vector>\n"; 764 tooling::Replacements Replaces = 765 toReplacements({createInsertion("#include <vector>")}); 766 EXPECT_EQ(Expected, apply(Code, Replaces)); 767 } 768 769 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) { 770 std::string Code = "#include <map>"; 771 std::string Expected = 772 "#include <map>\n#include <string>\n#include <vector>\n"; 773 tooling::Replacements Replaces = 774 toReplacements({createInsertion("#include <string>"), 775 createInsertion("#include <vector>")}); 776 EXPECT_EQ(Expected, apply(Code, Replaces)); 777 } 778 779 TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) { 780 std::string Code = "#include \"a.h\"\n" 781 "#include <vector>\n"; 782 std::string Expected = "#include \"a.h\"\n" 783 "#include <vector>\n"; 784 tooling::Replacements Replaces = 785 toReplacements({createInsertion("#include <vector>"), 786 createInsertion("#include \"a.h\"")}); 787 EXPECT_EQ(Expected, apply(Code, Replaces)); 788 } 789 790 TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) { 791 std::string Code = "#include \"a.h\"\n" 792 "#include <vector>\n"; 793 // FIXME: this might not be the best behavior. 794 std::string Expected = "#include \"a.h\"\n" 795 "#include \"vector\"\n" 796 "#include <vector>\n" 797 "#include <a.h>\n"; 798 tooling::Replacements Replaces = 799 toReplacements({createInsertion("#include \"vector\""), 800 createInsertion("#include <a.h>")}); 801 EXPECT_EQ(Expected, apply(Code, Replaces)); 802 } 803 804 TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) { 805 std::string Code = "#include \"abc.h\"\n" 806 "#include \"xyz.h\" // comment\n" 807 "#include \"xyz\"\n" 808 "int x;\n"; 809 std::string Expected = "#include \"xyz\"\n" 810 "int x;\n"; 811 tooling::Replacements Replaces = 812 toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")}); 813 EXPECT_EQ(Expected, apply(Code, Replaces)); 814 } 815 816 TEST_F(CleanUpReplacementsTest, DeleteAllCode) { 817 std::string Code = "#include \"xyz.h\"\n" 818 "#include <xyz.h>"; 819 std::string Expected = ""; 820 tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")}); 821 EXPECT_EQ(Expected, apply(Code, Replaces)); 822 } 823 824 TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) { 825 std::string Code = "#include \"xyz.h\"\n" 826 "#include \"xyz\"\n" 827 "#include <xyz.h>\n"; 828 std::string Expected = "#include \"xyz\"\n"; 829 tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")}); 830 EXPECT_EQ(Expected, apply(Code, Replaces)); 831 } 832 833 TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) { 834 std::string Code = "#include \"xyz.h\"\n" 835 "#include \"xyz\"\n" 836 "#include <xyz.h>"; 837 std::string Expected = "#include \"xyz.h\"\n" 838 "#include \"xyz\"\n"; 839 tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")}); 840 EXPECT_EQ(Expected, apply(Code, Replaces)); 841 } 842 843 TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) { 844 std::string Code = "#include \"a.h\"\n" 845 "\n" 846 "#include <vector>\n"; 847 std::string Expected = "#include \"a.h\"\n" 848 "\n" 849 "#include <map>\n"; 850 tooling::Replacements Replaces = toReplacements( 851 {createDeletion("<vector>"), createInsertion("#include <map>")}); 852 EXPECT_EQ(Expected, apply(Code, Replaces)); 853 } 854 855 TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) { 856 std::string Code = "#include \"a.h\"\n" 857 "void f() {}\n" 858 "#include \"b.h\"\n"; 859 std::string Expected = "#include \"a.h\"\n" 860 "#include \"c.h\"\n" 861 "void f() {}\n" 862 "#include \"b.h\"\n"; 863 tooling::Replacements Replaces = toReplacements( 864 {createInsertion("#include \"c.h\"")}); 865 EXPECT_EQ(Expected, apply(Code, Replaces)); 866 } 867 868 TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) { 869 std::string Code = "#include \"a.h\"\n" 870 "const char[] = R\"(\n" 871 "#include \"b.h\"\n" 872 ")\";\n"; 873 std::string Expected = "#include \"a.h\"\n" 874 "#include \"c.h\"\n" 875 "const char[] = R\"(\n" 876 "#include \"b.h\"\n" 877 ")\";\n"; 878 tooling::Replacements Replaces = 879 toReplacements({createInsertion("#include \"c.h\"")}); 880 EXPECT_EQ(Expected, apply(Code, Replaces)); 881 } 882 883 TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) { 884 std::string Code = "#include \"a.h\"\n" 885 "#ifdef X\n" 886 "#include \"b.h\"\n" 887 "#endif\n"; 888 std::string Expected = "#include \"a.h\"\n" 889 "#include \"c.h\"\n" 890 "#ifdef X\n" 891 "#include \"b.h\"\n" 892 "#endif\n"; 893 tooling::Replacements Replaces = toReplacements( 894 {createInsertion("#include \"c.h\"")}); 895 EXPECT_EQ(Expected, apply(Code, Replaces)); 896 } 897 898 TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) { 899 std::string Code = "#include \"a.h\"\n" 900 "// comment\n\n" 901 "#include <a/b/c/d/e.h>\n"; 902 std::string Expected = "#include \"a.h\"\n" 903 "// comment\n\n" 904 "#include <a/b/c/d/e.h>\n" 905 "#include <x.h>\n"; 906 tooling::Replacements Replaces = 907 toReplacements({createInsertion("#include <x.h>")}); 908 EXPECT_EQ(Expected, apply(Code, Replaces)); 909 } 910 911 TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) { 912 std::string Code = "#include \"a.h\"\n" 913 "// Comment\n" 914 "\n" 915 "/* Comment */\n" 916 "// Comment\n" 917 "\n" 918 "#include \"b.h\"\n"; 919 std::string Expected = "#include \"a.h\"\n" 920 "// Comment\n" 921 "\n" 922 "/* Comment */\n" 923 "// Comment\n" 924 "\n" 925 "#include \"b.h\"\n" 926 "#include \"c.h\"\n"; 927 tooling::Replacements Replaces = 928 toReplacements({createInsertion("#include \"c.h\"")}); 929 EXPECT_EQ(Expected, apply(Code, Replaces)); 930 } 931 932 TEST_F(CleanUpReplacementsTest, LongCommentsInTheBeginningOfFile) { 933 std::string Code = "// Loooooooooooooooooooooooooong comment\n" 934 "// Loooooooooooooooooooooooooong comment\n" 935 "// Loooooooooooooooooooooooooong comment\n" 936 "#include <string>\n" 937 "#include <vector>\n" 938 "\n" 939 "#include \"a.h\"\n" 940 "#include \"b.h\"\n"; 941 std::string Expected = "// Loooooooooooooooooooooooooong comment\n" 942 "// Loooooooooooooooooooooooooong comment\n" 943 "// Loooooooooooooooooooooooooong comment\n" 944 "#include <string>\n" 945 "#include <vector>\n" 946 "\n" 947 "#include \"a.h\"\n" 948 "#include \"b.h\"\n" 949 "#include \"third.h\"\n"; 950 tooling::Replacements Replaces = 951 toReplacements({createInsertion("#include \"third.h\"")}); 952 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 953 EXPECT_EQ(Expected, apply(Code, Replaces)); 954 } 955 956 TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) { 957 std::string Code = "#include \"a.h\"\n" 958 "void f() {}\n" 959 "#include \"b.h\"\n"; 960 std::string Expected = "#include \"a.h\"\n" 961 "void f() {}\n"; 962 tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")}); 963 EXPECT_EQ(Expected, apply(Code, Replaces)); 964 } 965 966 } // end namespace 967 } // end namespace format 968 } // end namespace clang 969