1 //===- unittest/Tooling/RangeSelectorTest.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/RangeSelector.h" 10 #include "clang/ASTMatchers/ASTMatchers.h" 11 #include "clang/Frontend/ASTUnit.h" 12 #include "clang/Tooling/Tooling.h" 13 #include "clang/Tooling/Transformer/Parsing.h" 14 #include "clang/Tooling/Transformer/SourceCode.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Testing/Support/Error.h" 17 #include "gmock/gmock.h" 18 #include "gtest/gtest.h" 19 20 using namespace clang; 21 using namespace transformer; 22 using namespace ast_matchers; 23 24 namespace { 25 using ::llvm::Expected; 26 using ::llvm::Failed; 27 using ::llvm::HasValue; 28 using ::llvm::StringError; 29 using ::testing::AllOf; 30 using ::testing::HasSubstr; 31 using ::testing::Property; 32 33 using MatchResult = MatchFinder::MatchResult; 34 35 struct TestMatch { 36 // The AST unit from which `result` is built. We bundle it because it backs 37 // the result. Users are not expected to access it. 38 std::unique_ptr<clang::ASTUnit> ASTUnit; 39 // The result to use in the test. References `ast_unit`. 40 MatchResult Result; 41 }; 42 43 template <typename M> TestMatch matchCode(StringRef Code, M Matcher) { 44 auto ASTUnit = tooling::buildASTFromCode(Code); 45 assert(ASTUnit != nullptr && "AST construction failed"); 46 47 ASTContext &Context = ASTUnit->getASTContext(); 48 assert(!Context.getDiagnostics().hasErrorOccurred() && "Compilation error"); 49 50 TraversalKindScope RAII(Context, ast_type_traits::TK_AsIs); 51 auto Matches = ast_matchers::match(Matcher, Context); 52 // We expect a single, exact match. 53 assert(Matches.size() != 0 && "no matches found"); 54 assert(Matches.size() == 1 && "too many matches"); 55 56 return TestMatch{std::move(ASTUnit), MatchResult(Matches[0], &Context)}; 57 } 58 59 // Applies \p Selector to \p Match and, on success, returns the selected source. 60 Expected<StringRef> select(RangeSelector Selector, const TestMatch &Match) { 61 Expected<CharSourceRange> Range = Selector(Match.Result); 62 if (!Range) 63 return Range.takeError(); 64 return tooling::getText(*Range, *Match.Result.Context); 65 } 66 67 // Applies \p Selector to a trivial match with only a single bound node with id 68 // "bound_node_id". For use in testing unbound-node errors. 69 Expected<CharSourceRange> selectFromTrivial(const RangeSelector &Selector) { 70 // We need to bind the result to something, or the match will fail. Use a 71 // binding that is not used in the unbound node tests. 72 TestMatch Match = 73 matchCode("static int x = 0;", varDecl().bind("bound_node_id")); 74 return Selector(Match.Result); 75 } 76 77 // Matches the message expected for unbound-node failures. 78 testing::Matcher<StringError> withUnboundNodeMessage() { 79 return testing::Property( 80 &StringError::getMessage, 81 AllOf(HasSubstr("unbound_id"), HasSubstr("not bound"))); 82 } 83 84 // Applies \p Selector to code containing assorted node types, where the match 85 // binds each one: a statement ("stmt"), a (non-member) ctor-initializer 86 // ("init"), an expression ("expr") and a (nameless) declaration ("decl"). Used 87 // to test failures caused by applying selectors to nodes of the wrong type. 88 Expected<CharSourceRange> selectFromAssorted(RangeSelector Selector) { 89 StringRef Code = R"cc( 90 struct A {}; 91 class F : public A { 92 public: 93 F(int) {} 94 }; 95 void g() { F f(1); } 96 )cc"; 97 98 auto Matcher = 99 compoundStmt( 100 hasDescendant( 101 cxxConstructExpr( 102 hasDeclaration( 103 decl(hasDescendant(cxxCtorInitializer(isBaseInitializer()) 104 .bind("init"))) 105 .bind("decl"))) 106 .bind("expr"))) 107 .bind("stmt"); 108 109 return Selector(matchCode(Code, Matcher).Result); 110 } 111 112 // Matches the message expected for type-error failures. 113 testing::Matcher<StringError> withTypeErrorMessage(const std::string &NodeID) { 114 return testing::Property( 115 &StringError::getMessage, 116 AllOf(HasSubstr(NodeID), HasSubstr("mismatched type"))); 117 } 118 119 TEST(RangeSelectorTest, UnboundNode) { 120 EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")), 121 Failed<StringError>(withUnboundNodeMessage())); 122 } 123 124 MATCHER_P(EqualsCharSourceRange, Range, "") { 125 return Range.getAsRange() == arg.getAsRange() && 126 Range.isTokenRange() == arg.isTokenRange(); 127 } 128 129 // FIXME: here and elsewhere: use llvm::Annotations library to explicitly mark 130 // points and ranges of interest, enabling more readable tests. 131 TEST(RangeSelectorTest, BeforeOp) { 132 StringRef Code = R"cc( 133 int f(int x, int y, int z) { return 3; } 134 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 135 )cc"; 136 StringRef CallID = "call"; 137 ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID); 138 RangeSelector R = before(node(CallID.str())); 139 140 TestMatch Match = matchCode(Code, M); 141 const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID); 142 assert(E != nullptr); 143 auto ExprBegin = E->getSourceRange().getBegin(); 144 EXPECT_THAT_EXPECTED( 145 R(Match.Result), 146 HasValue(EqualsCharSourceRange( 147 CharSourceRange::getCharRange(ExprBegin, ExprBegin)))); 148 } 149 150 TEST(RangeSelectorTest, BeforeOpParsed) { 151 StringRef Code = R"cc( 152 int f(int x, int y, int z) { return 3; } 153 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 154 )cc"; 155 StringRef CallID = "call"; 156 ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID); 157 auto R = parseRangeSelector(R"rs(before(node("call")))rs"); 158 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 159 160 TestMatch Match = matchCode(Code, M); 161 const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID); 162 assert(E != nullptr); 163 auto ExprBegin = E->getSourceRange().getBegin(); 164 EXPECT_THAT_EXPECTED( 165 (*R)(Match.Result), 166 HasValue(EqualsCharSourceRange( 167 CharSourceRange::getCharRange(ExprBegin, ExprBegin)))); 168 } 169 170 TEST(RangeSelectorTest, AfterOp) { 171 StringRef Code = R"cc( 172 int f(int x, int y, int z) { return 3; } 173 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 174 )cc"; 175 StringRef Call = "call"; 176 TestMatch Match = matchCode(Code, callExpr().bind(Call)); 177 const auto* E = Match.Result.Nodes.getNodeAs<Expr>(Call); 178 assert(E != nullptr); 179 const SourceRange Range = E->getSourceRange(); 180 // The end token, a right paren, is one character wide, so advance by one, 181 // bringing us to the semicolon. 182 const SourceLocation SemiLoc = Range.getEnd().getLocWithOffset(1); 183 const auto ExpectedAfter = CharSourceRange::getCharRange(SemiLoc, SemiLoc); 184 185 // Test with a char range. 186 auto CharRange = CharSourceRange::getCharRange(Range.getBegin(), SemiLoc); 187 EXPECT_THAT_EXPECTED(after(charRange(CharRange))(Match.Result), 188 HasValue(EqualsCharSourceRange(ExpectedAfter))); 189 190 // Test with a token range. 191 auto TokenRange = CharSourceRange::getTokenRange(Range); 192 EXPECT_THAT_EXPECTED(after(charRange(TokenRange))(Match.Result), 193 HasValue(EqualsCharSourceRange(ExpectedAfter))); 194 } 195 196 // Node-id specific version. 197 TEST(RangeSelectorTest, RangeOpNodes) { 198 StringRef Code = R"cc( 199 int f(int x, int y, int z) { return 3; } 200 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 201 )cc"; 202 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 203 hasArgument(1, expr().bind("a1"))); 204 RangeSelector R = encloseNodes("a0", "a1"); 205 TestMatch Match = matchCode(Code, Matcher); 206 EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7")); 207 } 208 209 TEST(RangeSelectorTest, RangeOpGeneral) { 210 StringRef Code = R"cc( 211 int f(int x, int y, int z) { return 3; } 212 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 213 )cc"; 214 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 215 hasArgument(1, expr().bind("a1"))); 216 RangeSelector R = enclose(node("a0"), node("a1")); 217 TestMatch Match = matchCode(Code, Matcher); 218 EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7")); 219 } 220 221 TEST(RangeSelectorTest, RangeOpNodesParsed) { 222 StringRef Code = R"cc( 223 int f(int x, int y, int z) { return 3; } 224 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 225 )cc"; 226 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 227 hasArgument(1, expr().bind("a1"))); 228 auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs"); 229 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 230 TestMatch Match = matchCode(Code, Matcher); 231 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7")); 232 } 233 234 TEST(RangeSelectorTest, RangeOpGeneralParsed) { 235 StringRef Code = R"cc( 236 int f(int x, int y, int z) { return 3; } 237 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 238 )cc"; 239 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 240 hasArgument(1, expr().bind("a1"))); 241 auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs"); 242 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 243 TestMatch Match = matchCode(Code, Matcher); 244 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7")); 245 } 246 247 TEST(RangeSelectorTest, NodeOpStatement) { 248 StringRef Code = "int f() { return 3; }"; 249 TestMatch Match = matchCode(Code, returnStmt().bind("id")); 250 EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("return 3;")); 251 } 252 253 TEST(RangeSelectorTest, NodeOpExpression) { 254 StringRef Code = "int f() { return 3; }"; 255 TestMatch Match = matchCode(Code, expr().bind("id")); 256 EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("3")); 257 } 258 259 TEST(RangeSelectorTest, StatementOp) { 260 StringRef Code = "int f() { return 3; }"; 261 TestMatch Match = matchCode(Code, expr().bind("id")); 262 RangeSelector R = statement("id"); 263 EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3;")); 264 } 265 266 TEST(RangeSelectorTest, StatementOpParsed) { 267 StringRef Code = "int f() { return 3; }"; 268 TestMatch Match = matchCode(Code, expr().bind("id")); 269 auto R = parseRangeSelector(R"rs(statement("id"))rs"); 270 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 271 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3;")); 272 } 273 274 TEST(RangeSelectorTest, MemberOp) { 275 StringRef Code = R"cc( 276 struct S { 277 int member; 278 }; 279 int g() { 280 S s; 281 return s.member; 282 } 283 )cc"; 284 const char *ID = "id"; 285 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 286 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member")); 287 } 288 289 // Tests that member does not select any qualifiers on the member name. 290 TEST(RangeSelectorTest, MemberOpQualified) { 291 StringRef Code = R"cc( 292 struct S { 293 int member; 294 }; 295 struct T : public S { 296 int field; 297 }; 298 int g() { 299 T t; 300 return t.S::member; 301 } 302 )cc"; 303 const char *ID = "id"; 304 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 305 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member")); 306 } 307 308 TEST(RangeSelectorTest, MemberOpTemplate) { 309 StringRef Code = R"cc( 310 struct S { 311 template <typename T> T foo(T t); 312 }; 313 int f(int x) { 314 S s; 315 return s.template foo<int>(3); 316 } 317 )cc"; 318 319 const char *ID = "id"; 320 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 321 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo")); 322 } 323 324 TEST(RangeSelectorTest, MemberOpOperator) { 325 StringRef Code = R"cc( 326 struct S { 327 int operator*(); 328 }; 329 int f(int x) { 330 S s; 331 return s.operator *(); 332 } 333 )cc"; 334 335 const char *ID = "id"; 336 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 337 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *")); 338 } 339 340 TEST(RangeSelectorTest, NameOpNamedDecl) { 341 StringRef Code = R"cc( 342 int myfun() { 343 return 3; 344 } 345 )cc"; 346 const char *ID = "id"; 347 TestMatch Match = matchCode(Code, functionDecl().bind(ID)); 348 EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("myfun")); 349 } 350 351 TEST(RangeSelectorTest, NameOpDeclRef) { 352 StringRef Code = R"cc( 353 int foo(int x) { 354 return x; 355 } 356 int g(int x) { return foo(x) * x; } 357 )cc"; 358 const char *Ref = "ref"; 359 TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref)); 360 EXPECT_THAT_EXPECTED(select(name(Ref), Match), HasValue("foo")); 361 } 362 363 TEST(RangeSelectorTest, NameOpCtorInitializer) { 364 StringRef Code = R"cc( 365 class C { 366 public: 367 C() : field(3) {} 368 int field; 369 }; 370 )cc"; 371 const char *Init = "init"; 372 TestMatch Match = matchCode(Code, cxxCtorInitializer().bind(Init)); 373 EXPECT_THAT_EXPECTED(select(name(Init), Match), HasValue("field")); 374 } 375 376 TEST(RangeSelectorTest, NameOpErrors) { 377 EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")), 378 Failed<StringError>(withUnboundNodeMessage())); 379 EXPECT_THAT_EXPECTED(selectFromAssorted(name("stmt")), 380 Failed<StringError>(withTypeErrorMessage("stmt"))); 381 } 382 383 TEST(RangeSelectorTest, NameOpDeclRefError) { 384 StringRef Code = R"cc( 385 struct S { 386 int operator*(); 387 }; 388 int f(int x) { 389 S s; 390 return *s + x; 391 } 392 )cc"; 393 const char *Ref = "ref"; 394 TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref)); 395 EXPECT_THAT_EXPECTED( 396 name(Ref)(Match.Result), 397 Failed<StringError>(testing::Property( 398 &StringError::getMessage, 399 AllOf(HasSubstr(Ref), HasSubstr("requires property 'identifier'"))))); 400 } 401 402 TEST(RangeSelectorTest, CallArgsOp) { 403 const StringRef Code = R"cc( 404 struct C { 405 int bar(int, int); 406 }; 407 int f() { 408 C x; 409 return x.bar(3, 4); 410 } 411 )cc"; 412 const char *ID = "id"; 413 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 414 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4")); 415 } 416 417 TEST(RangeSelectorTest, CallArgsOpNoArgs) { 418 const StringRef Code = R"cc( 419 struct C { 420 int bar(); 421 }; 422 int f() { 423 C x; 424 return x.bar(); 425 } 426 )cc"; 427 const char *ID = "id"; 428 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 429 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("")); 430 } 431 432 TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) { 433 const StringRef Code = R"cc( 434 struct C { 435 int bar(); 436 }; 437 int f() { 438 C x; 439 return x.bar(/*empty*/); 440 } 441 )cc"; 442 const char *ID = "id"; 443 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 444 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("/*empty*/")); 445 } 446 447 // Tests that arguments are extracted correctly when a temporary (with parens) 448 // is used. 449 TEST(RangeSelectorTest, CallArgsOpWithParens) { 450 const StringRef Code = R"cc( 451 struct C { 452 int bar(int, int) { return 3; } 453 }; 454 int f() { 455 C x; 456 return C().bar(3, 4); 457 } 458 )cc"; 459 const char *ID = "id"; 460 TestMatch Match = 461 matchCode(Code, callExpr(callee(functionDecl(hasName("bar")))).bind(ID)); 462 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4")); 463 } 464 465 TEST(RangeSelectorTest, CallArgsOpLeadingComments) { 466 const StringRef Code = R"cc( 467 struct C { 468 int bar(int, int) { return 3; } 469 }; 470 int f() { 471 C x; 472 return x.bar(/*leading*/ 3, 4); 473 } 474 )cc"; 475 const char *ID = "id"; 476 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 477 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), 478 HasValue("/*leading*/ 3, 4")); 479 } 480 481 TEST(RangeSelectorTest, CallArgsOpTrailingComments) { 482 const StringRef Code = R"cc( 483 struct C { 484 int bar(int, int) { return 3; } 485 }; 486 int f() { 487 C x; 488 return x.bar(3 /*trailing*/, 4); 489 } 490 )cc"; 491 const char *ID = "id"; 492 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 493 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), 494 HasValue("3 /*trailing*/, 4")); 495 } 496 497 TEST(RangeSelectorTest, CallArgsOpEolComments) { 498 const StringRef Code = R"cc( 499 struct C { 500 int bar(int, int) { return 3; } 501 }; 502 int f() { 503 C x; 504 return x.bar( // Header 505 1, // foo 506 2 // bar 507 ); 508 } 509 )cc"; 510 const char *ID = "id"; 511 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 512 std::string ExpectedString = R"( // Header 513 1, // foo 514 2 // bar 515 )"; 516 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString)); 517 } 518 519 TEST(RangeSelectorTest, CallArgsErrors) { 520 EXPECT_THAT_EXPECTED(selectFromTrivial(callArgs("unbound_id")), 521 Failed<StringError>(withUnboundNodeMessage())); 522 EXPECT_THAT_EXPECTED(selectFromAssorted(callArgs("stmt")), 523 Failed<StringError>(withTypeErrorMessage("stmt"))); 524 } 525 526 TEST(RangeSelectorTest, StatementsOp) { 527 StringRef Code = R"cc( 528 void g(); 529 void f() { /* comment */ g(); /* comment */ g(); /* comment */ } 530 )cc"; 531 const char *ID = "id"; 532 TestMatch Match = matchCode(Code, compoundStmt().bind(ID)); 533 EXPECT_THAT_EXPECTED( 534 select(statements(ID), Match), 535 HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ ")); 536 } 537 538 TEST(RangeSelectorTest, StatementsOpEmptyList) { 539 StringRef Code = "void f() {}"; 540 const char *ID = "id"; 541 TestMatch Match = matchCode(Code, compoundStmt().bind(ID)); 542 EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue("")); 543 } 544 545 TEST(RangeSelectorTest, StatementsOpErrors) { 546 EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")), 547 Failed<StringError>(withUnboundNodeMessage())); 548 EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")), 549 Failed<StringError>(withTypeErrorMessage("decl"))); 550 } 551 552 TEST(RangeSelectorTest, ElementsOp) { 553 StringRef Code = R"cc( 554 void f() { 555 int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */}; 556 (void)v; 557 } 558 )cc"; 559 const char *ID = "id"; 560 TestMatch Match = matchCode(Code, initListExpr().bind(ID)); 561 EXPECT_THAT_EXPECTED( 562 select(initListElements(ID), Match), 563 HasValue("/* comment */ 3, /* comment*/ 4 /* comment */")); 564 } 565 566 TEST(RangeSelectorTest, ElementsOpEmptyList) { 567 StringRef Code = R"cc( 568 void f() { 569 int v[] = {}; 570 (void)v; 571 } 572 )cc"; 573 const char *ID = "id"; 574 TestMatch Match = matchCode(Code, initListExpr().bind(ID)); 575 EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue("")); 576 } 577 578 TEST(RangeSelectorTest, ElementsOpErrors) { 579 EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")), 580 Failed<StringError>(withUnboundNodeMessage())); 581 EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")), 582 Failed<StringError>(withTypeErrorMessage("stmt"))); 583 } 584 585 TEST(RangeSelectorTest, ElseBranchOpSingleStatement) { 586 StringRef Code = R"cc( 587 int f() { 588 int x = 0; 589 if (true) x = 3; 590 else x = 4; 591 return x + 5; 592 } 593 )cc"; 594 const char *ID = "id"; 595 TestMatch Match = matchCode(Code, ifStmt().bind(ID)); 596 EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;")); 597 } 598 599 TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) { 600 StringRef Code = R"cc( 601 int f() { 602 int x = 0; 603 if (true) x = 3; 604 else { x = 4; } 605 return x + 5; 606 } 607 )cc"; 608 const char *ID = "id"; 609 TestMatch Match = matchCode(Code, ifStmt().bind(ID)); 610 EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), 611 HasValue("else { x = 4; }")); 612 } 613 614 // Tests case where the matched node is the complete expanded text. 615 TEST(RangeSelectorTest, ExpansionOp) { 616 StringRef Code = R"cc( 617 #define BADDECL(E) int bad(int x) { return E; } 618 BADDECL(x * x) 619 )cc"; 620 621 const char *Fun = "Fun"; 622 TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun)); 623 EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match), 624 HasValue("BADDECL(x * x)")); 625 } 626 627 // Tests case where the matched node is (only) part of the expanded text. 628 TEST(RangeSelectorTest, ExpansionOpPartial) { 629 StringRef Code = R"cc( 630 #define BADDECL(E) int bad(int x) { return E; } 631 BADDECL(x * x) 632 )cc"; 633 634 const char *Ret = "Ret"; 635 TestMatch Match = matchCode(Code, returnStmt().bind(Ret)); 636 EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match), 637 HasValue("BADDECL(x * x)")); 638 } 639 640 TEST(RangeSelectorTest, IfBoundOpBound) { 641 StringRef Code = R"cc( 642 int f() { 643 return 3 + 5; 644 } 645 )cc"; 646 const char *ID = "id", *Op = "op"; 647 TestMatch Match = 648 matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op)); 649 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match), 650 HasValue("3")); 651 } 652 653 TEST(RangeSelectorTest, IfBoundOpUnbound) { 654 StringRef Code = R"cc( 655 int f() { 656 return 3 + 5; 657 } 658 )cc"; 659 const char *ID = "id", *Op = "op"; 660 TestMatch Match = matchCode(Code, binaryOperator().bind(Op)); 661 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match), 662 HasValue("3 + 5")); 663 } 664 665 } // namespace 666