xref: /llvm-project/clang/unittests/Tooling/RangeSelectorTest.cpp (revision 6b931ab516616127ce4cd5a0ad5e37d5a1d1696b)
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 
32 using MatchResult = MatchFinder::MatchResult;
33 
34 struct TestMatch {
35   // The AST unit from which `result` is built. We bundle it because it backs
36   // 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 
matchCode(StringRef Code,M Matcher)42 template <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.
select(RangeSelector Selector,const TestMatch & Match)59 Expected<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 id
67 // "bound_node_id".  For use in testing unbound-node errors.
selectFromTrivial(const RangeSelector & Selector)68 Expected<CharSourceRange> selectFromTrivial(const RangeSelector &Selector) {
69   // We need to bind the result to something, or the match will fail. Use a
70   // 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.
withUnboundNodeMessage()77 testing::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 match
84 // binds each one: a statement ("stmt"), a (non-member) ctor-initializer
85 // ("init"), an expression ("expr") and a (nameless) declaration ("decl").  Used
86 // to test failures caused by applying selectors to nodes of the wrong type.
selectFromAssorted(RangeSelector Selector)87 Expected<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.
withTypeErrorMessage(const std::string & NodeID)112 testing::Matcher<StringError> withTypeErrorMessage(const std::string &NodeID) {
113   return testing::Property(
114       &StringError::getMessage,
115       AllOf(HasSubstr(NodeID), HasSubstr("mismatched type")));
116 }
117 
TEST(RangeSelectorTest,UnboundNode)118 TEST(RangeSelectorTest, UnboundNode) {
119   EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")),
120                        Failed<StringError>(withUnboundNodeMessage()));
121 }
122 
123 MATCHER_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 mark
129 // points and ranges of interest, enabling more readable tests.
TEST(RangeSelectorTest,BeforeOp)130 TEST(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 
TEST(RangeSelectorTest,BeforeOpParsed)149 TEST(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 
TEST(RangeSelectorTest,AfterOp)169 TEST(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 node
196 // `Id`.
getSpellingLocAfter(const MatchResult & Result,StringRef Id,int Length)197 static 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 the
206 // expansion itself.
TEST(RangeSelectorTest,AfterOpInMacroArg)207 TEST(RangeSelectorTest, AfterOpInMacroArg) {
208   StringRef Code = R"cc(
209 #define ISNULL(x) x == nullptr
210     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.
TEST(RangeSelectorTest,AfterOpInMacroArgEndsExpansion)223 TEST(RangeSelectorTest, AfterOpInMacroArgEndsExpansion) {
224   StringRef Code = R"cc(
225 #define ISNULL(x) nullptr == x
226     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 
TEST(RangeSelectorTest,AfterOpInPartOfMacroArg)238 TEST(RangeSelectorTest, AfterOpInPartOfMacroArg) {
239   StringRef Code = R"cc(
240 #define ISNULL(x) x == nullptr
241     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 
TEST(RangeSelectorTest,BetweenOp)254 TEST(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 
TEST(RangeSelectorTest,BetweenOpParsed)266 TEST(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.
TEST(RangeSelectorTest,EncloseOpNodes)280 TEST(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 
TEST(RangeSelectorTest,EncloseOpGeneral)292 TEST(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 
TEST(RangeSelectorTest,EncloseOpNodesParsed)304 TEST(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 
TEST(RangeSelectorTest,EncloseOpGeneralParsed)317 TEST(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 
TEST(RangeSelectorTest,NodeOpStatement)330 TEST(RangeSelectorTest, NodeOpStatement) {
331   StringRef Code = "int f() { return 3; }";
332   TestMatch Match = matchCode(Code, returnStmt().bind("id"));
333   EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("return 3;"));
334 }
335 
TEST(RangeSelectorTest,NodeOpExpression)336 TEST(RangeSelectorTest, NodeOpExpression) {
337   StringRef Code = "int f() { return 3; }";
338   TestMatch Match = matchCode(Code, expr().bind("id"));
339   EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("3"));
340 }
341 
TEST(RangeSelectorTest,StatementOp)342 TEST(RangeSelectorTest, StatementOp) {
343   StringRef Code = "int f() { return 3; }";
344   TestMatch Match = matchCode(Code, expr().bind("id"));
345   RangeSelector R = statement("id");
346   EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3;"));
347 }
348 
TEST(RangeSelectorTest,StatementOpParsed)349 TEST(RangeSelectorTest, StatementOpParsed) {
350   StringRef Code = "int f() { return 3; }";
351   TestMatch Match = matchCode(Code, expr().bind("id"));
352   auto R = parseRangeSelector(R"rs(statement("id"))rs");
353   ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
354   EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3;"));
355 }
356 
TEST(RangeSelectorTest,MemberOp)357 TEST(RangeSelectorTest, MemberOp) {
358   StringRef Code = R"cc(
359     struct S {
360       int member;
361     };
362     int g() {
363       S s;
364       return s.member;
365     }
366   )cc";
367   const char *ID = "id";
368   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
369   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));
370 }
371 
372 // Tests that member does not select any qualifiers on the member name.
TEST(RangeSelectorTest,MemberOpQualified)373 TEST(RangeSelectorTest, MemberOpQualified) {
374   StringRef Code = R"cc(
375     struct S {
376       int member;
377     };
378     struct T : public S {
379       int field;
380     };
381     int g() {
382       T t;
383       return t.S::member;
384     }
385   )cc";
386   const char *ID = "id";
387   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
388   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));
389 }
390 
TEST(RangeSelectorTest,MemberOpTemplate)391 TEST(RangeSelectorTest, MemberOpTemplate) {
392   StringRef Code = R"cc(
393     struct S {
394       template <typename T> T foo(T t);
395     };
396     int f(int x) {
397       S s;
398       return s.template foo<int>(3);
399     }
400   )cc";
401 
402   const char *ID = "id";
403   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
404   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo"));
405 }
406 
TEST(RangeSelectorTest,MemberOpOperator)407 TEST(RangeSelectorTest, MemberOpOperator) {
408   StringRef Code = R"cc(
409     struct S {
410       int operator*();
411     };
412     int f(int x) {
413       S s;
414       return s.operator *();
415     }
416   )cc";
417 
418   const char *ID = "id";
419   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
420   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *"));
421 }
422 
TEST(RangeSelectorTest,NameOpNamedDecl)423 TEST(RangeSelectorTest, NameOpNamedDecl) {
424   StringRef Code = R"cc(
425     int myfun() {
426       return 3;
427     }
428   )cc";
429   const char *ID = "id";
430   TestMatch Match = matchCode(Code, functionDecl().bind(ID));
431   EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("myfun"));
432 }
433 
TEST(RangeSelectorTest,NameOpDeclRef)434 TEST(RangeSelectorTest, NameOpDeclRef) {
435   StringRef Code = R"cc(
436     int foo(int x) {
437       return x;
438     }
439     int g(int x) { return foo(x) * x; }
440   )cc";
441   const char *Ref = "ref";
442   TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));
443   EXPECT_THAT_EXPECTED(select(name(Ref), Match), HasValue("foo"));
444 }
445 
TEST(RangeSelectorTest,NameOpCtorInitializer)446 TEST(RangeSelectorTest, NameOpCtorInitializer) {
447   StringRef Code = R"cc(
448     class C {
449      public:
450       C() : field(3) {}
451       int field;
452     };
453   )cc";
454   const char *Init = "init";
455   TestMatch Match = matchCode(Code, cxxCtorInitializer().bind(Init));
456   EXPECT_THAT_EXPECTED(select(name(Init), Match), HasValue("field"));
457 }
458 
TEST(RangeSelectorTest,NameOpTypeLoc)459 TEST(RangeSelectorTest, NameOpTypeLoc) {
460   StringRef Code = R"cc(
461     namespace ns {
462     struct Foo {
463       Foo();
464       Foo(int);
465       Foo(int, int);
466     };
467     }  // namespace ns
468 
469     ns::Foo a;
470     auto b = ns::Foo(3);
471     auto c = ns::Foo(1, 2);
472   )cc";
473   const char *CtorTy = "ctor_ty";
474   // Matches declaration of `a`
475   TestMatch MatchA = matchCode(
476       Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(CtorTy))));
477   EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchA), HasValue("Foo"));
478   // Matches call of Foo(int)
479   TestMatch MatchB = matchCode(
480       Code, cxxFunctionalCastExpr(hasTypeLoc(typeLoc().bind(CtorTy))));
481   EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchB), HasValue("Foo"));
482   // Matches call of Foo(int, int)
483   TestMatch MatchC = matchCode(
484       Code, cxxTemporaryObjectExpr(hasTypeLoc(typeLoc().bind(CtorTy))));
485   EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchC), HasValue("Foo"));
486 }
487 
TEST(RangeSelectorTest,NameOpTemplateSpecializationTypeLoc)488 TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) {
489   StringRef Code = R"cc(
490     namespace ns {
491     template <typename T>
492     struct Foo {};
493     }  // namespace ns
494 
495     ns::Foo<int> a;
496   )cc";
497   const char *Loc = "tyloc";
498   // Matches declaration of `a`.
499   TestMatch MatchA =
500       matchCode(Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(Loc))));
501   EXPECT_THAT_EXPECTED(select(name(Loc), MatchA), HasValue("Foo"));
502 }
503 
TEST(RangeSelectorTest,NameOpErrors)504 TEST(RangeSelectorTest, NameOpErrors) {
505   EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")),
506                        Failed<StringError>(withUnboundNodeMessage()));
507   EXPECT_THAT_EXPECTED(selectFromAssorted(name("stmt")),
508                        Failed<StringError>(withTypeErrorMessage("stmt")));
509 }
510 
TEST(RangeSelectorTest,NameOpDeclRefError)511 TEST(RangeSelectorTest, NameOpDeclRefError) {
512   StringRef Code = R"cc(
513     struct S {
514       int operator*();
515     };
516     int f(int x) {
517       S s;
518       return *s + x;
519     }
520   )cc";
521   const char *Ref = "ref";
522   TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));
523   EXPECT_THAT_EXPECTED(
524       name(Ref)(Match.Result),
525       Failed<StringError>(testing::Property(
526           &StringError::getMessage,
527           AllOf(HasSubstr(Ref), HasSubstr("requires property 'identifier'")))));
528 }
529 
TEST(RangeSelectorTest,CallArgsOp)530 TEST(RangeSelectorTest, CallArgsOp) {
531   const StringRef Code = R"cc(
532     struct C {
533       int bar(int, int);
534     };
535     int f() {
536       C x;
537       return x.bar(3, 4);
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("3, 4"));
543 }
544 
TEST(RangeSelectorTest,CallArgsOpNoArgs)545 TEST(RangeSelectorTest, CallArgsOpNoArgs) {
546   const StringRef Code = R"cc(
547     struct C {
548       int bar();
549     };
550     int f() {
551       C x;
552       return x.bar();
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(""));
558 }
559 
TEST(RangeSelectorTest,CallArgsOpNoArgsWithComments)560 TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) {
561   const StringRef Code = R"cc(
562     struct C {
563       int bar();
564     };
565     int f() {
566       C x;
567       return x.bar(/*empty*/);
568     }
569   )cc";
570   const char *ID = "id";
571   TestMatch Match = matchCode(Code, callExpr().bind(ID));
572   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("/*empty*/"));
573 }
574 
575 // Tests that arguments are extracted correctly when a temporary (with parens)
576 // is used.
TEST(RangeSelectorTest,CallArgsOpWithParens)577 TEST(RangeSelectorTest, CallArgsOpWithParens) {
578   const StringRef Code = R"cc(
579     struct C {
580       int bar(int, int) { return 3; }
581     };
582     int f() {
583       C x;
584       return C().bar(3, 4);
585     }
586   )cc";
587   const char *ID = "id";
588   TestMatch Match =
589       matchCode(Code, callExpr(callee(functionDecl(hasName("bar")))).bind(ID));
590   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));
591 }
592 
TEST(RangeSelectorTest,CallArgsOpLeadingComments)593 TEST(RangeSelectorTest, CallArgsOpLeadingComments) {
594   const StringRef Code = R"cc(
595     struct C {
596       int bar(int, int) { return 3; }
597     };
598     int f() {
599       C x;
600       return x.bar(/*leading*/ 3, 4);
601     }
602   )cc";
603   const char *ID = "id";
604   TestMatch Match = matchCode(Code, callExpr().bind(ID));
605   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),
606                        HasValue("/*leading*/ 3, 4"));
607 }
608 
TEST(RangeSelectorTest,CallArgsOpTrailingComments)609 TEST(RangeSelectorTest, CallArgsOpTrailingComments) {
610   const StringRef Code = R"cc(
611     struct C {
612       int bar(int, int) { return 3; }
613     };
614     int f() {
615       C x;
616       return x.bar(3 /*trailing*/, 4);
617     }
618   )cc";
619   const char *ID = "id";
620   TestMatch Match = matchCode(Code, callExpr().bind(ID));
621   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),
622                        HasValue("3 /*trailing*/, 4"));
623 }
624 
TEST(RangeSelectorTest,CallArgsOpEolComments)625 TEST(RangeSelectorTest, CallArgsOpEolComments) {
626   const StringRef Code = R"cc(
627     struct C {
628       int bar(int, int) { return 3; }
629     };
630     int f() {
631       C x;
632       return x.bar(  // Header
633           1,           // foo
634           2            // bar
635       );
636     }
637   )cc";
638   const char *ID = "id";
639   TestMatch Match = matchCode(Code, callExpr().bind(ID));
640   std::string ExpectedString = R"(  // Header
641           1,           // foo
642           2            // bar
643       )";
644   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString));
645 }
646 
TEST(RangeSelectorTest,CallArgsErrors)647 TEST(RangeSelectorTest, CallArgsErrors) {
648   EXPECT_THAT_EXPECTED(selectFromTrivial(callArgs("unbound_id")),
649                        Failed<StringError>(withUnboundNodeMessage()));
650   EXPECT_THAT_EXPECTED(selectFromAssorted(callArgs("stmt")),
651                        Failed<StringError>(withTypeErrorMessage("stmt")));
652 }
653 
TEST(RangeSelectorTest,ConstructExprArgs)654 TEST(RangeSelectorTest, ConstructExprArgs) {
655   const StringRef Code = R"cc(
656     struct C {
657       C(int, int);
658     };
659     C f() {
660       return C(1, 2);
661     }
662   )cc";
663   const char *ID = "id";
664   TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));
665   EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));
666 }
667 
TEST(RangeSelectorTest,ConstructExprBracedArgs)668 TEST(RangeSelectorTest, ConstructExprBracedArgs) {
669   const StringRef Code = R"cc(
670     struct C {
671       C(int, int);
672     };
673     C f() {
674       return {1, 2};
675     }
676   )cc";
677   const char *ID = "id";
678   TestMatch Match = matchCode(Code, cxxConstructExpr().bind(ID));
679   EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));
680 }
681 
TEST(RangeSelectorTest,ConstructExprNoArgs)682 TEST(RangeSelectorTest, ConstructExprNoArgs) {
683   const StringRef Code = R"cc(
684     struct C {
685       C();
686     };
687     C f() {
688       return C();
689     }
690   )cc";
691   const char *ID = "id";
692   TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));
693   EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue(""));
694 }
695 
TEST(RangeSelectorTest,StatementsOp)696 TEST(RangeSelectorTest, StatementsOp) {
697   StringRef Code = R"cc(
698     void g();
699     void f() { /* comment */ g(); /* comment */ g(); /* comment */ }
700   )cc";
701   const char *ID = "id";
702   TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
703   EXPECT_THAT_EXPECTED(
704       select(statements(ID), Match),
705       HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ "));
706 }
707 
TEST(RangeSelectorTest,StatementsOpEmptyList)708 TEST(RangeSelectorTest, StatementsOpEmptyList) {
709   StringRef Code = "void f() {}";
710   const char *ID = "id";
711   TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
712   EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue(""));
713 }
714 
TEST(RangeSelectorTest,StatementsOpErrors)715 TEST(RangeSelectorTest, StatementsOpErrors) {
716   EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")),
717                        Failed<StringError>(withUnboundNodeMessage()));
718   EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")),
719                        Failed<StringError>(withTypeErrorMessage("decl")));
720 }
721 
TEST(RangeSelectorTest,ElementsOp)722 TEST(RangeSelectorTest, ElementsOp) {
723   StringRef Code = R"cc(
724     void f() {
725       int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};
726       (void)v;
727     }
728   )cc";
729   const char *ID = "id";
730   TestMatch Match = matchCode(Code, initListExpr().bind(ID));
731   EXPECT_THAT_EXPECTED(
732       select(initListElements(ID), Match),
733       HasValue("/* comment */ 3, /* comment*/ 4 /* comment */"));
734 }
735 
TEST(RangeSelectorTest,ElementsOpEmptyList)736 TEST(RangeSelectorTest, ElementsOpEmptyList) {
737   StringRef Code = R"cc(
738     void f() {
739       int v[] = {};
740       (void)v;
741     }
742   )cc";
743   const char *ID = "id";
744   TestMatch Match = matchCode(Code, initListExpr().bind(ID));
745   EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue(""));
746 }
747 
TEST(RangeSelectorTest,ElementsOpErrors)748 TEST(RangeSelectorTest, ElementsOpErrors) {
749   EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")),
750                        Failed<StringError>(withUnboundNodeMessage()));
751   EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")),
752                        Failed<StringError>(withTypeErrorMessage("stmt")));
753 }
754 
TEST(RangeSelectorTest,ElseBranchOpSingleStatement)755 TEST(RangeSelectorTest, ElseBranchOpSingleStatement) {
756   StringRef Code = R"cc(
757     int f() {
758       int x = 0;
759       if (true) x = 3;
760       else x = 4;
761       return x + 5;
762     }
763   )cc";
764   const char *ID = "id";
765   TestMatch Match = matchCode(Code, ifStmt().bind(ID));
766   EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;"));
767 }
768 
TEST(RangeSelectorTest,ElseBranchOpCompoundStatement)769 TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) {
770   StringRef Code = R"cc(
771     int f() {
772       int x = 0;
773       if (true) x = 3;
774       else { x = 4; }
775       return x + 5;
776     }
777   )cc";
778   const char *ID = "id";
779   TestMatch Match = matchCode(Code, ifStmt().bind(ID));
780   EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match),
781                        HasValue("else { x = 4; }"));
782 }
783 
784 // Tests case where the matched node is the complete expanded text.
TEST(RangeSelectorTest,ExpansionOp)785 TEST(RangeSelectorTest, ExpansionOp) {
786   StringRef Code = R"cc(
787 #define BADDECL(E) int bad(int x) { return E; }
788     BADDECL(x * x)
789   )cc";
790 
791   const char *Fun = "Fun";
792   TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun));
793   EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match),
794                        HasValue("BADDECL(x * x)"));
795 }
796 
797 // Tests case where the matched node is (only) part of the expanded text.
TEST(RangeSelectorTest,ExpansionOpPartial)798 TEST(RangeSelectorTest, ExpansionOpPartial) {
799   StringRef Code = R"cc(
800 #define BADDECL(E) int bad(int x) { return E; }
801     BADDECL(x * x)
802   )cc";
803 
804   const char *Ret = "Ret";
805   TestMatch Match = matchCode(Code, returnStmt().bind(Ret));
806   EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match),
807                        HasValue("BADDECL(x * x)"));
808 }
809 
TEST(RangeSelectorTest,IfBoundOpBound)810 TEST(RangeSelectorTest, IfBoundOpBound) {
811   StringRef Code = R"cc(
812     int f() {
813       return 3 + 5;
814     }
815   )cc";
816   const char *ID = "id", *Op = "op";
817   TestMatch Match =
818       matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));
819   EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
820                        HasValue("3"));
821 }
822 
TEST(RangeSelectorTest,IfBoundOpUnbound)823 TEST(RangeSelectorTest, IfBoundOpUnbound) {
824   StringRef Code = R"cc(
825     int f() {
826       return 3 + 5;
827     }
828   )cc";
829   const char *ID = "id", *Op = "op";
830   TestMatch Match = matchCode(Code, binaryOperator().bind(Op));
831   EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
832                        HasValue("3 + 5"));
833 }
834 
835 } // namespace
836