1 //===- unittest/Tooling/SourceCodeTest.cpp --------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Tooling/Transformer/SourceCode.h" 10 #include "TestVisitor.h" 11 #include "clang/Basic/Diagnostic.h" 12 #include "llvm/Testing/Support/Annotations.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "llvm/Testing/Support/SupportHelpers.h" 15 #include <gmock/gmock.h> 16 #include <gtest/gtest.h> 17 18 using namespace clang; 19 20 using llvm::Failed; 21 using llvm::Succeeded; 22 using llvm::ValueIs; 23 using tooling::getAssociatedRange; 24 using tooling::getExtendedText; 25 using tooling::getRangeForEdit; 26 using tooling::getText; 27 using tooling::validateEditRange; 28 29 namespace { 30 31 struct IntLitVisitor : TestVisitor<IntLitVisitor> { 32 bool VisitIntegerLiteral(IntegerLiteral *Expr) { 33 OnIntLit(Expr, Context); 34 return true; 35 } 36 37 std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit; 38 }; 39 40 struct CallsVisitor : TestVisitor<CallsVisitor> { 41 bool VisitCallExpr(CallExpr *Expr) { 42 OnCall(Expr, Context); 43 return true; 44 } 45 46 std::function<void(CallExpr *, ASTContext *Context)> OnCall; 47 }; 48 49 // Equality matcher for `clang::CharSourceRange`, which lacks `operator==`. 50 MATCHER_P(EqualsRange, R, "") { 51 return arg.isTokenRange() == R.isTokenRange() && 52 arg.getBegin() == R.getBegin() && arg.getEnd() == R.getEnd(); 53 } 54 55 MATCHER_P2(EqualsAnnotatedRange, SM, R, "") { 56 if (arg.getBegin().isMacroID()) { 57 *result_listener << "which starts in a macro"; 58 return false; 59 } 60 if (arg.getEnd().isMacroID()) { 61 *result_listener << "which ends in a macro"; 62 return false; 63 } 64 65 unsigned Begin = SM->getFileOffset(arg.getBegin()); 66 unsigned End = SM->getFileOffset(arg.getEnd()); 67 68 *result_listener << "which is [" << Begin << ","; 69 if (arg.isTokenRange()) { 70 *result_listener << End << "]"; 71 return Begin == R.Begin && End + 1 == R.End; 72 } 73 *result_listener << End << ")"; 74 return Begin == R.Begin && End == R.End; 75 } 76 77 static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM, 78 llvm::Annotations::Range R) { 79 return EqualsRange(CharSourceRange::getCharRange( 80 SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.Begin), 81 SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.End))); 82 } 83 84 // Base class for visitors that expect a single match corresponding to a 85 // specific annotated range. 86 template <typename T> class AnnotatedCodeVisitor : public TestVisitor<T> { 87 llvm::Annotations Code; 88 int MatchCount = 0; 89 90 public: 91 AnnotatedCodeVisitor() : Code("$r[[]]") {} 92 bool VisitDeclHelper(Decl *Decl) { 93 // Only consider explicit declarations. 94 if (Decl->isImplicit()) 95 return true; 96 97 ++MatchCount; 98 EXPECT_THAT(getAssociatedRange(*Decl, *this->Context), 99 EqualsAnnotatedRange(&this->Context->getSourceManager(), 100 Code.range("r"))) 101 << Code.code(); 102 return true; 103 } 104 105 bool runOverAnnotated(llvm::StringRef AnnotatedCode, 106 std::vector<std::string> Args = {}) { 107 Code = llvm::Annotations(AnnotatedCode); 108 MatchCount = 0; 109 Args.push_back("-std=c++11"); 110 Args.push_back("-fno-delayed-template-parsing"); 111 bool result = tooling::runToolOnCodeWithArgs(this->CreateTestAction(), 112 Code.code(), Args); 113 EXPECT_EQ(MatchCount, 1) << AnnotatedCode; 114 return result; 115 } 116 }; 117 118 TEST(SourceCodeTest, getText) { 119 CallsVisitor Visitor; 120 121 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 122 EXPECT_EQ("foo(x, y)", getText(*CE, *Context)); 123 }; 124 Visitor.runOver("void foo(int x, int y) { foo(x, y); }"); 125 126 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 127 EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context)); 128 }; 129 Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n" 130 "void foo(int x, int y) { APPLY(foo, x, y); }"); 131 } 132 133 TEST(SourceCodeTest, getTextWithMacro) { 134 CallsVisitor Visitor; 135 136 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 137 EXPECT_EQ("F OO", getText(*CE, *Context)); 138 Expr *P0 = CE->getArg(0); 139 Expr *P1 = CE->getArg(1); 140 EXPECT_EQ("", getText(*P0, *Context)); 141 EXPECT_EQ("", getText(*P1, *Context)); 142 }; 143 Visitor.runOver("#define F foo(\n" 144 "#define OO x, y)\n" 145 "void foo(int x, int y) { F OO ; }"); 146 147 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 148 EXPECT_EQ("", getText(*CE, *Context)); 149 Expr *P0 = CE->getArg(0); 150 Expr *P1 = CE->getArg(1); 151 EXPECT_EQ("x", getText(*P0, *Context)); 152 EXPECT_EQ("y", getText(*P1, *Context)); 153 }; 154 Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n" 155 "void foo(int x, int y) { FOO(x,y) }"); 156 } 157 158 TEST(SourceCodeTest, getExtendedText) { 159 CallsVisitor Visitor; 160 161 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 162 EXPECT_EQ("foo(x, y);", 163 getExtendedText(*CE, tok::TokenKind::semi, *Context)); 164 165 Expr *P0 = CE->getArg(0); 166 Expr *P1 = CE->getArg(1); 167 EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context)); 168 EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context)); 169 EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context)); 170 }; 171 Visitor.runOver("void foo(int x, int y) { foo(x, y); }"); 172 Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }"); 173 Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }"); 174 Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }"); 175 Visitor.runOver( 176 "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }"); 177 178 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 179 EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context)); 180 }; 181 Visitor.runOver("bool foo() { if (foo()) return true; return false; }"); 182 Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }"); 183 Visitor.runOver("int foo() { return foo() + 3; }"); 184 } 185 186 TEST(SourceCodeTest, getAssociatedRange) { 187 struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> { 188 bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); } 189 }; 190 VarDeclsVisitor Visitor; 191 192 // Includes semicolon. 193 Visitor.runOverAnnotated("$r[[int x = 4;]]"); 194 195 // Includes newline and semicolon. 196 Visitor.runOverAnnotated("$r[[int x = 4;\n]]"); 197 198 // Includes trailing comments. 199 Visitor.runOverAnnotated("$r[[int x = 4; // Comment\n]]"); 200 Visitor.runOverAnnotated("$r[[int x = 4; /* Comment */\n]]"); 201 202 // Does *not* include trailing comments when another entity appears between 203 // the decl and the comment. 204 Visitor.runOverAnnotated("$r[[int x = 4;]] class C {}; // Comment\n"); 205 206 // Includes attributes. 207 Visitor.runOverAnnotated(R"cpp( 208 #define ATTR __attribute__((deprecated("message"))) 209 $r[[ATTR 210 int x;]])cpp"); 211 212 // Includes attributes and comments together. 213 Visitor.runOverAnnotated(R"cpp( 214 #define ATTR __attribute__((deprecated("message"))) 215 $r[[ATTR 216 // Commment. 217 int x;]])cpp"); 218 } 219 220 TEST(SourceCodeTest, getAssociatedRangeClasses) { 221 struct RecordDeclsVisitor : AnnotatedCodeVisitor<RecordDeclsVisitor> { 222 bool VisitRecordDecl(RecordDecl *Decl) { return VisitDeclHelper(Decl); } 223 }; 224 RecordDeclsVisitor Visitor; 225 226 Visitor.runOverAnnotated("$r[[class A;]]"); 227 Visitor.runOverAnnotated("$r[[class A {};]]"); 228 229 // Includes leading template annotation. 230 Visitor.runOverAnnotated("$r[[template <typename T> class A;]]"); 231 Visitor.runOverAnnotated("$r[[template <typename T> class A {};]]"); 232 } 233 234 TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) { 235 struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor<CXXRecordDeclsVisitor> { 236 bool VisitCXXRecordDecl(CXXRecordDecl *Decl) { 237 return Decl->getTemplateSpecializationKind() != 238 TSK_ExplicitSpecialization || 239 VisitDeclHelper(Decl); 240 } 241 }; 242 CXXRecordDeclsVisitor Visitor; 243 244 Visitor.runOverAnnotated(R"cpp( 245 template <typename T> class A{}; 246 $r[[template <> class A<int>;]])cpp"); 247 Visitor.runOverAnnotated(R"cpp( 248 template <typename T> class A{}; 249 $r[[template <> class A<int> {};]])cpp"); 250 } 251 252 TEST(SourceCodeTest, getAssociatedRangeFunctions) { 253 struct FunctionDeclsVisitor : AnnotatedCodeVisitor<FunctionDeclsVisitor> { 254 bool VisitFunctionDecl(FunctionDecl *Decl) { return VisitDeclHelper(Decl); } 255 }; 256 FunctionDeclsVisitor Visitor; 257 258 Visitor.runOverAnnotated("$r[[int f();]]"); 259 Visitor.runOverAnnotated("$r[[int f() { return 0; }]]"); 260 // Includes leading template annotation. 261 Visitor.runOverAnnotated("$r[[template <typename T> int f();]]"); 262 Visitor.runOverAnnotated("$r[[template <typename T> int f() { return 0; }]]"); 263 } 264 265 TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) { 266 struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor<CXXMethodDeclsVisitor> { 267 bool VisitCXXMethodDecl(CXXMethodDecl *Decl) { 268 // Only consider the definition of the template. 269 return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl); 270 } 271 }; 272 CXXMethodDeclsVisitor Visitor; 273 274 Visitor.runOverAnnotated(R"cpp( 275 template <typename C> 276 struct A { template <typename T> int member(T v); }; 277 278 $r[[template <typename C> 279 template <typename T> 280 int A<C>::member(T v) { return 0; }]])cpp"); 281 } 282 283 TEST(SourceCodeTest, getAssociatedRangeWithComments) { 284 struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> { 285 bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); } 286 }; 287 288 VarDeclsVisitor Visitor; 289 auto Visit = [&](llvm::StringRef AnnotatedCode) { 290 Visitor.runOverAnnotated(AnnotatedCode, {"-fparse-all-comments"}); 291 }; 292 293 // Includes leading comments. 294 Visit("$r[[// Comment.\nint x = 4;]]"); 295 Visit("$r[[// Comment.\nint x = 4;\n]]"); 296 Visit("$r[[/* Comment.*/\nint x = 4;\n]]"); 297 // ... even if separated by (extra) horizontal whitespace. 298 Visit("$r[[/* Comment.*/ \nint x = 4;\n]]"); 299 300 // Includes comments even in the presence of trailing whitespace. 301 Visit("$r[[// Comment.\nint x = 4;]] "); 302 303 // Includes comments when the declaration is followed by the beginning or end 304 // of a compound statement. 305 Visit(R"cpp( 306 void foo() { 307 $r[[/* C */ 308 int x = 4; 309 ]]};)cpp"); 310 Visit(R"cpp( 311 void foo() { 312 $r[[/* C */ 313 int x = 4; 314 ]]{ class Foo {}; } 315 })cpp"); 316 317 // Includes comments inside macros (when decl is in the same macro). 318 Visit(R"cpp( 319 #define DECL /* Comment */ int x 320 $r[[DECL;]])cpp"); 321 322 // Does not include comments when only the decl or the comment come from a 323 // macro. 324 // FIXME: Change code to allow this. 325 Visit(R"cpp( 326 #define DECL int x 327 // Comment 328 $r[[DECL;]])cpp"); 329 Visit(R"cpp( 330 #define COMMENT /* Comment */ 331 COMMENT 332 $r[[int x;]])cpp"); 333 334 // Includes multi-line comments. 335 Visit(R"cpp( 336 $r[[/* multi 337 * line 338 * comment 339 */ 340 int x;]])cpp"); 341 Visit(R"cpp( 342 $r[[// multi 343 // line 344 // comment 345 int x;]])cpp"); 346 347 // Does not include comments separated by multiple empty lines. 348 Visit("// Comment.\n\n\n$r[[int x = 4;\n]]"); 349 Visit("/* Comment.*/\n\n\n$r[[int x = 4;\n]]"); 350 351 // Does not include comments before a *series* of declarations. 352 Visit(R"cpp( 353 // Comment. 354 $r[[int x = 4; 355 ]]class foo {};)cpp"); 356 357 // Does not include IfThisThenThat comments 358 Visit("// LINT.IfChange.\n$r[[int x = 4;]]"); 359 Visit("// LINT.ThenChange.\n$r[[int x = 4;]]"); 360 361 // Includes attributes. 362 Visit(R"cpp( 363 #define ATTR __attribute__((deprecated("message"))) 364 $r[[ATTR 365 int x;]])cpp"); 366 367 // Includes attributes and comments together. 368 Visit(R"cpp( 369 #define ATTR __attribute__((deprecated("message"))) 370 $r[[ATTR 371 // Commment. 372 int x;]])cpp"); 373 } 374 375 TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) { 376 struct FailingVarDeclsVisitor : TestVisitor<FailingVarDeclsVisitor> { 377 FailingVarDeclsVisitor() {} 378 bool VisitVarDecl(VarDecl *Decl) { 379 EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid()); 380 return true; 381 } 382 }; 383 384 FailingVarDeclsVisitor Visitor; 385 // Should fail because it only includes a part of the expansion. 386 std::string Code = R"cpp( 387 #define DECL class foo { }; int x 388 DECL;)cpp"; 389 Visitor.runOver(Code); 390 } 391 392 TEST(SourceCodeTest, EditRangeWithMacroExpansionsShouldSucceed) { 393 // The call expression, whose range we are extracting, includes two macro 394 // expansions. 395 llvm::Annotations Code(R"cpp( 396 #define M(a) a * 13 397 int foo(int x, int y); 398 int a = $r[[foo(M(1), M(2))]]; 399 )cpp"); 400 401 CallsVisitor Visitor; 402 403 Visitor.OnCall = [&Code](CallExpr *CE, ASTContext *Context) { 404 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 405 EXPECT_THAT(getRangeForEdit(Range, *Context), 406 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 407 }; 408 Visitor.runOver(Code.code()); 409 } 410 411 TEST(SourceCodeTest, EditWholeMacroExpansionShouldSucceed) { 412 llvm::Annotations Code(R"cpp( 413 #define FOO 10 414 int a = $r[[FOO]]; 415 )cpp"); 416 417 IntLitVisitor Visitor; 418 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 419 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 420 EXPECT_THAT(getRangeForEdit(Range, *Context), 421 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 422 }; 423 Visitor.runOver(Code.code()); 424 } 425 426 TEST(SourceCodeTest, EditPartialMacroExpansionShouldFail) { 427 std::string Code = R"cpp( 428 #define BAR 10+ 429 int c = BAR 3.0; 430 )cpp"; 431 432 IntLitVisitor Visitor; 433 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 434 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 435 EXPECT_FALSE(getRangeForEdit(Range, *Context).hasValue()); 436 }; 437 Visitor.runOver(Code); 438 } 439 440 TEST(SourceCodeTest, EditWholeMacroArgShouldSucceed) { 441 llvm::Annotations Code(R"cpp( 442 #define FOO(a) a + 7.0; 443 int a = FOO($r[[10]]); 444 )cpp"); 445 446 IntLitVisitor Visitor; 447 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 448 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 449 EXPECT_THAT(getRangeForEdit(Range, *Context), 450 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 451 }; 452 Visitor.runOver(Code.code()); 453 } 454 455 TEST(SourceCodeTest, EditPartialMacroArgShouldSucceed) { 456 llvm::Annotations Code(R"cpp( 457 #define FOO(a) a + 7.0; 458 int a = FOO($r[[10]] + 10.0); 459 )cpp"); 460 461 IntLitVisitor Visitor; 462 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) { 463 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 464 EXPECT_THAT(getRangeForEdit(Range, *Context), 465 ValueIs(AsRange(Context->getSourceManager(), Code.range("r")))); 466 }; 467 Visitor.runOver(Code.code()); 468 } 469 470 TEST(SourceCodeTest, EditRangeWithMacroExpansionsIsValid) { 471 // The call expression, whose range we are extracting, includes two macro 472 // expansions. 473 llvm::StringRef Code = R"cpp( 474 #define M(a) a * 13 475 int foo(int x, int y); 476 int a = foo(M(1), M(2)); 477 )cpp"; 478 479 CallsVisitor Visitor; 480 481 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) { 482 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange()); 483 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 484 Succeeded()); 485 }; 486 Visitor.runOver(Code); 487 } 488 489 TEST(SourceCodeTest, SpellingRangeOfMacroArgIsValid) { 490 llvm::StringRef Code = R"cpp( 491 #define FOO(a) a + 7.0; 492 int a = FOO(10); 493 )cpp"; 494 495 IntLitVisitor Visitor; 496 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 497 SourceLocation ArgLoc = 498 Context->getSourceManager().getSpellingLoc(Expr->getBeginLoc()); 499 // The integer literal is a single token. 500 auto ArgRange = CharSourceRange::getTokenRange(ArgLoc); 501 EXPECT_THAT_ERROR(validateEditRange(ArgRange, Context->getSourceManager()), 502 Succeeded()); 503 }; 504 Visitor.runOver(Code); 505 } 506 507 TEST(SourceCodeTest, InvalidEditRangeIsInvalid) { 508 llvm::StringRef Code = "int c = 10;"; 509 510 // We use the visitor just to get a valid context. 511 IntLitVisitor Visitor; 512 Visitor.OnIntLit = [](IntegerLiteral *, ASTContext *Context) { 513 CharSourceRange Invalid; 514 EXPECT_THAT_ERROR(validateEditRange(Invalid, Context->getSourceManager()), 515 Failed()); 516 }; 517 Visitor.runOver(Code); 518 } 519 520 TEST(SourceCodeTest, InvertedEditRangeIsInvalid) { 521 llvm::StringRef Code = R"cpp( 522 int foo(int x); 523 int a = foo(2); 524 )cpp"; 525 526 CallsVisitor Visitor; 527 Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) { 528 auto InvertedRange = CharSourceRange::getTokenRange( 529 SourceRange(Expr->getEndLoc(), Expr->getBeginLoc())); 530 EXPECT_THAT_ERROR( 531 validateEditRange(InvertedRange, Context->getSourceManager()), 532 Failed()); 533 }; 534 Visitor.runOver(Code); 535 } 536 537 TEST(SourceCodeTest, MacroArgIsInvalid) { 538 llvm::StringRef Code = R"cpp( 539 #define FOO(a) a + 7.0; 540 int a = FOO(10); 541 )cpp"; 542 543 IntLitVisitor Visitor; 544 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 545 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 546 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 547 Failed()); 548 }; 549 Visitor.runOver(Code); 550 } 551 552 TEST(SourceCodeTest, EditWholeMacroExpansionIsInvalid) { 553 llvm::StringRef Code = R"cpp( 554 #define FOO 10 555 int a = FOO; 556 )cpp"; 557 558 IntLitVisitor Visitor; 559 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 560 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 561 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 562 Failed()); 563 564 }; 565 Visitor.runOver(Code); 566 } 567 568 TEST(SourceCodeTest, EditPartialMacroExpansionIsInvalid) { 569 llvm::StringRef Code = R"cpp( 570 #define BAR 10+ 571 int c = BAR 3.0; 572 )cpp"; 573 574 IntLitVisitor Visitor; 575 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) { 576 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange()); 577 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()), 578 Failed()); 579 }; 580 Visitor.runOver(Code); 581 } 582 } // end anonymous namespace 583