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