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 
matchCode(StringRef Code,M Matcher)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.
select(RangeSelector Selector,const TestMatch & Match)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.
selectFromTrivial(const RangeSelector & Selector)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.
withUnboundNodeMessage()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.
selectFromAssorted(RangeSelector Selector)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.
withTypeErrorMessage(const std::string & NodeID)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 
TEST(RangeSelectorTest,UnboundNode)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.
TEST(RangeSelectorTest,BeforeOp)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 
TEST(RangeSelectorTest,BeforeOpParsed)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 
TEST(RangeSelectorTest,AfterOp)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`.
getSpellingLocAfter(const MatchResult & Result,StringRef Id,int Length)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.
TEST(RangeSelectorTest,AfterOpInMacroArg)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.
TEST(RangeSelectorTest,AfterOpInMacroArgEndsExpansion)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 
TEST(RangeSelectorTest,AfterOpInPartOfMacroArg)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 
TEST(RangeSelectorTest,BetweenOp)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 
TEST(RangeSelectorTest,BetweenOpParsed)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.
TEST(RangeSelectorTest,EncloseOpNodes)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 
TEST(RangeSelectorTest,EncloseOpGeneral)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 
TEST(RangeSelectorTest,EncloseOpNodesParsed)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 
TEST(RangeSelectorTest,EncloseOpGeneralParsed)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 
TEST(RangeSelectorTest,NodeOpStatement)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 
TEST(RangeSelectorTest,NodeOpExpression)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 
TEST(RangeSelectorTest,StatementOp)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 
TEST(RangeSelectorTest,StatementOpParsed)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 
TEST(RangeSelectorTest,MemberOp)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.
TEST(RangeSelectorTest,MemberOpQualified)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 
TEST(RangeSelectorTest,MemberOpTemplate)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 
TEST(RangeSelectorTest,MemberOpOperator)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 
TEST(RangeSelectorTest,NameOpNamedDecl)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 
TEST(RangeSelectorTest,NameOpDeclRef)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 
TEST(RangeSelectorTest,NameOpCtorInitializer)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 
TEST(RangeSelectorTest,NameOpTypeLoc)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 
TEST(RangeSelectorTest,NameOpErrors)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 
TEST(RangeSelectorTest,NameOpDeclRefError)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 
TEST(RangeSelectorTest,CallArgsOp)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 
TEST(RangeSelectorTest,CallArgsOpNoArgs)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 
TEST(RangeSelectorTest,CallArgsOpNoArgsWithComments)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.
TEST(RangeSelectorTest,CallArgsOpWithParens)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 
TEST(RangeSelectorTest,CallArgsOpLeadingComments)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 
TEST(RangeSelectorTest,CallArgsOpTrailingComments)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 
TEST(RangeSelectorTest,CallArgsOpEolComments)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 
TEST(RangeSelectorTest,CallArgsErrors)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 
TEST(RangeSelectorTest,StatementsOp)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 
TEST(RangeSelectorTest,StatementsOpEmptyList)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 
TEST(RangeSelectorTest,StatementsOpErrors)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 
TEST(RangeSelectorTest,ElementsOp)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 
TEST(RangeSelectorTest,ElementsOpEmptyList)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 
TEST(RangeSelectorTest,ElementsOpErrors)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 
TEST(RangeSelectorTest,ElseBranchOpSingleStatement)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 
TEST(RangeSelectorTest,ElseBranchOpCompoundStatement)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.
TEST(RangeSelectorTest,ExpansionOp)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.
TEST(RangeSelectorTest,ExpansionOpPartial)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 
TEST(RangeSelectorTest,IfBoundOpBound)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 
TEST(RangeSelectorTest,IfBoundOpUnbound)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