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 auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style); 307 EXPECT_TRUE(static_cast<bool>(CleanReplaces)) 308 << llvm::toString(CleanReplaces.takeError()) << "\n"; 309 auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style); 310 EXPECT_TRUE(static_cast<bool>(FormattedReplaces)) 311 << llvm::toString(FormattedReplaces.takeError()) << "\n"; 312 auto Result = applyAllReplacements(Code, *FormattedReplaces); 313 EXPECT_TRUE(static_cast<bool>(Result)); 314 return *Result; 315 } 316 317 int getOffset(StringRef Code, int Line, int Column) { 318 RewriterTestContext Context; 319 FileID ID = Context.createInMemoryFile(FileName, Code); 320 auto DecomposedLocation = 321 Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column)); 322 return DecomposedLocation.second; 323 } 324 325 const std::string FileName = "fix.cpp"; 326 FormatStyle Style = getLLVMStyle(); 327 }; 328 329 TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) { 330 std::string Code = "namespace A {\n" 331 "namespace B {\n" 332 " int x;\n" 333 "} // namespace B\n" 334 "} // namespace A\n" 335 "\n" 336 "namespace C {\n" 337 "namespace D { int i; }\n" 338 "inline namespace E { namespace { int y; } }\n" 339 "int x= 0;" 340 "}"; 341 std::string Expected = "\n\nnamespace C {\n" 342 "namespace D { int i; }\n\n" 343 "int x= 0;" 344 "}"; 345 tooling::Replacements Replaces = 346 toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""), 347 createReplacement(getOffset(Code, 9, 34), 6, "")}); 348 349 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 350 } 351 352 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) { 353 std::string Code = "int main() {}"; 354 std::string Expected = "#include \"a.h\"\n" 355 "int main() {}"; 356 tooling::Replacements Replaces = 357 toReplacements({createInsertion("#include \"a.h\"")}); 358 EXPECT_EQ(Expected, apply(Code, Replaces)); 359 } 360 361 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) { 362 std::string Code = "#ifndef A_H\n" 363 "#define A_H\n" 364 "class A {};\n" 365 "#define MMM 123\n" 366 "#endif"; 367 std::string Expected = "#ifndef A_H\n" 368 "#define A_H\n" 369 "#include \"b.h\"\n" 370 "class A {};\n" 371 "#define MMM 123\n" 372 "#endif"; 373 374 tooling::Replacements Replaces = 375 toReplacements({createInsertion("#include \"b.h\"")}); 376 EXPECT_EQ(Expected, apply(Code, Replaces)); 377 } 378 379 TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) { 380 std::string Code = "#ifndef A_H\n" 381 "#define A_H\n" 382 "\n" 383 "\n" 384 "\n" 385 "#include <vector>\n" 386 "class A {};\n" 387 "#define MMM 123\n" 388 "#endif"; 389 std::string Expected = "#ifndef A_H\n" 390 "#define A_H\n" 391 "\n" 392 "\n" 393 "\n" 394 "#include \"a.h\"\n" 395 "#include <vector>\n" 396 "class A {};\n" 397 "#define MMM 123\n" 398 "#endif"; 399 400 tooling::Replacements Replaces = 401 toReplacements({createInsertion("#include \"a.h\"")}); 402 EXPECT_EQ(Expected, apply(Code, Replaces)); 403 } 404 405 TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) { 406 std::string Code = "#include \"fix.h\"\n" 407 "\n" 408 "int main() {}"; 409 std::string Expected = "#include \"fix.h\"\n" 410 "#include <a>\n" 411 "\n" 412 "int main() {}"; 413 tooling::Replacements Replaces = 414 toReplacements({createInsertion("#include <a>")}); 415 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 416 EXPECT_EQ(Expected, apply(Code, Replaces)); 417 } 418 419 TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) { 420 std::string Code = "#include <memory>\n" 421 "\n" 422 "int main() {}"; 423 std::string Expected = "#include \"z.h\"\n" 424 "#include <memory>\n" 425 "\n" 426 "int main() {}"; 427 tooling::Replacements Replaces = 428 toReplacements({createInsertion("#include \"z.h\"")}); 429 EXPECT_EQ(Expected, apply(Code, Replaces)); 430 } 431 432 TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) { 433 std::string Code = "#include <memory>\n" 434 "\n" 435 "int main() {}"; 436 std::string Expected = "#include <memory>\n" 437 "#include \"z.h\"\n" 438 "\n" 439 "int main() {}"; 440 tooling::Replacements Replaces = 441 toReplacements({createInsertion("#include \"z.h\"")}); 442 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 443 EXPECT_EQ(Expected, apply(Code, Replaces)); 444 } 445 446 TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) { 447 std::string Code = "#include \"x/fix.h\"\n" 448 "#include \"a.h\"\n" 449 "#include \"b.h\"\n" 450 "#include \"clang/Format/Format.h\"\n" 451 "#include <memory>\n"; 452 std::string Expected = "#include \"x/fix.h\"\n" 453 "#include \"a.h\"\n" 454 "#include \"b.h\"\n" 455 "#include \"d.h\"\n" 456 "#include \"clang/Format/Format.h\"\n" 457 "#include \"llvm/x/y.h\"\n" 458 "#include <memory>\n"; 459 tooling::Replacements Replaces = 460 toReplacements({createInsertion("#include \"d.h\""), 461 createInsertion("#include \"llvm/x/y.h\"")}); 462 EXPECT_EQ(Expected, apply(Code, Replaces)); 463 } 464 465 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) { 466 std::string Code = "#include \"x/fix.h\"\n" 467 "#include \"a.h\"\n" 468 "#include \"b.h\"\n" 469 "#include \"clang/Format/Format.h\"\n" 470 "#include <memory>\n"; 471 std::string Expected = "#include \"x/fix.h\"\n" 472 "#include \"a.h\"\n" 473 "#include \"b.h\"\n" 474 "#include \"new/new.h\"\n" 475 "#include \"clang/Format/Format.h\"\n" 476 "#include <memory>\n" 477 "#include <list>\n"; 478 tooling::Replacements Replaces = 479 toReplacements({createInsertion("#include <list>"), 480 createInsertion("#include \"new/new.h\"")}); 481 EXPECT_EQ(Expected, apply(Code, Replaces)); 482 } 483 484 TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) { 485 std::string Code = "#include \"x/fix.h\"\n" 486 "\n" 487 "#include \"y/a.h\"\n" 488 "#include \"z/b.h\"\n"; 489 // FIXME: inserting after the empty line following the main header might be 490 // prefered. 491 std::string Expected = "#include \"x/fix.h\"\n" 492 "#include <vector>\n" 493 "\n" 494 "#include \"y/a.h\"\n" 495 "#include \"z/b.h\"\n"; 496 tooling::Replacements Replaces = 497 toReplacements({createInsertion("#include <vector>")}); 498 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 499 EXPECT_EQ(Expected, apply(Code, Replaces)); 500 } 501 502 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) { 503 std::string Code = "#include \"x/fix.h\"\n" 504 "\n" 505 "#include <vector>\n" 506 "\n" 507 "#include \"y/a.h\"\n" 508 "#include \"z/b.h\"\n"; 509 std::string Expected = "#include \"x/fix.h\"\n" 510 "\n" 511 "#include <vector>\n" 512 "#include <list>\n" 513 "\n" 514 "#include \"y/a.h\"\n" 515 "#include \"z/b.h\"\n" 516 "#include \"x/x.h\"\n"; 517 tooling::Replacements Replaces = 518 toReplacements({createInsertion("#include <list>"), 519 createInsertion("#include \"x/x.h\"")}); 520 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 521 EXPECT_EQ(Expected, apply(Code, Replaces)); 522 } 523 524 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) { 525 std::string Code = "\nint x;"; 526 std::string Expected = "\n#include \"fix.h\"\n" 527 "#include \"a.h\"\n" 528 "#include \"b.h\"\n" 529 "#include \"c.h\"\n" 530 "#include <list>\n" 531 "#include <vector>\n" 532 "int x;"; 533 tooling::Replacements Replaces = toReplacements( 534 {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""), 535 createInsertion("#include \"b.h\""), 536 createInsertion("#include <vector>"), createInsertion("#include <list>"), 537 createInsertion("#include \"fix.h\"")}); 538 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 539 } 540 541 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) { 542 std::string Code = "\nint x;"; 543 std::string Expected = "\n#include \"fix.h\"\n" 544 "#include <list>\n" 545 "#include <vector>\n" 546 "#include \"a.h\"\n" 547 "#include \"b.h\"\n" 548 "#include \"c.h\"\n" 549 "int x;"; 550 tooling::Replacements Replaces = toReplacements( 551 {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""), 552 createInsertion("#include \"b.h\""), 553 createInsertion("#include <vector>"), createInsertion("#include <list>"), 554 createInsertion("#include \"fix.h\"")}); 555 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 556 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 557 } 558 559 TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) { 560 std::string Code = "\n" 561 "int x;\n" 562 "int a;\n" 563 "int a;\n" 564 "int a;"; 565 566 std::string Expected = "\n#include \"x.h\"\n" 567 "#include \"y.h\"\n" 568 "#include \"clang/x/x.h\"\n" 569 "#include <list>\n" 570 "#include <vector>\n" 571 "int x;\n" 572 "int a;\n" 573 "int b;\n" 574 "int a;"; 575 tooling::Replacements Replaces = toReplacements( 576 {createReplacement(getOffset(Code, 4, 8), 1, "b"), 577 createInsertion("#include <vector>"), createInsertion("#include <list>"), 578 createInsertion("#include \"clang/x/x.h\""), 579 createInsertion("#include \"y.h\""), 580 createInsertion("#include \"x.h\"")}); 581 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 582 } 583 584 TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) { 585 std::string Code = "void f() {}\n" 586 "#define A \\\n" 587 " int i;"; 588 std::string Expected = "#include <vector>\n" 589 "void f() {}\n" 590 "#define A \\\n" 591 " int i;"; 592 tooling::Replacements Replaces = 593 toReplacements({createInsertion("#include <vector>")}); 594 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 595 } 596 597 TEST_F(CleanUpReplacementsTest, SkippedTopComment) { 598 std::string Code = "// comment\n" 599 "\n" 600 " // comment\n"; 601 std::string Expected = "// comment\n" 602 "\n" 603 " // comment\n" 604 "#include <vector>\n"; 605 tooling::Replacements Replaces = 606 toReplacements({createInsertion("#include <vector>")}); 607 EXPECT_EQ(Expected, apply(Code, Replaces)); 608 } 609 610 TEST_F(CleanUpReplacementsTest, SkippedMixedComments) { 611 std::string Code = "// comment\n" 612 "// comment \\\n" 613 " comment continued\n" 614 "/*\n" 615 "* comment\n" 616 "*/\n"; 617 std::string Expected = "// comment\n" 618 "// comment \\\n" 619 " comment continued\n" 620 "/*\n" 621 "* comment\n" 622 "*/\n" 623 "#include <vector>\n"; 624 tooling::Replacements Replaces = 625 toReplacements({createInsertion("#include <vector>")}); 626 EXPECT_EQ(Expected, apply(Code, Replaces)); 627 } 628 629 TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) { 630 std::string Code = "/*\n" 631 "* comment\n" 632 "*/ /* comment\n" 633 "*/\n" 634 "\n\n" 635 "/* c1 */ /*c2 */\n"; 636 std::string Expected = "/*\n" 637 "* comment\n" 638 "*/ /* comment\n" 639 "*/\n" 640 "\n\n" 641 "/* c1 */ /*c2 */\n" 642 "#include <vector>\n"; 643 tooling::Replacements Replaces = 644 toReplacements({createInsertion("#include <vector>")}); 645 EXPECT_EQ(Expected, apply(Code, Replaces)); 646 } 647 648 TEST_F(CleanUpReplacementsTest, CodeAfterComments) { 649 std::string Code = "/*\n" 650 "* comment\n" 651 "*/ /* comment\n" 652 "*/\n" 653 "\n\n" 654 "/* c1 */ /*c2 */\n" 655 "\n" 656 "int x;\n"; 657 std::string Expected = "/*\n" 658 "* comment\n" 659 "*/ /* comment\n" 660 "*/\n" 661 "\n\n" 662 "/* c1 */ /*c2 */\n" 663 "\n" 664 "#include <vector>\n" 665 "int x;\n"; 666 tooling::Replacements Replaces = 667 toReplacements({createInsertion("#include <vector>")}); 668 EXPECT_EQ(Expected, apply(Code, Replaces)); 669 } 670 671 TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) { 672 std::string Code = "// comment \n" 673 "#ifdef X\n" 674 "#define X\n"; 675 std::string Expected = "// comment \n" 676 "#include <vector>\n" 677 "#ifdef X\n" 678 "#define X\n"; 679 tooling::Replacements Replaces = 680 toReplacements({createInsertion("#include <vector>")}); 681 EXPECT_EQ(Expected, apply(Code, Replaces)); 682 } 683 684 TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) { 685 std::string Code = "// comment \n" 686 "#ifndef X\n" 687 "#define X\n" 688 "int x;\n" 689 "#define Y 1\n"; 690 std::string Expected = "// comment \n" 691 "#ifndef X\n" 692 "#define X\n" 693 "#include <vector>\n" 694 "int x;\n" 695 "#define Y 1\n"; 696 tooling::Replacements Replaces = 697 toReplacements({createInsertion("#include <vector>")}); 698 EXPECT_EQ(Expected, apply(Code, Replaces)); 699 } 700 701 TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) { 702 std::string Code = "// comment \n" 703 "#ifndef X\n" 704 "int x;\n" 705 "#define Y 1\n"; 706 std::string Expected = "// comment \n" 707 "#include <vector>\n" 708 "#ifndef X\n" 709 "int x;\n" 710 "#define Y 1\n"; 711 tooling::Replacements Replaces = 712 toReplacements({createInsertion("#include <vector>")}); 713 EXPECT_EQ(Expected, apply(Code, Replaces)); 714 } 715 716 TEST_F(CleanUpReplacementsTest, FakeHeaderGuard) { 717 std::string Code = "// comment \n" 718 "#ifndef X\n" 719 "#define 1\n"; 720 std::string Expected = "// comment \n" 721 "#include <vector>\n" 722 "#ifndef X\n" 723 "#define 1\n"; 724 tooling::Replacements Replaces = 725 toReplacements({createInsertion("#include <vector>")}); 726 EXPECT_EQ(Expected, apply(Code, Replaces)); 727 } 728 729 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) { 730 std::string Code = "// comment \n" 731 "#ifndef X // comment\n" 732 "// comment\n" 733 "/* comment\n" 734 "*/\n" 735 "/* comment */ #define X\n" 736 "int x;\n" 737 "#define Y 1\n"; 738 std::string Expected = "// comment \n" 739 "#ifndef X // comment\n" 740 "// comment\n" 741 "/* comment\n" 742 "*/\n" 743 "/* comment */ #define X\n" 744 "#include <vector>\n" 745 "int x;\n" 746 "#define Y 1\n"; 747 tooling::Replacements Replaces = 748 toReplacements({createInsertion("#include <vector>")}); 749 EXPECT_EQ(Expected, apply(Code, Replaces)); 750 } 751 752 TEST_F(CleanUpReplacementsTest, EmptyCode) { 753 std::string Code = ""; 754 std::string Expected = "#include <vector>\n"; 755 tooling::Replacements Replaces = 756 toReplacements({createInsertion("#include <vector>")}); 757 EXPECT_EQ(Expected, apply(Code, Replaces)); 758 } 759 760 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) { 761 std::string Code = "#include <map>"; 762 std::string Expected = "#include <map>\n#include <vector>\n"; 763 tooling::Replacements Replaces = 764 toReplacements({createInsertion("#include <vector>")}); 765 EXPECT_EQ(Expected, apply(Code, Replaces)); 766 } 767 768 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) { 769 std::string Code = "#include <map>"; 770 std::string Expected = 771 "#include <map>\n#include <string>\n#include <vector>\n"; 772 tooling::Replacements Replaces = 773 toReplacements({createInsertion("#include <string>"), 774 createInsertion("#include <vector>")}); 775 EXPECT_EQ(Expected, apply(Code, Replaces)); 776 } 777 778 TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) { 779 std::string Code = "#include \"a.h\"\n" 780 "#include <vector>\n"; 781 std::string Expected = "#include \"a.h\"\n" 782 "#include <vector>\n"; 783 tooling::Replacements Replaces = 784 toReplacements({createInsertion("#include <vector>"), 785 createInsertion("#include \"a.h\"")}); 786 EXPECT_EQ(Expected, apply(Code, Replaces)); 787 } 788 789 TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) { 790 std::string Code = "#include \"a.h\"\n" 791 "#include <vector>\n"; 792 // FIXME: this might not be the best behavior. 793 std::string Expected = "#include \"a.h\"\n" 794 "#include \"vector\"\n" 795 "#include <vector>\n" 796 "#include <a.h>\n"; 797 tooling::Replacements Replaces = 798 toReplacements({createInsertion("#include \"vector\""), 799 createInsertion("#include <a.h>")}); 800 EXPECT_EQ(Expected, apply(Code, Replaces)); 801 } 802 803 TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) { 804 std::string Code = "#include \"abc.h\"\n" 805 "#include \"xyz.h\" // comment\n" 806 "#include \"xyz\"\n" 807 "int x;\n"; 808 std::string Expected = "#include \"xyz\"\n" 809 "int x;\n"; 810 tooling::Replacements Replaces = 811 toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")}); 812 EXPECT_EQ(Expected, apply(Code, Replaces)); 813 } 814 815 TEST_F(CleanUpReplacementsTest, DeleteAllCode) { 816 std::string Code = "#include \"xyz.h\"\n" 817 "#include <xyz.h>"; 818 std::string Expected = ""; 819 tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")}); 820 EXPECT_EQ(Expected, apply(Code, Replaces)); 821 } 822 823 TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) { 824 std::string Code = "#include \"xyz.h\"\n" 825 "#include \"xyz\"\n" 826 "#include <xyz.h>\n"; 827 std::string Expected = "#include \"xyz\"\n"; 828 tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")}); 829 EXPECT_EQ(Expected, apply(Code, Replaces)); 830 } 831 832 TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) { 833 std::string Code = "#include \"xyz.h\"\n" 834 "#include \"xyz\"\n" 835 "#include <xyz.h>"; 836 std::string Expected = "#include \"xyz.h\"\n" 837 "#include \"xyz\"\n"; 838 tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")}); 839 EXPECT_EQ(Expected, apply(Code, Replaces)); 840 } 841 842 TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) { 843 std::string Code = "#include \"a.h\"\n" 844 "\n" 845 "#include <vector>\n"; 846 std::string Expected = "#include \"a.h\"\n" 847 "\n" 848 "#include <map>\n"; 849 tooling::Replacements Replaces = toReplacements( 850 {createDeletion("<vector>"), createInsertion("#include <map>")}); 851 EXPECT_EQ(Expected, apply(Code, Replaces)); 852 } 853 854 TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) { 855 std::string Code = "#include \"a.h\"\n" 856 "void f() {}\n" 857 "#include \"b.h\"\n"; 858 std::string Expected = "#include \"a.h\"\n" 859 "#include \"c.h\"\n" 860 "void f() {}\n" 861 "#include \"b.h\"\n"; 862 tooling::Replacements Replaces = toReplacements( 863 {createInsertion("#include \"c.h\"")}); 864 EXPECT_EQ(Expected, apply(Code, Replaces)); 865 } 866 867 TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) { 868 std::string Code = "#include \"a.h\"\n" 869 "const char[] = R\"(\n" 870 "#include \"b.h\"\n" 871 ")\";\n"; 872 std::string Expected = "#include \"a.h\"\n" 873 "#include \"c.h\"\n" 874 "const char[] = R\"(\n" 875 "#include \"b.h\"\n" 876 ")\";\n"; 877 tooling::Replacements Replaces = 878 toReplacements({createInsertion("#include \"c.h\"")}); 879 EXPECT_EQ(Expected, apply(Code, Replaces)); 880 } 881 882 TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) { 883 std::string Code = "#include \"a.h\"\n" 884 "#ifdef X\n" 885 "#include \"b.h\"\n" 886 "#endif\n"; 887 std::string Expected = "#include \"a.h\"\n" 888 "#include \"c.h\"\n" 889 "#ifdef X\n" 890 "#include \"b.h\"\n" 891 "#endif\n"; 892 tooling::Replacements Replaces = toReplacements( 893 {createInsertion("#include \"c.h\"")}); 894 EXPECT_EQ(Expected, apply(Code, Replaces)); 895 } 896 897 TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) { 898 std::string Code = "#include \"a.h\"\n" 899 "// comment\n\n" 900 "#include <a/b/c/d/e.h>\n"; 901 std::string Expected = "#include \"a.h\"\n" 902 "// comment\n\n" 903 "#include <a/b/c/d/e.h>\n" 904 "#include <x.h>\n"; 905 tooling::Replacements Replaces = 906 toReplacements({createInsertion("#include <x.h>")}); 907 EXPECT_EQ(Expected, apply(Code, Replaces)); 908 } 909 910 TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) { 911 std::string Code = "#include \"a.h\"\n" 912 "// Comment\n" 913 "\n" 914 "/* Comment */\n" 915 "// Comment\n" 916 "\n" 917 "#include \"b.h\"\n"; 918 std::string Expected = "#include \"a.h\"\n" 919 "// Comment\n" 920 "\n" 921 "/* Comment */\n" 922 "// Comment\n" 923 "\n" 924 "#include \"b.h\"\n" 925 "#include \"c.h\"\n"; 926 tooling::Replacements Replaces = 927 toReplacements({createInsertion("#include \"c.h\"")}); 928 EXPECT_EQ(Expected, apply(Code, Replaces)); 929 } 930 931 TEST_F(CleanUpReplacementsTest, LongCommentsInTheBeginningOfFile) { 932 std::string Code = "// Loooooooooooooooooooooooooong comment\n" 933 "// Loooooooooooooooooooooooooong comment\n" 934 "// Loooooooooooooooooooooooooong comment\n" 935 "#include <string>\n" 936 "#include <vector>\n" 937 "\n" 938 "#include \"a.h\"\n" 939 "#include \"b.h\"\n"; 940 std::string Expected = "// Loooooooooooooooooooooooooong comment\n" 941 "// Loooooooooooooooooooooooooong comment\n" 942 "// Loooooooooooooooooooooooooong comment\n" 943 "#include <string>\n" 944 "#include <vector>\n" 945 "\n" 946 "#include \"a.h\"\n" 947 "#include \"b.h\"\n" 948 "#include \"third.h\"\n"; 949 tooling::Replacements Replaces = 950 toReplacements({createInsertion("#include \"third.h\"")}); 951 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 952 EXPECT_EQ(Expected, apply(Code, Replaces)); 953 } 954 955 TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) { 956 std::string Code = "#include \"a.h\"\n" 957 "void f() {}\n" 958 "#include \"b.h\"\n"; 959 std::string Expected = "#include \"a.h\"\n" 960 "void f() {}\n"; 961 tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")}); 962 EXPECT_EQ(Expected, apply(Code, Replaces)); 963 } 964 965 } // end namespace 966 } // end namespace format 967 } // end namespace clang 968