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/RewriterTestContext.h" 13 #include "clang/Tooling/Core/Replacement.h" 14 15 #include "gtest/gtest.h" 16 17 namespace clang { 18 namespace format { 19 namespace { 20 21 class CleanupTest : public ::testing::Test { 22 protected: 23 std::string cleanup(llvm::StringRef Code, 24 const std::vector<tooling::Range> &Ranges, 25 const FormatStyle &Style = getLLVMStyle()) { 26 tooling::Replacements Replaces = format::cleanup(Style, Code, Ranges); 27 28 std::string Result = applyAllReplacements(Code, Replaces); 29 EXPECT_NE("", Result); 30 return Result; 31 } 32 }; 33 34 TEST_F(CleanupTest, DeleteEmptyNamespaces) { 35 std::string Code = "namespace A {\n" 36 "namespace B {\n" 37 "} // namespace B\n" 38 "} // namespace A\n\n" 39 "namespace C {\n" 40 "namespace D { int i; }\n" 41 "inline namespace E { namespace { } }\n" 42 "}"; 43 std::string Expected = "\n\n\n\n\nnamespace C {\n" 44 "namespace D { int i; }\n \n" 45 "}"; 46 std::vector<tooling::Range> Ranges; 47 Ranges.push_back(tooling::Range(28, 0)); 48 Ranges.push_back(tooling::Range(91, 6)); 49 Ranges.push_back(tooling::Range(132, 0)); 50 std::string Result = cleanup(Code, Ranges); 51 EXPECT_EQ(Expected, Result); 52 } 53 54 TEST_F(CleanupTest, NamespaceWithSyntaxError) { 55 std::string Code = "namespace A {\n" 56 "namespace B {\n" // missing r_brace 57 "} // namespace A\n\n" 58 "namespace C {\n" 59 "namespace D int i; }\n" 60 "inline namespace E { namespace { } }\n" 61 "}"; 62 std::string Expected = "namespace A {\n" 63 "\n\n\nnamespace C {\n" 64 "namespace D int i; }\n \n" 65 "}"; 66 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 67 std::string Result = cleanup(Code, Ranges); 68 EXPECT_EQ(Expected, Result); 69 } 70 71 TEST_F(CleanupTest, EmptyNamespaceNotAffected) { 72 std::string Code = "namespace A {\n\n" 73 "namespace {\n\n}}"; 74 // Even though the namespaces are empty, but the inner most empty namespace 75 // block is not affected by the changed ranges. 76 std::string Expected = "namespace A {\n\n" 77 "namespace {\n\n}}"; 78 // Set the changed range to be the second "\n". 79 std::vector<tooling::Range> Ranges(1, tooling::Range(14, 0)); 80 std::string Result = cleanup(Code, Ranges); 81 EXPECT_EQ(Expected, Result); 82 } 83 84 TEST_F(CleanupTest, EmptyNamespaceWithCommentsNoBreakBeforeBrace) { 85 std::string Code = "namespace A {\n" 86 "namespace B {\n" 87 "// Yo\n" 88 "} // namespace B\n" 89 "} // namespace A\n" 90 "namespace C { // Yo\n" 91 "}"; 92 std::string Expected = "\n\n\n\n\n\n"; 93 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 94 std::string Result = cleanup(Code, Ranges); 95 EXPECT_EQ(Expected, Result); 96 } 97 98 TEST_F(CleanupTest, EmptyNamespaceWithCommentsBreakBeforeBrace) { 99 std::string Code = "namespace A\n" 100 "/* Yo */ {\n" 101 "namespace B\n" 102 "{\n" 103 "// Yo\n" 104 "} // namespace B\n" 105 "} // namespace A\n" 106 "namespace C\n" 107 "{ // Yo\n" 108 "}\n"; 109 std::string Expected = "\n\n\n\n\n\n\n\n\n\n"; 110 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 111 FormatStyle Style = getLLVMStyle(); 112 Style.BraceWrapping.AfterNamespace = true; 113 std::string Result = cleanup(Code, Ranges, Style); 114 EXPECT_EQ(Expected, Result); 115 } 116 117 TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) { 118 std::string Code = "class A {\nA() : , {} };"; 119 std::string Expected = "class A {\nA() {} };"; 120 std::vector<tooling::Range> Ranges; 121 Ranges.push_back(tooling::Range(17, 0)); 122 Ranges.push_back(tooling::Range(19, 0)); 123 std::string Result = cleanup(Code, Ranges); 124 EXPECT_EQ(Expected, Result); 125 126 Code = "class A {\nA() : x(1), {} };"; 127 Expected = "class A {\nA() : x(1) {} };"; 128 Ranges.clear(); 129 Ranges.push_back(tooling::Range(23, 0)); 130 Result = cleanup(Code, Ranges); 131 EXPECT_EQ(Expected, Result); 132 133 Code = "class A {\nA() :,,,,{} };"; 134 Expected = "class A {\nA() {} };"; 135 Ranges.clear(); 136 Ranges.push_back(tooling::Range(15, 0)); 137 Result = cleanup(Code, Ranges); 138 EXPECT_EQ(Expected, Result); 139 } 140 141 TEST_F(CleanupTest, ListSimpleRedundantComma) { 142 std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }"; 143 std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }"; 144 std::vector<tooling::Range> Ranges; 145 Ranges.push_back(tooling::Range(40, 0)); 146 std::string Result = cleanup(Code, Ranges); 147 EXPECT_EQ(Expected, Result); 148 149 Code = "int main() { f(1,,2,3,,4);}"; 150 Expected = "int main() { f(1,2,3,4);}"; 151 Ranges.clear(); 152 Ranges.push_back(tooling::Range(17, 0)); 153 Ranges.push_back(tooling::Range(22, 0)); 154 Result = cleanup(Code, Ranges); 155 EXPECT_EQ(Expected, Result); 156 } 157 158 TEST_F(CleanupTest, CtorInitializationBracesInParens) { 159 std::string Code = "class A {\nA() : x({1}),, {} };"; 160 std::string Expected = "class A {\nA() : x({1}) {} };"; 161 std::vector<tooling::Range> Ranges; 162 Ranges.push_back(tooling::Range(24, 0)); 163 Ranges.push_back(tooling::Range(26, 0)); 164 std::string Result = cleanup(Code, Ranges); 165 EXPECT_EQ(Expected, Result); 166 } 167 168 TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) { 169 std::string Code = 170 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };"; 171 std::string Expected = 172 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };"; 173 // Set the affected range to be "int x = 0", which does not intercept the 174 // constructor initialization list. 175 std::vector<tooling::Range> Ranges(1, tooling::Range(42, 9)); 176 std::string Result = cleanup(Code, Ranges); 177 EXPECT_EQ(Expected, Result); 178 179 Code = "class A {\nA() : x(1), {} };"; 180 Expected = "class A {\nA() : x(1), {} };"; 181 // No range. Fixer should do nothing. 182 Ranges.clear(); 183 Result = cleanup(Code, Ranges); 184 EXPECT_EQ(Expected, Result); 185 } 186 187 // FIXME: delete comments too. 188 TEST_F(CleanupTest, CtorInitializationCommentAroundCommas) { 189 // Remove redundant commas around comment. 190 std::string Code = "class A {\nA() : x({1}), /* comment */, {} };"; 191 std::string Expected = "class A {\nA() : x({1}) /* comment */ {} };"; 192 std::vector<tooling::Range> Ranges; 193 Ranges.push_back(tooling::Range(25, 0)); 194 Ranges.push_back(tooling::Range(40, 0)); 195 std::string Result = cleanup(Code, Ranges); 196 EXPECT_EQ(Expected, Result); 197 198 // Remove trailing comma and ignore comment. 199 Code = "class A {\nA() : x({1}), // comment\n{} };"; 200 Expected = "class A {\nA() : x({1}) // comment\n{} };"; 201 Ranges = std::vector<tooling::Range>(1, tooling::Range(25, 0)); 202 Result = cleanup(Code, Ranges); 203 EXPECT_EQ(Expected, Result); 204 205 // Remove trailing comma and ignore comment. 206 Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };"; 207 Expected = "class A {\nA() : x({1}), // comment\n y(1){} };"; 208 Ranges = std::vector<tooling::Range>(1, tooling::Range(38, 0)); 209 Result = cleanup(Code, Ranges); 210 EXPECT_EQ(Expected, Result); 211 212 // Remove trailing comma and ignore comment. 213 Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };"; 214 Expected = "class A {\nA() : x({1}), \n/* comment */ y(1){} };"; 215 Ranges = std::vector<tooling::Range>(1, tooling::Range(40, 0)); 216 Result = cleanup(Code, Ranges); 217 EXPECT_EQ(Expected, Result); 218 219 // Remove trailing comma and ignore comment. 220 Code = "class A {\nA() : , // comment\n y(1),{} };"; 221 Expected = "class A {\nA() : // comment\n y(1){} };"; 222 Ranges = std::vector<tooling::Range>(1, tooling::Range(17, 0)); 223 Result = cleanup(Code, Ranges); 224 EXPECT_EQ(Expected, Result); 225 } 226 227 TEST_F(CleanupTest, CtorInitializerInNamespace) { 228 std::string Code = "namespace A {\n" 229 "namespace B {\n" // missing r_brace 230 "} // namespace A\n\n" 231 "namespace C {\n" 232 "class A { A() : x(0),, {} };\n" 233 "inline namespace E { namespace { } }\n" 234 "}"; 235 std::string Expected = "namespace A {\n" 236 "\n\n\nnamespace C {\n" 237 "class A { A() : x(0) {} };\n \n" 238 "}"; 239 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 240 std::string Result = cleanup(Code, Ranges); 241 EXPECT_EQ(Expected, Result); 242 } 243 244 class CleanUpReplacementsTest : public ::testing::Test { 245 protected: 246 tooling::Replacement createReplacement(unsigned Offset, unsigned Length, 247 StringRef Text) { 248 return tooling::Replacement(FileName, Offset, Length, Text); 249 } 250 251 tooling::Replacement createInsertion(StringRef HeaderName) { 252 return createReplacement(UINT_MAX, 0, HeaderName); 253 } 254 255 inline std::string apply(StringRef Code, 256 const tooling::Replacements Replaces) { 257 return applyAllReplacements( 258 Code, cleanupAroundReplacements(Code, Replaces, Style)); 259 } 260 261 inline std::string formatAndApply(StringRef Code, 262 const tooling::Replacements Replaces) { 263 return applyAllReplacements( 264 Code, 265 formatReplacements( 266 Code, cleanupAroundReplacements(Code, Replaces, Style), Style)); 267 } 268 269 int getOffset(StringRef Code, int Line, int Column) { 270 RewriterTestContext Context; 271 FileID ID = Context.createInMemoryFile(FileName, Code); 272 auto DecomposedLocation = 273 Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column)); 274 return DecomposedLocation.second; 275 } 276 277 const std::string FileName = "fix.cpp"; 278 FormatStyle Style = getLLVMStyle(); 279 }; 280 281 TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) { 282 std::string Code = "namespace A {\n" 283 "namespace B {\n" 284 " int x;\n" 285 "} // namespace B\n" 286 "} // namespace A\n" 287 "\n" 288 "namespace C {\n" 289 "namespace D { int i; }\n" 290 "inline namespace E { namespace { int y; } }\n" 291 "int x= 0;" 292 "}"; 293 std::string Expected = "\n\nnamespace C {\n" 294 "namespace D { int i; }\n\n" 295 "int x= 0;" 296 "}"; 297 tooling::Replacements Replaces = { 298 createReplacement(getOffset(Code, 3, 3), 6, ""), 299 createReplacement(getOffset(Code, 9, 34), 6, "")}; 300 301 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 302 } 303 304 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) { 305 std::string Code = "int main() {}"; 306 std::string Expected = "#include \"a.h\"\n" 307 "int main() {}"; 308 tooling::Replacements Replaces = {createInsertion("#include \"a.h\"")}; 309 EXPECT_EQ(Expected, apply(Code, Replaces)); 310 } 311 312 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) { 313 std::string Code = "#ifndef A_H\n" 314 "#define A_H\n" 315 "class A {};\n" 316 "#define MMM 123\n" 317 "#endif"; 318 std::string Expected = "#ifndef A_H\n" 319 "#define A_H\n" 320 "#include \"b.h\"\n" 321 "class A {};\n" 322 "#define MMM 123\n" 323 "#endif"; 324 325 tooling::Replacements Replaces = {createInsertion("#include \"b.h\"")}; 326 EXPECT_EQ(Expected, apply(Code, Replaces)); 327 } 328 329 TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) { 330 std::string Code = "#ifndef A_H\n" 331 "#define A_H\n" 332 "\n" 333 "\n" 334 "\n" 335 "#include <vector>\n" 336 "class A {};\n" 337 "#define MMM 123\n" 338 "#endif"; 339 std::string Expected = "#ifndef A_H\n" 340 "#define A_H\n" 341 "\n" 342 "\n" 343 "\n" 344 "#include \"a.h\"\n" 345 "#include <vector>\n" 346 "class A {};\n" 347 "#define MMM 123\n" 348 "#endif"; 349 350 tooling::Replacements Replaces = {createInsertion("#include \"a.h\"")}; 351 EXPECT_EQ(Expected, apply(Code, Replaces)); 352 } 353 354 TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) { 355 std::string Code = "#include \"fix.h\"\n" 356 "\n" 357 "int main() {}"; 358 std::string Expected = "#include \"fix.h\"\n" 359 "#include <a>\n" 360 "\n" 361 "int main() {}"; 362 tooling::Replacements Replaces = {createInsertion("#include <a>")}; 363 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 364 EXPECT_EQ(Expected, apply(Code, Replaces)); 365 } 366 367 TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) { 368 std::string Code = "#include <memory>\n" 369 "\n" 370 "int main() {}"; 371 std::string Expected = "#include \"z.h\"\n" 372 "#include <memory>\n" 373 "\n" 374 "int main() {}"; 375 tooling::Replacements Replaces = {createInsertion("#include \"z.h\"")}; 376 EXPECT_EQ(Expected, apply(Code, Replaces)); 377 } 378 379 TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) { 380 std::string Code = "#include <memory>\n" 381 "\n" 382 "int main() {}"; 383 std::string Expected = "#include <memory>\n" 384 "#include \"z.h\"\n" 385 "\n" 386 "int main() {}"; 387 tooling::Replacements Replaces = {createInsertion("#include \"z.h\"")}; 388 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 389 EXPECT_EQ(Expected, apply(Code, Replaces)); 390 } 391 392 TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) { 393 std::string Code = "#include \"x/fix.h\"\n" 394 "#include \"a.h\"\n" 395 "#include \"b.h\"\n" 396 "#include \"clang/Format/Format.h\"\n" 397 "#include <memory>\n"; 398 std::string Expected = "#include \"x/fix.h\"\n" 399 "#include \"a.h\"\n" 400 "#include \"b.h\"\n" 401 "#include \"d.h\"\n" 402 "#include \"clang/Format/Format.h\"\n" 403 "#include \"llvm/x/y.h\"\n" 404 "#include <memory>\n"; 405 tooling::Replacements Replaces = {createInsertion("#include \"d.h\""), 406 createInsertion("#include \"llvm/x/y.h\"")}; 407 EXPECT_EQ(Expected, apply(Code, Replaces)); 408 } 409 410 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) { 411 std::string Code = "#include \"x/fix.h\"\n" 412 "#include \"a.h\"\n" 413 "#include \"b.h\"\n" 414 "#include \"clang/Format/Format.h\"\n" 415 "#include <memory>\n"; 416 std::string Expected = "#include \"x/fix.h\"\n" 417 "#include \"a.h\"\n" 418 "#include \"b.h\"\n" 419 "#include \"new/new.h\"\n" 420 "#include \"clang/Format/Format.h\"\n" 421 "#include <memory>\n" 422 "#include <list>\n"; 423 tooling::Replacements Replaces = {createInsertion("#include <list>"), 424 createInsertion("#include \"new/new.h\"")}; 425 EXPECT_EQ(Expected, apply(Code, Replaces)); 426 } 427 428 TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) { 429 std::string Code = "#include \"x/fix.h\"\n" 430 "\n" 431 "#include \"y/a.h\"\n" 432 "#include \"z/b.h\"\n"; 433 // FIXME: inserting after the empty line following the main header might be 434 // prefered. 435 std::string Expected = "#include \"x/fix.h\"\n" 436 "#include <vector>\n" 437 "\n" 438 "#include \"y/a.h\"\n" 439 "#include \"z/b.h\"\n"; 440 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 441 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 442 EXPECT_EQ(Expected, apply(Code, Replaces)); 443 } 444 445 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) { 446 std::string Code = "#include \"x/fix.h\"\n" 447 "\n" 448 "#include <vector>\n" 449 "\n" 450 "#include \"y/a.h\"\n" 451 "#include \"z/b.h\"\n"; 452 std::string Expected = "#include \"x/fix.h\"\n" 453 "\n" 454 "#include <vector>\n" 455 "#include <list>\n" 456 "\n" 457 "#include \"y/a.h\"\n" 458 "#include \"z/b.h\"\n" 459 "#include \"x/x.h\"\n"; 460 tooling::Replacements Replaces = {createInsertion("#include <list>"), 461 createInsertion("#include \"x/x.h\"")}; 462 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 463 EXPECT_EQ(Expected, apply(Code, Replaces)); 464 } 465 466 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) { 467 std::string Code = "\nint x;"; 468 std::string Expected = "\n#include \"fix.h\"\n" 469 "#include \"a.h\"\n" 470 "#include \"b.h\"\n" 471 "#include \"c.h\"\n" 472 "#include <list>\n" 473 "#include <vector>\n" 474 "int x;"; 475 tooling::Replacements Replaces = {createInsertion("#include \"a.h\""), 476 createInsertion("#include \"c.h\""), 477 createInsertion("#include \"b.h\""), 478 createInsertion("#include <vector>"), 479 createInsertion("#include <list>"), 480 createInsertion("#include \"fix.h\"")}; 481 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 482 } 483 484 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) { 485 std::string Code = "\nint x;"; 486 std::string Expected = "\n#include \"fix.h\"\n" 487 "#include <list>\n" 488 "#include <vector>\n" 489 "#include \"a.h\"\n" 490 "#include \"b.h\"\n" 491 "#include \"c.h\"\n" 492 "int x;"; 493 tooling::Replacements Replaces = {createInsertion("#include \"a.h\""), 494 createInsertion("#include \"c.h\""), 495 createInsertion("#include \"b.h\""), 496 createInsertion("#include <vector>"), 497 createInsertion("#include <list>"), 498 createInsertion("#include \"fix.h\"")}; 499 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp); 500 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 501 } 502 503 TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) { 504 std::string Code = "\n" 505 "int x;\n" 506 "int a;\n" 507 "int a;\n" 508 "int a;"; 509 510 std::string Expected = "\n#include \"x.h\"\n" 511 "#include \"y.h\"\n" 512 "#include \"clang/x/x.h\"\n" 513 "#include <list>\n" 514 "#include <vector>\n" 515 "int x;\n" 516 "int a;\n" 517 "int b;\n" 518 "int a;"; 519 tooling::Replacements Replaces = { 520 createReplacement(getOffset(Code, 4, 8), 1, "b"), 521 createInsertion("#include <vector>"), 522 createInsertion("#include <list>"), 523 createInsertion("#include \"clang/x/x.h\""), 524 createInsertion("#include \"y.h\""), 525 createInsertion("#include \"x.h\"")}; 526 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 527 } 528 529 TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) { 530 std::string Code = "void f() {}\n" 531 "#define A \\\n" 532 " int i;"; 533 std::string Expected = "#include <vector>\n" 534 "void f() {}\n" 535 "#define A \\\n" 536 " int i;"; 537 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 538 EXPECT_EQ(Expected, formatAndApply(Code, Replaces)); 539 } 540 541 TEST_F(CleanUpReplacementsTest, SkippedTopComment) { 542 std::string Code = "// comment\n" 543 "\n" 544 " // comment\n"; 545 std::string Expected = "// comment\n" 546 "\n" 547 " // comment\n" 548 "#include <vector>\n"; 549 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 550 EXPECT_EQ(Expected, apply(Code, Replaces)); 551 } 552 553 TEST_F(CleanUpReplacementsTest, SkippedMixedComments) { 554 std::string Code = "// comment\n" 555 "// comment \\\n" 556 " comment continued\n" 557 "/*\n" 558 "* comment\n" 559 "*/\n"; 560 std::string Expected = "// comment\n" 561 "// comment \\\n" 562 " comment continued\n" 563 "/*\n" 564 "* comment\n" 565 "*/\n" 566 "#include <vector>\n"; 567 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 568 EXPECT_EQ(Expected, apply(Code, Replaces)); 569 } 570 571 TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) { 572 std::string Code = "/*\n" 573 "* comment\n" 574 "*/ /* comment\n" 575 "*/\n" 576 "\n\n" 577 "/* c1 */ /*c2 */\n"; 578 std::string Expected = "/*\n" 579 "* comment\n" 580 "*/ /* comment\n" 581 "*/\n" 582 "\n\n" 583 "/* c1 */ /*c2 */\n" 584 "#include <vector>\n"; 585 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 586 EXPECT_EQ(Expected, apply(Code, Replaces)); 587 } 588 589 TEST_F(CleanUpReplacementsTest, CodeAfterComments) { 590 std::string Code = "/*\n" 591 "* comment\n" 592 "*/ /* comment\n" 593 "*/\n" 594 "\n\n" 595 "/* c1 */ /*c2 */\n" 596 "\n" 597 "int x;\n"; 598 std::string Expected = "/*\n" 599 "* comment\n" 600 "*/ /* comment\n" 601 "*/\n" 602 "\n\n" 603 "/* c1 */ /*c2 */\n" 604 "\n" 605 "#include <vector>\n" 606 "int x;\n"; 607 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 608 EXPECT_EQ(Expected, apply(Code, Replaces)); 609 } 610 611 TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) { 612 std::string Code = "// comment \n" 613 "#ifdef X\n" 614 "#define X\n"; 615 std::string Expected = "// comment \n" 616 "#include <vector>\n" 617 "#ifdef X\n" 618 "#define X\n"; 619 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 620 EXPECT_EQ(Expected, apply(Code, Replaces)); 621 } 622 623 TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) { 624 std::string Code = "// comment \n" 625 "#ifndef X\n" 626 "#define X\n" 627 "int x;\n" 628 "#define Y 1\n"; 629 std::string Expected = "// comment \n" 630 "#ifndef X\n" 631 "#define X\n" 632 "#include <vector>\n" 633 "int x;\n" 634 "#define Y 1\n"; 635 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 636 EXPECT_EQ(Expected, apply(Code, Replaces)); 637 } 638 639 TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) { 640 std::string Code = "// comment \n" 641 "#ifndef X\n" 642 "int x;\n" 643 "#define Y 1\n"; 644 std::string Expected = "// comment \n" 645 "#include <vector>\n" 646 "#ifndef X\n" 647 "int x;\n" 648 "#define Y 1\n"; 649 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 650 EXPECT_EQ(Expected, apply(Code, Replaces)); 651 } 652 653 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) { 654 std::string Code = "// comment \n" 655 "#ifndef X // comment\n" 656 "// comment\n" 657 "/* comment\n" 658 "*/\n" 659 "/* comment */ #define X\n" 660 "int x;\n" 661 "#define Y 1\n"; 662 std::string Expected = "// comment \n" 663 "#ifndef X // comment\n" 664 "// comment\n" 665 "/* comment\n" 666 "*/\n" 667 "/* comment */ #define X\n" 668 "#include <vector>\n" 669 "int x;\n" 670 "#define Y 1\n"; 671 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 672 EXPECT_EQ(Expected, apply(Code, Replaces)); 673 } 674 675 TEST_F(CleanUpReplacementsTest, EmptyCode) { 676 std::string Code = ""; 677 std::string Expected = "#include <vector>\n"; 678 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 679 EXPECT_EQ(Expected, apply(Code, Replaces)); 680 } 681 682 // FIXME: although this case does not crash, the insertion is wrong. A '\n' 683 // should be inserted between the two #includes. 684 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) { 685 std::string Code = "#include <map>"; 686 std::string Expected = "#include <map>#include <vector>\n"; 687 tooling::Replacements Replaces = {createInsertion("#include <vector>")}; 688 EXPECT_EQ(Expected, apply(Code, Replaces)); 689 } 690 691 } // end namespace 692 } // end namespace format 693 } // end namespace clang 694