brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.9 KiB · 9e83fa1 Raw
953 lines · cpp
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-exception6//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 20using namespace clang;21using namespace transformer;22using namespace ast_matchers;23 24namespace {25using ::llvm::Expected;26using ::llvm::Failed;27using ::llvm::HasValue;28using ::llvm::StringError;29using ::testing::AllOf;30using ::testing::HasSubstr;31 32using MatchResult = MatchFinder::MatchResult;33 34struct TestMatch {35  // The AST unit from which `result` is built. We bundle it because it backs36  // the result. Users are not expected to access it.37  std::unique_ptr<clang::ASTUnit> ASTUnit;38  // The result to use in the test. References `ast_unit`.39  MatchResult Result;40};41 42template <typename M> TestMatch matchCode(StringRef Code, M Matcher) {43  auto ASTUnit = tooling::buildASTFromCode(Code);44  assert(ASTUnit != nullptr && "AST construction failed");45 46  ASTContext &Context = ASTUnit->getASTContext();47  assert(!Context.getDiagnostics().hasErrorOccurred() && "Compilation error");48 49  TraversalKindScope RAII(Context, TK_AsIs);50  auto Matches = ast_matchers::match(Matcher, Context);51  // We expect a single, exact match.52  assert(Matches.size() != 0 && "no matches found");53  assert(Matches.size() == 1 && "too many matches");54 55  return TestMatch{std::move(ASTUnit), MatchResult(Matches[0], &Context)};56}57 58// Applies \p Selector to \p Match and, on success, returns the selected source.59Expected<StringRef> select(RangeSelector Selector, const TestMatch &Match) {60  Expected<CharSourceRange> Range = Selector(Match.Result);61  if (!Range)62    return Range.takeError();63  return tooling::getText(*Range, *Match.Result.Context);64}65 66// Applies \p Selector to a trivial match with only a single bound node with id67// "bound_node_id".  For use in testing unbound-node errors.68Expected<CharSourceRange> selectFromTrivial(const RangeSelector &Selector) {69  // We need to bind the result to something, or the match will fail. Use a70  // binding that is not used in the unbound node tests.71  TestMatch Match =72      matchCode("static int x = 0;", varDecl().bind("bound_node_id"));73  return Selector(Match.Result);74}75 76// Matches the message expected for unbound-node failures.77testing::Matcher<StringError> withUnboundNodeMessage() {78  return testing::Property(79      &StringError::getMessage,80      AllOf(HasSubstr("unbound_id"), HasSubstr("not bound")));81}82 83// Applies \p Selector to code containing assorted node types, where the match84// binds each one: a statement ("stmt"), a (non-member) ctor-initializer85// ("init"), an expression ("expr") and a (nameless) declaration ("decl").  Used86// to test failures caused by applying selectors to nodes of the wrong type.87Expected<CharSourceRange> selectFromAssorted(RangeSelector Selector) {88  StringRef Code = R"cc(89      struct A {};90      class F : public A {91       public:92        F(int) {}93      };94      void g() { F f(1); }95    )cc";96 97  auto Matcher =98      compoundStmt(99          hasDescendant(100              cxxConstructExpr(101                  hasDeclaration(102                      decl(hasDescendant(cxxCtorInitializer(isBaseInitializer())103                                             .bind("init")))104                          .bind("decl")))105                  .bind("expr")))106          .bind("stmt");107 108  return Selector(matchCode(Code, Matcher).Result);109}110 111// Matches the message expected for type-error failures.112testing::Matcher<StringError> withTypeErrorMessage(const std::string &NodeID) {113  return testing::Property(114      &StringError::getMessage,115      AllOf(HasSubstr(NodeID), HasSubstr("mismatched type")));116}117 118TEST(RangeSelectorTest, UnboundNode) {119  EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")),120                       Failed<StringError>(withUnboundNodeMessage()));121}122 123MATCHER_P(EqualsCharSourceRange, Range, "") {124  return Range.getAsRange() == arg.getAsRange() &&125         Range.isTokenRange() == arg.isTokenRange();126}127 128// FIXME: here and elsewhere: use llvm::Annotations library to explicitly mark129// points and ranges of interest, enabling more readable tests.130TEST(RangeSelectorTest, BeforeOp) {131  StringRef Code = R"cc(132    int f(int x, int y, int z) { return 3; }133    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }134  )cc";135  StringRef CallID = "call";136  ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID);137  RangeSelector R = before(node(CallID.str()));138 139  TestMatch Match = matchCode(Code, M);140  const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID);141  assert(E != nullptr);142  auto ExprBegin = E->getSourceRange().getBegin();143  EXPECT_THAT_EXPECTED(144      R(Match.Result),145      HasValue(EqualsCharSourceRange(146          CharSourceRange::getCharRange(ExprBegin, ExprBegin))));147}148 149TEST(RangeSelectorTest, BeforeOpParsed) {150  StringRef Code = R"cc(151    int f(int x, int y, int z) { return 3; }152    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }153  )cc";154  StringRef CallID = "call";155  ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID);156  auto R = parseRangeSelector(R"rs(before(node("call")))rs");157  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());158 159  TestMatch Match = matchCode(Code, M);160  const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID);161  assert(E != nullptr);162  auto ExprBegin = E->getSourceRange().getBegin();163  EXPECT_THAT_EXPECTED(164      (*R)(Match.Result),165      HasValue(EqualsCharSourceRange(166          CharSourceRange::getCharRange(ExprBegin, ExprBegin))));167}168 169TEST(RangeSelectorTest, AfterOp) {170  StringRef Code = R"cc(171    int f(int x, int y, int z) { return 3; }172    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }173  )cc";174  StringRef Call = "call";175  TestMatch Match = matchCode(Code, callExpr().bind(Call));176  const auto* E = Match.Result.Nodes.getNodeAs<Expr>(Call);177  assert(E != nullptr);178  const SourceRange Range = E->getSourceRange();179  // The end token, a right paren, is one character wide, so advance by one,180  // bringing us to the semicolon.181  const SourceLocation SemiLoc = Range.getEnd().getLocWithOffset(1);182  const auto ExpectedAfter = CharSourceRange::getCharRange(SemiLoc, SemiLoc);183 184  // Test with a char range.185  auto CharRange = CharSourceRange::getCharRange(Range.getBegin(), SemiLoc);186  EXPECT_THAT_EXPECTED(after(charRange(CharRange))(Match.Result),187                       HasValue(EqualsCharSourceRange(ExpectedAfter)));188 189  // Test with a token range.190  auto TokenRange = CharSourceRange::getTokenRange(Range);191  EXPECT_THAT_EXPECTED(after(charRange(TokenRange))(Match.Result),192                       HasValue(EqualsCharSourceRange(ExpectedAfter)));193}194 195// Gets the spelling location `Length` characters after the start of AST node196// `Id`.197static SourceLocation getSpellingLocAfter(const MatchResult &Result,198                                          StringRef Id, int Length) {199  const auto *E = Result.Nodes.getNodeAs<Expr>(Id);200  assert(E != nullptr);201  return Result.SourceManager->getSpellingLoc(E->getBeginLoc())202      .getLocWithOffset(Length);203}204 205// Test with a range that is the entire macro arg, but does not end the206// expansion itself.207TEST(RangeSelectorTest, AfterOpInMacroArg) {208  StringRef Code = R"cc(209#define ISNULL(x) x == nullptr210    bool g() { int* y; return ISNULL(y); }211  )cc";212 213  TestMatch Match =214      matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));215  int YVarLen = 1;216  SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);217  CharSourceRange Expected = CharSourceRange::getCharRange(After, After);218  EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),219                       HasValue(EqualsCharSourceRange(Expected)));220}221 222// Test with a range that is the entire macro arg and ends the expansion itself.223TEST(RangeSelectorTest, AfterOpInMacroArgEndsExpansion) {224  StringRef Code = R"cc(225#define ISNULL(x) nullptr == x226    bool g() { int* y; return ISNULL(y); }227  )cc";228 229  TestMatch Match =230      matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));231  int YVarLen = 1;232  SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);233  CharSourceRange Expected = CharSourceRange::getCharRange(After, After);234  EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),235                       HasValue(EqualsCharSourceRange(Expected)));236}237 238TEST(RangeSelectorTest, AfterOpInPartOfMacroArg) {239  StringRef Code = R"cc(240#define ISNULL(x) x == nullptr241    int* f(int*);242    bool g() { int* y; return ISNULL(f(y)); }243  )cc";244 245  TestMatch Match =246      matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));247  int YVarLen = 1;248  SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);249  CharSourceRange Expected = CharSourceRange::getCharRange(After, After);250  EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),251                       HasValue(EqualsCharSourceRange(Expected)));252}253 254TEST(RangeSelectorTest, BetweenOp) {255  StringRef Code = R"cc(256    int f(int x, int y, int z) { return 3; }257    int g() { return f(3, /* comment */ 7 /* comment */, 9); }258  )cc";259  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),260                          hasArgument(1, expr().bind("a1")));261  RangeSelector R = between(node("a0"), node("a1"));262  TestMatch Match = matchCode(Code, Matcher);263  EXPECT_THAT_EXPECTED(select(R, Match), HasValue(", /* comment */ "));264}265 266TEST(RangeSelectorTest, BetweenOpParsed) {267  StringRef Code = R"cc(268    int f(int x, int y, int z) { return 3; }269    int g() { return f(3, /* comment */ 7 /* comment */, 9); }270  )cc";271  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),272                          hasArgument(1, expr().bind("a1")));273  auto R = parseRangeSelector(R"rs(between(node("a0"), node("a1")))rs");274  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());275  TestMatch Match = matchCode(Code, Matcher);276  EXPECT_THAT_EXPECTED(select(*R, Match), HasValue(", /* comment */ "));277}278 279// Node-id specific version.280TEST(RangeSelectorTest, EncloseOpNodes) {281  StringRef Code = R"cc(282    int f(int x, int y, int z) { return 3; }283    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }284  )cc";285  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),286                          hasArgument(1, expr().bind("a1")));287  RangeSelector R = encloseNodes("a0", "a1");288  TestMatch Match = matchCode(Code, Matcher);289  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));290}291 292TEST(RangeSelectorTest, EncloseOpGeneral) {293  StringRef Code = R"cc(294    int f(int x, int y, int z) { return 3; }295    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }296  )cc";297  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),298                          hasArgument(1, expr().bind("a1")));299  RangeSelector R = enclose(node("a0"), node("a1"));300  TestMatch Match = matchCode(Code, Matcher);301  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));302}303 304TEST(RangeSelectorTest, EncloseOpNodesParsed) {305  StringRef Code = R"cc(306    int f(int x, int y, int z) { return 3; }307    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }308  )cc";309  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),310                          hasArgument(1, expr().bind("a1")));311  auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs");312  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());313  TestMatch Match = matchCode(Code, Matcher);314  EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));315}316 317TEST(RangeSelectorTest, EncloseOpGeneralParsed) {318  StringRef Code = R"cc(319    int f(int x, int y, int z) { return 3; }320    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }321  )cc";322  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),323                          hasArgument(1, expr().bind("a1")));324  auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs");325  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());326  TestMatch Match = matchCode(Code, Matcher);327  EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));328}329 330TEST(RangeSelectorTest, MergeOp) {331  StringRef Code = R"cc(332    int f(int x, int y, int z) { return 3; }333    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }334  )cc";335  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),336                          hasArgument(1, expr().bind("a1")),337                          hasArgument(2, expr().bind("a2")));338  RangeSelector R = merge(node("a0"), node("a1"));339  TestMatch Match = matchCode(Code, Matcher);340  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));341  // Test the merge of two non-contiguous and out-of-order token-ranges.342  R = merge(node("a2"), node("a0"));343  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7 /* comment */, 9"));344  // Test the merge of a token-range (expr node) with a char-range (before).345  R = merge(node("a1"), before(node("a0")));346  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));347  // Test the merge of two char-ranges.348  R = merge(before(node("a0")), before(node("a1")));349  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, "));350}351 352TEST(RangeSelectorTest, MergeOpParsed) {353  StringRef Code = R"cc(354    int f(int x, int y, int z) { return 3; }355    int g() { return f(/* comment */ 3, 7 /* comment */, 9); }356  )cc";357  auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),358                          hasArgument(1, expr().bind("a1")),359                          hasArgument(2, expr().bind("a2")));360  auto R = parseRangeSelector(R"rs(merge(node("a0"), node("a1")))rs");361  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());362  TestMatch Match = matchCode(Code, Matcher);363  EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));364  R = parseRangeSelector(R"rs(merge(node("a2"), node("a1")))rs");365  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());366  EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("7 /* comment */, 9"));367}368 369TEST(RangeSelectorTest, NodeOpStatement) {370  StringRef Code = "int f() { return 3; }";371  TestMatch Match = matchCode(Code, returnStmt().bind("id"));372  EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("return 3;"));373}374 375TEST(RangeSelectorTest, NodeOpExpression) {376  StringRef Code = "int f() { return 3; }";377  TestMatch Match = matchCode(Code, expr().bind("id"));378  EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("3"));379}380 381TEST(RangeSelectorTest, NodeOpTypeLoc) {382  StringRef Code = "namespace ns {struct Foo{};} ns::Foo a;";383  TestMatch Match =384      matchCode(Code, varDecl(hasTypeLoc(typeLoc().bind("typeloc"))));385  EXPECT_THAT_EXPECTED(select(node("typeloc"), Match), HasValue("ns::Foo"));386}387 388TEST(RangeSelectorTest, StatementOp) {389  StringRef Code = "int f() { return 3; }";390  TestMatch Match = matchCode(Code, expr().bind("id"));391  RangeSelector R = statement("id");392  EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3;"));393}394 395TEST(RangeSelectorTest, StatementOpParsed) {396  StringRef Code = "int f() { return 3; }";397  TestMatch Match = matchCode(Code, expr().bind("id"));398  auto R = parseRangeSelector(R"rs(statement("id"))rs");399  ASSERT_THAT_EXPECTED(R, llvm::Succeeded());400  EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3;"));401}402 403TEST(RangeSelectorTest, MemberOp) {404  StringRef Code = R"cc(405    struct S {406      int member;407    };408    int g() {409      S s;410      return s.member;411    }412  )cc";413  const char *ID = "id";414  TestMatch Match = matchCode(Code, memberExpr().bind(ID));415  EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));416}417 418// Tests that member does not select any qualifiers on the member name.419TEST(RangeSelectorTest, MemberOpQualified) {420  StringRef Code = R"cc(421    struct S {422      int member;423    };424    struct T : public S {425      int field;426    };427    int g() {428      T t;429      return t.S::member;430    }431  )cc";432  const char *ID = "id";433  TestMatch Match = matchCode(Code, memberExpr().bind(ID));434  EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));435}436 437TEST(RangeSelectorTest, MemberOpTemplate) {438  StringRef Code = R"cc(439    struct S {440      template <typename T> T foo(T t);441    };442    int f(int x) {443      S s;444      return s.template foo<int>(3);445    }446  )cc";447 448  const char *ID = "id";449  TestMatch Match = matchCode(Code, memberExpr().bind(ID));450  EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo"));451}452 453TEST(RangeSelectorTest, MemberOpOperator) {454  StringRef Code = R"cc(455    struct S {456      int operator*();457    };458    int f(int x) {459      S s;460      return s.operator *();461    }462  )cc";463 464  const char *ID = "id";465  TestMatch Match = matchCode(Code, memberExpr().bind(ID));466  EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *"));467}468 469TEST(RangeSelectorTest, NameOpNamedDecl) {470  StringRef Code = R"cc(471    int myfun() {472      return 3;473    }474  )cc";475  const char *ID = "id";476  TestMatch Match = matchCode(Code, functionDecl().bind(ID));477  EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("myfun"));478}479 480TEST(RangeSelectorTest, NameOpDeclRef) {481  StringRef Code = R"cc(482    int foo(int x) {483      return x;484    }485    int g(int x) { return foo(x) * x; }486  )cc";487  const char *Ref = "ref";488  TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));489  EXPECT_THAT_EXPECTED(select(name(Ref), Match), HasValue("foo"));490}491 492TEST(RangeSelectorTest, NameOpCtorInitializer) {493  StringRef Code = R"cc(494    class C {495     public:496      C() : field(3) {}497      int field;498    };499  )cc";500  const char *Init = "init";501  TestMatch Match = matchCode(Code, cxxCtorInitializer().bind(Init));502  EXPECT_THAT_EXPECTED(select(name(Init), Match), HasValue("field"));503}504 505TEST(RangeSelectorTest, NameOpTypeLoc) {506  StringRef Code = R"cc(507    namespace ns {508    struct Foo {509      Foo();510      Foo(int);511      Foo(int, int);512    };513    }  // namespace ns514 515    ns::Foo a;516    auto b = ns::Foo(3);517    auto c = ns::Foo(1, 2);518  )cc";519  const char *CtorTy = "ctor_ty";520  // Matches declaration of `a`521  TestMatch MatchA = matchCode(522      Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(CtorTy))));523  EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchA), HasValue("ns::Foo"));524  // Matches call of Foo(int)525  TestMatch MatchB = matchCode(526      Code, cxxFunctionalCastExpr(hasTypeLoc(typeLoc().bind(CtorTy))));527  EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchB), HasValue("ns::Foo"));528  // Matches call of Foo(int, int)529  TestMatch MatchC = matchCode(530      Code, cxxTemporaryObjectExpr(hasTypeLoc(typeLoc().bind(CtorTy))));531  EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchC), HasValue("ns::Foo"));532}533 534TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) {535  StringRef Code = R"cc(536    namespace ns {537    template <typename T>538    struct Foo {};539    }  // namespace ns540 541    ns::Foo<int> a;542  )cc";543  const char *Loc = "tyloc";544  // Matches declaration of `a`.545  TestMatch MatchA =546      matchCode(Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(Loc))));547  EXPECT_THAT_EXPECTED(select(name(Loc), MatchA), HasValue("Foo"));548}549 550TEST(RangeSelectorTest, NameOpErrors) {551  EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")),552                       Failed<StringError>(withUnboundNodeMessage()));553  EXPECT_THAT_EXPECTED(selectFromAssorted(name("stmt")),554                       Failed<StringError>(withTypeErrorMessage("stmt")));555}556 557TEST(RangeSelectorTest, NameOpDeclRefError) {558  StringRef Code = R"cc(559    struct S {560      int operator*();561    };562    int f(int x) {563      S s;564      return *s + x;565    }566  )cc";567  const char *Ref = "ref";568  TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));569  EXPECT_THAT_EXPECTED(570      name(Ref)(Match.Result),571      Failed<StringError>(testing::Property(572          &StringError::getMessage,573          AllOf(HasSubstr(Ref), HasSubstr("requires property 'identifier'")))));574}575 576TEST(RangeSelectorTest, NameOpDeclInMacroArg) {577  StringRef Code = R"cc(578  #define MACRO(name) int name;579  MACRO(x)580  )cc";581  const char *ID = "id";582  TestMatch Match = matchCode(Code, varDecl().bind(ID));583  EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("x"));584}585 586TEST(RangeSelectorTest, NameOpDeclInMacroBodyError) {587  StringRef Code = R"cc(588  #define MACRO int x;589  MACRO590  )cc";591  const char *ID = "id";592  TestMatch Match = matchCode(Code, varDecl().bind(ID));593  EXPECT_THAT_EXPECTED(594      name(ID)(Match.Result),595      Failed<StringError>(testing::Property(596          &StringError::getMessage,597          AllOf(HasSubstr("range selected by name(node id="),598                HasSubstr("' is different from decl name 'x'")))));599}600 601TEST(RangeSelectorTest, CallArgsOp) {602  const StringRef Code = R"cc(603    struct C {604      int bar(int, int);605    };606    int f() {607      C x;608      return x.bar(3, 4);609    }610  )cc";611  const char *ID = "id";612  TestMatch Match = matchCode(Code, callExpr().bind(ID));613  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));614}615 616TEST(RangeSelectorTest, CallArgsOpNoArgs) {617  const StringRef Code = R"cc(618    struct C {619      int bar();620    };621    int f() {622      C x;623      return x.bar();624    }625  )cc";626  const char *ID = "id";627  TestMatch Match = matchCode(Code, callExpr().bind(ID));628  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(""));629}630 631TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) {632  const StringRef Code = R"cc(633    struct C {634      int bar();635    };636    int f() {637      C x;638      return x.bar(/*empty*/);639    }640  )cc";641  const char *ID = "id";642  TestMatch Match = matchCode(Code, callExpr().bind(ID));643  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("/*empty*/"));644}645 646// Tests that arguments are extracted correctly when a temporary (with parens)647// is used.648TEST(RangeSelectorTest, CallArgsOpWithParens) {649  const StringRef Code = R"cc(650    struct C {651      int bar(int, int) { return 3; }652    };653    int f() {654      C x;655      return C().bar(3, 4);656    }657  )cc";658  const char *ID = "id";659  TestMatch Match =660      matchCode(Code, callExpr(callee(functionDecl(hasName("bar")))).bind(ID));661  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));662}663 664TEST(RangeSelectorTest, CallArgsOpLeadingComments) {665  const StringRef Code = R"cc(666    struct C {667      int bar(int, int) { return 3; }668    };669    int f() {670      C x;671      return x.bar(/*leading*/ 3, 4);672    }673  )cc";674  const char *ID = "id";675  TestMatch Match = matchCode(Code, callExpr().bind(ID));676  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),677                       HasValue("/*leading*/ 3, 4"));678}679 680TEST(RangeSelectorTest, CallArgsOpTrailingComments) {681  const StringRef Code = R"cc(682    struct C {683      int bar(int, int) { return 3; }684    };685    int f() {686      C x;687      return x.bar(3 /*trailing*/, 4);688    }689  )cc";690  const char *ID = "id";691  TestMatch Match = matchCode(Code, callExpr().bind(ID));692  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),693                       HasValue("3 /*trailing*/, 4"));694}695 696TEST(RangeSelectorTest, CallArgsOpEolComments) {697  const StringRef Code = R"cc(698    struct C {699      int bar(int, int) { return 3; }700    };701    int f() {702      C x;703      return x.bar(  // Header704          1,           // foo705          2            // bar706      );707    }708  )cc";709  const char *ID = "id";710  TestMatch Match = matchCode(Code, callExpr().bind(ID));711  std::string ExpectedString = R"(  // Header712          1,           // foo713          2            // bar714      )";715  EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString));716}717 718TEST(RangeSelectorTest, CallArgsErrors) {719  EXPECT_THAT_EXPECTED(selectFromTrivial(callArgs("unbound_id")),720                       Failed<StringError>(withUnboundNodeMessage()));721  EXPECT_THAT_EXPECTED(selectFromAssorted(callArgs("stmt")),722                       Failed<StringError>(withTypeErrorMessage("stmt")));723}724 725TEST(RangeSelectorTest, ConstructExprArgs) {726  const StringRef Code = R"cc(727    struct C {728      C(int, int);729    };730    C f() {731      return C(1, 2);732    }733  )cc";734  const char *ID = "id";735  TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));736  EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));737}738 739TEST(RangeSelectorTest, ConstructExprBracedArgs) {740  const StringRef Code = R"cc(741    struct C {742      C(int, int);743    };744    C f() {745      return {1, 2};746    }747  )cc";748  const char *ID = "id";749  TestMatch Match = matchCode(Code, cxxConstructExpr().bind(ID));750  EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));751}752 753TEST(RangeSelectorTest, ConstructExprNoArgs) {754  const StringRef Code = R"cc(755    struct C {756      C();757    };758    C f() {759      return C();760    }761  )cc";762  const char *ID = "id";763  TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));764  EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue(""));765}766 767TEST(RangeSelectorTest, ConstructExprArgsDirectInitialization) {768  const StringRef Code = R"cc(769    struct C {770      C(int, int);771    };772    void f() {773      C c(1, 2);774    }775  )cc";776  const char *ID = "id";777  TestMatch Match = matchCode(Code, cxxConstructExpr().bind(ID));778  EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));779}780 781TEST(RangeSelectorTest, ConstructExprArgsDirectBraceInitialization) {782  const StringRef Code = R"cc(783    struct C {784      C(int, int);785    };786    void f() {787      C c{1, 2};788    }789  )cc";790  const char *ID = "id";791  TestMatch Match = matchCode(Code, cxxConstructExpr().bind(ID));792  EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));793}794 795TEST(RangeSelectorTest, ConstructExprArgsImplicitConstruction) {796  const StringRef Code = R"cc(797    struct C {798      C(int, int = 42);799    };800    void sink(C);801    void f() {802      sink(1);803    }804  )cc";805  const char *ID = "id";806  TestMatch Match = matchCode(807      Code,808      cxxConstructExpr(ignoringElidableConstructorCall(cxxConstructExpr()))809          .bind(ID));810  EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1"));811}812 813TEST(RangeSelectorTest, StatementsOp) {814  StringRef Code = R"cc(815    void g();816    void f() { /* comment */ g(); /* comment */ g(); /* comment */ }817  )cc";818  const char *ID = "id";819  TestMatch Match = matchCode(Code, compoundStmt().bind(ID));820  EXPECT_THAT_EXPECTED(821      select(statements(ID), Match),822      HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ "));823}824 825TEST(RangeSelectorTest, StatementsOpEmptyList) {826  StringRef Code = "void f() {}";827  const char *ID = "id";828  TestMatch Match = matchCode(Code, compoundStmt().bind(ID));829  EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue(""));830}831 832TEST(RangeSelectorTest, StatementsOpErrors) {833  EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")),834                       Failed<StringError>(withUnboundNodeMessage()));835  EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")),836                       Failed<StringError>(withTypeErrorMessage("decl")));837}838 839TEST(RangeSelectorTest, ElementsOp) {840  StringRef Code = R"cc(841    void f() {842      int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};843      (void)v;844    }845  )cc";846  const char *ID = "id";847  TestMatch Match = matchCode(Code, initListExpr().bind(ID));848  EXPECT_THAT_EXPECTED(849      select(initListElements(ID), Match),850      HasValue("/* comment */ 3, /* comment*/ 4 /* comment */"));851}852 853TEST(RangeSelectorTest, ElementsOpEmptyList) {854  StringRef Code = R"cc(855    void f() {856      int v[] = {};857      (void)v;858    }859  )cc";860  const char *ID = "id";861  TestMatch Match = matchCode(Code, initListExpr().bind(ID));862  EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue(""));863}864 865TEST(RangeSelectorTest, ElementsOpErrors) {866  EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")),867                       Failed<StringError>(withUnboundNodeMessage()));868  EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")),869                       Failed<StringError>(withTypeErrorMessage("stmt")));870}871 872TEST(RangeSelectorTest, ElseBranchOpSingleStatement) {873  StringRef Code = R"cc(874    int f() {875      int x = 0;876      if (true) x = 3;877      else x = 4;878      return x + 5;879    }880  )cc";881  const char *ID = "id";882  TestMatch Match = matchCode(Code, ifStmt().bind(ID));883  EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;"));884}885 886TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) {887  StringRef Code = R"cc(888    int f() {889      int x = 0;890      if (true) x = 3;891      else { x = 4; }892      return x + 5;893    }894  )cc";895  const char *ID = "id";896  TestMatch Match = matchCode(Code, ifStmt().bind(ID));897  EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match),898                       HasValue("else { x = 4; }"));899}900 901// Tests case where the matched node is the complete expanded text.902TEST(RangeSelectorTest, ExpansionOp) {903  StringRef Code = R"cc(904#define BADDECL(E) int bad(int x) { return E; }905    BADDECL(x * x)906  )cc";907 908  const char *Fun = "Fun";909  TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun));910  EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match),911                       HasValue("BADDECL(x * x)"));912}913 914// Tests case where the matched node is (only) part of the expanded text.915TEST(RangeSelectorTest, ExpansionOpPartial) {916  StringRef Code = R"cc(917#define BADDECL(E) int bad(int x) { return E; }918    BADDECL(x * x)919  )cc";920 921  const char *Ret = "Ret";922  TestMatch Match = matchCode(Code, returnStmt().bind(Ret));923  EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match),924                       HasValue("BADDECL(x * x)"));925}926 927TEST(RangeSelectorTest, IfBoundOpBound) {928  StringRef Code = R"cc(929    int f() {930      return 3 + 5;931    }932  )cc";933  const char *ID = "id", *Op = "op";934  TestMatch Match =935      matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));936  EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),937                       HasValue("3"));938}939 940TEST(RangeSelectorTest, IfBoundOpUnbound) {941  StringRef Code = R"cc(942    int f() {943      return 3 + 5;944    }945  )cc";946  const char *ID = "id", *Op = "op";947  TestMatch Match = matchCode(Code, binaryOperator().bind(Op));948  EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),949                       HasValue("3 + 5"));950}951 952} // namespace953