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 TEST(RangeSelectorTest, BetweenOp) { 197 StringRef Code = R"cc( 198 int f(int x, int y, int z) { return 3; } 199 int g() { return f(3, /* comment */ 7 /* comment */, 9); } 200 )cc"; 201 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 202 hasArgument(1, expr().bind("a1"))); 203 RangeSelector R = between(node("a0"), node("a1")); 204 TestMatch Match = matchCode(Code, Matcher); 205 EXPECT_THAT_EXPECTED(select(R, Match), HasValue(", /* comment */ ")); 206 } 207 208 TEST(RangeSelectorTest, BetweenOpParsed) { 209 StringRef Code = R"cc( 210 int f(int x, int y, int z) { return 3; } 211 int g() { return f(3, /* comment */ 7 /* comment */, 9); } 212 )cc"; 213 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 214 hasArgument(1, expr().bind("a1"))); 215 auto R = parseRangeSelector(R"rs(between(node("a0"), node("a1")))rs"); 216 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 217 TestMatch Match = matchCode(Code, Matcher); 218 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue(", /* comment */ ")); 219 } 220 221 // Node-id specific version. 222 TEST(RangeSelectorTest, EncloseOpNodes) { 223 StringRef Code = R"cc( 224 int f(int x, int y, int z) { return 3; } 225 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 226 )cc"; 227 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 228 hasArgument(1, expr().bind("a1"))); 229 RangeSelector R = encloseNodes("a0", "a1"); 230 TestMatch Match = matchCode(Code, Matcher); 231 EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7")); 232 } 233 234 TEST(RangeSelectorTest, EncloseOpGeneral) { 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 RangeSelector R = enclose(node("a0"), node("a1")); 242 TestMatch Match = matchCode(Code, Matcher); 243 EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7")); 244 } 245 246 TEST(RangeSelectorTest, EncloseOpNodesParsed) { 247 StringRef Code = R"cc( 248 int f(int x, int y, int z) { return 3; } 249 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 250 )cc"; 251 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 252 hasArgument(1, expr().bind("a1"))); 253 auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs"); 254 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 255 TestMatch Match = matchCode(Code, Matcher); 256 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7")); 257 } 258 259 TEST(RangeSelectorTest, EncloseOpGeneralParsed) { 260 StringRef Code = R"cc( 261 int f(int x, int y, int z) { return 3; } 262 int g() { return f(/* comment */ 3, 7 /* comment */, 9); } 263 )cc"; 264 auto Matcher = callExpr(hasArgument(0, expr().bind("a0")), 265 hasArgument(1, expr().bind("a1"))); 266 auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs"); 267 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 268 TestMatch Match = matchCode(Code, Matcher); 269 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7")); 270 } 271 272 TEST(RangeSelectorTest, NodeOpStatement) { 273 StringRef Code = "int f() { return 3; }"; 274 TestMatch Match = matchCode(Code, returnStmt().bind("id")); 275 EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("return 3;")); 276 } 277 278 TEST(RangeSelectorTest, NodeOpExpression) { 279 StringRef Code = "int f() { return 3; }"; 280 TestMatch Match = matchCode(Code, expr().bind("id")); 281 EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("3")); 282 } 283 284 TEST(RangeSelectorTest, StatementOp) { 285 StringRef Code = "int f() { return 3; }"; 286 TestMatch Match = matchCode(Code, expr().bind("id")); 287 RangeSelector R = statement("id"); 288 EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3;")); 289 } 290 291 TEST(RangeSelectorTest, StatementOpParsed) { 292 StringRef Code = "int f() { return 3; }"; 293 TestMatch Match = matchCode(Code, expr().bind("id")); 294 auto R = parseRangeSelector(R"rs(statement("id"))rs"); 295 ASSERT_THAT_EXPECTED(R, llvm::Succeeded()); 296 EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3;")); 297 } 298 299 TEST(RangeSelectorTest, MemberOp) { 300 StringRef Code = R"cc( 301 struct S { 302 int member; 303 }; 304 int g() { 305 S s; 306 return s.member; 307 } 308 )cc"; 309 const char *ID = "id"; 310 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 311 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member")); 312 } 313 314 // Tests that member does not select any qualifiers on the member name. 315 TEST(RangeSelectorTest, MemberOpQualified) { 316 StringRef Code = R"cc( 317 struct S { 318 int member; 319 }; 320 struct T : public S { 321 int field; 322 }; 323 int g() { 324 T t; 325 return t.S::member; 326 } 327 )cc"; 328 const char *ID = "id"; 329 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 330 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member")); 331 } 332 333 TEST(RangeSelectorTest, MemberOpTemplate) { 334 StringRef Code = R"cc( 335 struct S { 336 template <typename T> T foo(T t); 337 }; 338 int f(int x) { 339 S s; 340 return s.template foo<int>(3); 341 } 342 )cc"; 343 344 const char *ID = "id"; 345 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 346 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo")); 347 } 348 349 TEST(RangeSelectorTest, MemberOpOperator) { 350 StringRef Code = R"cc( 351 struct S { 352 int operator*(); 353 }; 354 int f(int x) { 355 S s; 356 return s.operator *(); 357 } 358 )cc"; 359 360 const char *ID = "id"; 361 TestMatch Match = matchCode(Code, memberExpr().bind(ID)); 362 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *")); 363 } 364 365 TEST(RangeSelectorTest, NameOpNamedDecl) { 366 StringRef Code = R"cc( 367 int myfun() { 368 return 3; 369 } 370 )cc"; 371 const char *ID = "id"; 372 TestMatch Match = matchCode(Code, functionDecl().bind(ID)); 373 EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("myfun")); 374 } 375 376 TEST(RangeSelectorTest, NameOpDeclRef) { 377 StringRef Code = R"cc( 378 int foo(int x) { 379 return x; 380 } 381 int g(int x) { return foo(x) * x; } 382 )cc"; 383 const char *Ref = "ref"; 384 TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref)); 385 EXPECT_THAT_EXPECTED(select(name(Ref), Match), HasValue("foo")); 386 } 387 388 TEST(RangeSelectorTest, NameOpCtorInitializer) { 389 StringRef Code = R"cc( 390 class C { 391 public: 392 C() : field(3) {} 393 int field; 394 }; 395 )cc"; 396 const char *Init = "init"; 397 TestMatch Match = matchCode(Code, cxxCtorInitializer().bind(Init)); 398 EXPECT_THAT_EXPECTED(select(name(Init), Match), HasValue("field")); 399 } 400 401 TEST(RangeSelectorTest, NameOpErrors) { 402 EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")), 403 Failed<StringError>(withUnboundNodeMessage())); 404 EXPECT_THAT_EXPECTED(selectFromAssorted(name("stmt")), 405 Failed<StringError>(withTypeErrorMessage("stmt"))); 406 } 407 408 TEST(RangeSelectorTest, NameOpDeclRefError) { 409 StringRef Code = R"cc( 410 struct S { 411 int operator*(); 412 }; 413 int f(int x) { 414 S s; 415 return *s + x; 416 } 417 )cc"; 418 const char *Ref = "ref"; 419 TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref)); 420 EXPECT_THAT_EXPECTED( 421 name(Ref)(Match.Result), 422 Failed<StringError>(testing::Property( 423 &StringError::getMessage, 424 AllOf(HasSubstr(Ref), HasSubstr("requires property 'identifier'"))))); 425 } 426 427 TEST(RangeSelectorTest, CallArgsOp) { 428 const StringRef Code = R"cc( 429 struct C { 430 int bar(int, int); 431 }; 432 int f() { 433 C x; 434 return x.bar(3, 4); 435 } 436 )cc"; 437 const char *ID = "id"; 438 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 439 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4")); 440 } 441 442 TEST(RangeSelectorTest, CallArgsOpNoArgs) { 443 const StringRef Code = R"cc( 444 struct C { 445 int bar(); 446 }; 447 int f() { 448 C x; 449 return x.bar(); 450 } 451 )cc"; 452 const char *ID = "id"; 453 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 454 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("")); 455 } 456 457 TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) { 458 const StringRef Code = R"cc( 459 struct C { 460 int bar(); 461 }; 462 int f() { 463 C x; 464 return x.bar(/*empty*/); 465 } 466 )cc"; 467 const char *ID = "id"; 468 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 469 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("/*empty*/")); 470 } 471 472 // Tests that arguments are extracted correctly when a temporary (with parens) 473 // is used. 474 TEST(RangeSelectorTest, CallArgsOpWithParens) { 475 const StringRef Code = R"cc( 476 struct C { 477 int bar(int, int) { return 3; } 478 }; 479 int f() { 480 C x; 481 return C().bar(3, 4); 482 } 483 )cc"; 484 const char *ID = "id"; 485 TestMatch Match = 486 matchCode(Code, callExpr(callee(functionDecl(hasName("bar")))).bind(ID)); 487 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4")); 488 } 489 490 TEST(RangeSelectorTest, CallArgsOpLeadingComments) { 491 const StringRef Code = R"cc( 492 struct C { 493 int bar(int, int) { return 3; } 494 }; 495 int f() { 496 C x; 497 return x.bar(/*leading*/ 3, 4); 498 } 499 )cc"; 500 const char *ID = "id"; 501 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 502 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), 503 HasValue("/*leading*/ 3, 4")); 504 } 505 506 TEST(RangeSelectorTest, CallArgsOpTrailingComments) { 507 const StringRef Code = R"cc( 508 struct C { 509 int bar(int, int) { return 3; } 510 }; 511 int f() { 512 C x; 513 return x.bar(3 /*trailing*/, 4); 514 } 515 )cc"; 516 const char *ID = "id"; 517 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 518 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), 519 HasValue("3 /*trailing*/, 4")); 520 } 521 522 TEST(RangeSelectorTest, CallArgsOpEolComments) { 523 const StringRef Code = R"cc( 524 struct C { 525 int bar(int, int) { return 3; } 526 }; 527 int f() { 528 C x; 529 return x.bar( // Header 530 1, // foo 531 2 // bar 532 ); 533 } 534 )cc"; 535 const char *ID = "id"; 536 TestMatch Match = matchCode(Code, callExpr().bind(ID)); 537 std::string ExpectedString = R"( // Header 538 1, // foo 539 2 // bar 540 )"; 541 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString)); 542 } 543 544 TEST(RangeSelectorTest, CallArgsErrors) { 545 EXPECT_THAT_EXPECTED(selectFromTrivial(callArgs("unbound_id")), 546 Failed<StringError>(withUnboundNodeMessage())); 547 EXPECT_THAT_EXPECTED(selectFromAssorted(callArgs("stmt")), 548 Failed<StringError>(withTypeErrorMessage("stmt"))); 549 } 550 551 TEST(RangeSelectorTest, StatementsOp) { 552 StringRef Code = R"cc( 553 void g(); 554 void f() { /* comment */ g(); /* comment */ g(); /* comment */ } 555 )cc"; 556 const char *ID = "id"; 557 TestMatch Match = matchCode(Code, compoundStmt().bind(ID)); 558 EXPECT_THAT_EXPECTED( 559 select(statements(ID), Match), 560 HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ ")); 561 } 562 563 TEST(RangeSelectorTest, StatementsOpEmptyList) { 564 StringRef Code = "void f() {}"; 565 const char *ID = "id"; 566 TestMatch Match = matchCode(Code, compoundStmt().bind(ID)); 567 EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue("")); 568 } 569 570 TEST(RangeSelectorTest, StatementsOpErrors) { 571 EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")), 572 Failed<StringError>(withUnboundNodeMessage())); 573 EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")), 574 Failed<StringError>(withTypeErrorMessage("decl"))); 575 } 576 577 TEST(RangeSelectorTest, ElementsOp) { 578 StringRef Code = R"cc( 579 void f() { 580 int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */}; 581 (void)v; 582 } 583 )cc"; 584 const char *ID = "id"; 585 TestMatch Match = matchCode(Code, initListExpr().bind(ID)); 586 EXPECT_THAT_EXPECTED( 587 select(initListElements(ID), Match), 588 HasValue("/* comment */ 3, /* comment*/ 4 /* comment */")); 589 } 590 591 TEST(RangeSelectorTest, ElementsOpEmptyList) { 592 StringRef Code = R"cc( 593 void f() { 594 int v[] = {}; 595 (void)v; 596 } 597 )cc"; 598 const char *ID = "id"; 599 TestMatch Match = matchCode(Code, initListExpr().bind(ID)); 600 EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue("")); 601 } 602 603 TEST(RangeSelectorTest, ElementsOpErrors) { 604 EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")), 605 Failed<StringError>(withUnboundNodeMessage())); 606 EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")), 607 Failed<StringError>(withTypeErrorMessage("stmt"))); 608 } 609 610 TEST(RangeSelectorTest, ElseBranchOpSingleStatement) { 611 StringRef Code = R"cc( 612 int f() { 613 int x = 0; 614 if (true) x = 3; 615 else x = 4; 616 return x + 5; 617 } 618 )cc"; 619 const char *ID = "id"; 620 TestMatch Match = matchCode(Code, ifStmt().bind(ID)); 621 EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;")); 622 } 623 624 TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) { 625 StringRef Code = R"cc( 626 int f() { 627 int x = 0; 628 if (true) x = 3; 629 else { x = 4; } 630 return x + 5; 631 } 632 )cc"; 633 const char *ID = "id"; 634 TestMatch Match = matchCode(Code, ifStmt().bind(ID)); 635 EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), 636 HasValue("else { x = 4; }")); 637 } 638 639 // Tests case where the matched node is the complete expanded text. 640 TEST(RangeSelectorTest, ExpansionOp) { 641 StringRef Code = R"cc( 642 #define BADDECL(E) int bad(int x) { return E; } 643 BADDECL(x * x) 644 )cc"; 645 646 const char *Fun = "Fun"; 647 TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun)); 648 EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match), 649 HasValue("BADDECL(x * x)")); 650 } 651 652 // Tests case where the matched node is (only) part of the expanded text. 653 TEST(RangeSelectorTest, ExpansionOpPartial) { 654 StringRef Code = R"cc( 655 #define BADDECL(E) int bad(int x) { return E; } 656 BADDECL(x * x) 657 )cc"; 658 659 const char *Ret = "Ret"; 660 TestMatch Match = matchCode(Code, returnStmt().bind(Ret)); 661 EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match), 662 HasValue("BADDECL(x * x)")); 663 } 664 665 TEST(RangeSelectorTest, IfBoundOpBound) { 666 StringRef Code = R"cc( 667 int f() { 668 return 3 + 5; 669 } 670 )cc"; 671 const char *ID = "id", *Op = "op"; 672 TestMatch Match = 673 matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op)); 674 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match), 675 HasValue("3")); 676 } 677 678 TEST(RangeSelectorTest, IfBoundOpUnbound) { 679 StringRef Code = R"cc( 680 int f() { 681 return 3 + 5; 682 } 683 )cc"; 684 const char *ID = "id", *Op = "op"; 685 TestMatch Match = matchCode(Code, binaryOperator().bind(Op)); 686 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match), 687 HasValue("3 + 5")); 688 } 689 690 } // namespace 691