1 //===- unittest/Tooling/RangeSelectorTest.cpp -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Tooling/Transformer/RangeSelector.h"
10 #include "clang/ASTMatchers/ASTMatchers.h"
11 #include "clang/Frontend/ASTUnit.h"
12 #include "clang/Tooling/Tooling.h"
13 #include "clang/Tooling/Transformer/Parsing.h"
14 #include "clang/Tooling/Transformer/SourceCode.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Testing/Support/Error.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 
20 using namespace clang;
21 using namespace transformer;
22 using namespace ast_matchers;
23 
24 namespace {
25 using ::llvm::Expected;
26 using ::llvm::Failed;
27 using ::llvm::HasValue;
28 using ::llvm::StringError;
29 using ::testing::AllOf;
30 using ::testing::HasSubstr;
31 using ::testing::Property;
32 
33 using MatchResult = MatchFinder::MatchResult;
34 
35 struct TestMatch {
36   // The AST unit from which `result` is built. We bundle it because it backs
37   // the result. Users are not expected to access it.
38   std::unique_ptr<clang::ASTUnit> ASTUnit;
39   // The result to use in the test. References `ast_unit`.
40   MatchResult Result;
41 };
42 
43 template <typename M> TestMatch matchCode(StringRef Code, M Matcher) {
44   auto ASTUnit = tooling::buildASTFromCode(Code);
45   assert(ASTUnit != nullptr && "AST construction failed");
46 
47   ASTContext &Context = ASTUnit->getASTContext();
48   assert(!Context.getDiagnostics().hasErrorOccurred() && "Compilation error");
49 
50   TraversalKindScope RAII(Context, ast_type_traits::TK_AsIs);
51   auto Matches = ast_matchers::match(Matcher, Context);
52   // We expect a single, exact match.
53   assert(Matches.size() != 0 && "no matches found");
54   assert(Matches.size() == 1 && "too many matches");
55 
56   return TestMatch{std::move(ASTUnit), MatchResult(Matches[0], &Context)};
57 }
58 
59 // Applies \p Selector to \p Match and, on success, returns the selected source.
60 Expected<StringRef> select(RangeSelector Selector, const TestMatch &Match) {
61   Expected<CharSourceRange> Range = Selector(Match.Result);
62   if (!Range)
63     return Range.takeError();
64   return tooling::getText(*Range, *Match.Result.Context);
65 }
66 
67 // Applies \p Selector to a trivial match with only a single bound node with id
68 // "bound_node_id".  For use in testing unbound-node errors.
69 Expected<CharSourceRange> selectFromTrivial(const RangeSelector &Selector) {
70   // We need to bind the result to something, or the match will fail. Use a
71   // binding that is not used in the unbound node tests.
72   TestMatch Match =
73       matchCode("static int x = 0;", varDecl().bind("bound_node_id"));
74   return Selector(Match.Result);
75 }
76 
77 // Matches the message expected for unbound-node failures.
78 testing::Matcher<StringError> withUnboundNodeMessage() {
79   return testing::Property(
80       &StringError::getMessage,
81       AllOf(HasSubstr("unbound_id"), HasSubstr("not bound")));
82 }
83 
84 // Applies \p Selector to code containing assorted node types, where the match
85 // binds each one: a statement ("stmt"), a (non-member) ctor-initializer
86 // ("init"), an expression ("expr") and a (nameless) declaration ("decl").  Used
87 // to test failures caused by applying selectors to nodes of the wrong type.
88 Expected<CharSourceRange> selectFromAssorted(RangeSelector Selector) {
89   StringRef Code = R"cc(
90       struct A {};
91       class F : public A {
92        public:
93         F(int) {}
94       };
95       void g() { F f(1); }
96     )cc";
97 
98   auto Matcher =
99       compoundStmt(
100           hasDescendant(
101               cxxConstructExpr(
102                   hasDeclaration(
103                       decl(hasDescendant(cxxCtorInitializer(isBaseInitializer())
104                                              .bind("init")))
105                           .bind("decl")))
106                   .bind("expr")))
107           .bind("stmt");
108 
109   return Selector(matchCode(Code, Matcher).Result);
110 }
111 
112 // Matches the message expected for type-error failures.
113 testing::Matcher<StringError> withTypeErrorMessage(const std::string &NodeID) {
114   return testing::Property(
115       &StringError::getMessage,
116       AllOf(HasSubstr(NodeID), HasSubstr("mismatched type")));
117 }
118 
119 TEST(RangeSelectorTest, UnboundNode) {
120   EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")),
121                        Failed<StringError>(withUnboundNodeMessage()));
122 }
123 
124 MATCHER_P(EqualsCharSourceRange, Range, "") {
125   return Range.getAsRange() == arg.getAsRange() &&
126          Range.isTokenRange() == arg.isTokenRange();
127 }
128 
129 // FIXME: here and elsewhere: use llvm::Annotations library to explicitly mark
130 // points and ranges of interest, enabling more readable tests.
131 TEST(RangeSelectorTest, BeforeOp) {
132   StringRef Code = R"cc(
133     int f(int x, int y, int z) { return 3; }
134     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
135   )cc";
136   StringRef CallID = "call";
137   ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID);
138   RangeSelector R = before(node(CallID.str()));
139 
140   TestMatch Match = matchCode(Code, M);
141   const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID);
142   assert(E != nullptr);
143   auto ExprBegin = E->getSourceRange().getBegin();
144   EXPECT_THAT_EXPECTED(
145       R(Match.Result),
146       HasValue(EqualsCharSourceRange(
147           CharSourceRange::getCharRange(ExprBegin, ExprBegin))));
148 }
149 
150 TEST(RangeSelectorTest, BeforeOpParsed) {
151   StringRef Code = R"cc(
152     int f(int x, int y, int z) { return 3; }
153     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
154   )cc";
155   StringRef CallID = "call";
156   ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID);
157   auto R = parseRangeSelector(R"rs(before(node("call")))rs");
158   ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
159 
160   TestMatch Match = matchCode(Code, M);
161   const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID);
162   assert(E != nullptr);
163   auto ExprBegin = E->getSourceRange().getBegin();
164   EXPECT_THAT_EXPECTED(
165       (*R)(Match.Result),
166       HasValue(EqualsCharSourceRange(
167           CharSourceRange::getCharRange(ExprBegin, ExprBegin))));
168 }
169 
170 TEST(RangeSelectorTest, AfterOp) {
171   StringRef Code = R"cc(
172     int f(int x, int y, int z) { return 3; }
173     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
174   )cc";
175   StringRef Call = "call";
176   TestMatch Match = matchCode(Code, callExpr().bind(Call));
177   const auto* E = Match.Result.Nodes.getNodeAs<Expr>(Call);
178   assert(E != nullptr);
179   const SourceRange Range = E->getSourceRange();
180   // The end token, a right paren, is one character wide, so advance by one,
181   // bringing us to the semicolon.
182   const SourceLocation SemiLoc = Range.getEnd().getLocWithOffset(1);
183   const auto ExpectedAfter = CharSourceRange::getCharRange(SemiLoc, SemiLoc);
184 
185   // Test with a char range.
186   auto CharRange = CharSourceRange::getCharRange(Range.getBegin(), SemiLoc);
187   EXPECT_THAT_EXPECTED(after(charRange(CharRange))(Match.Result),
188                        HasValue(EqualsCharSourceRange(ExpectedAfter)));
189 
190   // Test with a token range.
191   auto TokenRange = CharSourceRange::getTokenRange(Range);
192   EXPECT_THAT_EXPECTED(after(charRange(TokenRange))(Match.Result),
193                        HasValue(EqualsCharSourceRange(ExpectedAfter)));
194 }
195 
196 TEST(RangeSelectorTest, BetweenOp) {
197   StringRef Code = R"cc(
198     int f(int x, int y, int z) { return 3; }
199     int g() { return f(3, /* comment */ 7 /* comment */, 9); }
200   )cc";
201   auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
202                           hasArgument(1, expr().bind("a1")));
203   RangeSelector R = between(node("a0"), node("a1"));
204   TestMatch Match = matchCode(Code, Matcher);
205   EXPECT_THAT_EXPECTED(select(R, Match), HasValue(", /* comment */ "));
206 }
207 
208 TEST(RangeSelectorTest, BetweenOpParsed) {
209   StringRef Code = R"cc(
210     int f(int x, int y, int z) { return 3; }
211     int g() { return f(3, /* comment */ 7 /* comment */, 9); }
212   )cc";
213   auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
214                           hasArgument(1, expr().bind("a1")));
215   auto R = parseRangeSelector(R"rs(between(node("a0"), node("a1")))rs");
216   ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
217   TestMatch Match = matchCode(Code, Matcher);
218   EXPECT_THAT_EXPECTED(select(*R, Match), HasValue(", /* comment */ "));
219 }
220 
221 // Node-id specific version.
222 TEST(RangeSelectorTest, EncloseOpNodes) {
223   StringRef Code = R"cc(
224     int f(int x, int y, int z) { return 3; }
225     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
226   )cc";
227   auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
228                           hasArgument(1, expr().bind("a1")));
229   RangeSelector R = encloseNodes("a0", "a1");
230   TestMatch Match = matchCode(Code, Matcher);
231   EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));
232 }
233 
234 TEST(RangeSelectorTest, EncloseOpGeneral) {
235   StringRef Code = R"cc(
236     int f(int x, int y, int z) { return 3; }
237     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
238   )cc";
239   auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
240                           hasArgument(1, expr().bind("a1")));
241   RangeSelector R = enclose(node("a0"), node("a1"));
242   TestMatch Match = matchCode(Code, Matcher);
243   EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));
244 }
245 
246 TEST(RangeSelectorTest, EncloseOpNodesParsed) {
247   StringRef Code = R"cc(
248     int f(int x, int y, int z) { return 3; }
249     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
250   )cc";
251   auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
252                           hasArgument(1, expr().bind("a1")));
253   auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs");
254   ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
255   TestMatch Match = matchCode(Code, Matcher);
256   EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));
257 }
258 
259 TEST(RangeSelectorTest, EncloseOpGeneralParsed) {
260   StringRef Code = R"cc(
261     int f(int x, int y, int z) { return 3; }
262     int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
263   )cc";
264   auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
265                           hasArgument(1, expr().bind("a1")));
266   auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs");
267   ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
268   TestMatch Match = matchCode(Code, Matcher);
269   EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));
270 }
271 
272 TEST(RangeSelectorTest, NodeOpStatement) {
273   StringRef Code = "int f() { return 3; }";
274   TestMatch Match = matchCode(Code, returnStmt().bind("id"));
275   EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("return 3;"));
276 }
277 
278 TEST(RangeSelectorTest, NodeOpExpression) {
279   StringRef Code = "int f() { return 3; }";
280   TestMatch Match = matchCode(Code, expr().bind("id"));
281   EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("3"));
282 }
283 
284 TEST(RangeSelectorTest, StatementOp) {
285   StringRef Code = "int f() { return 3; }";
286   TestMatch Match = matchCode(Code, expr().bind("id"));
287   RangeSelector R = statement("id");
288   EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3;"));
289 }
290 
291 TEST(RangeSelectorTest, StatementOpParsed) {
292   StringRef Code = "int f() { return 3; }";
293   TestMatch Match = matchCode(Code, expr().bind("id"));
294   auto R = parseRangeSelector(R"rs(statement("id"))rs");
295   ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
296   EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3;"));
297 }
298 
299 TEST(RangeSelectorTest, MemberOp) {
300   StringRef Code = R"cc(
301     struct S {
302       int member;
303     };
304     int g() {
305       S s;
306       return s.member;
307     }
308   )cc";
309   const char *ID = "id";
310   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
311   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));
312 }
313 
314 // Tests that member does not select any qualifiers on the member name.
315 TEST(RangeSelectorTest, MemberOpQualified) {
316   StringRef Code = R"cc(
317     struct S {
318       int member;
319     };
320     struct T : public S {
321       int field;
322     };
323     int g() {
324       T t;
325       return t.S::member;
326     }
327   )cc";
328   const char *ID = "id";
329   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
330   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));
331 }
332 
333 TEST(RangeSelectorTest, MemberOpTemplate) {
334   StringRef Code = R"cc(
335     struct S {
336       template <typename T> T foo(T t);
337     };
338     int f(int x) {
339       S s;
340       return s.template foo<int>(3);
341     }
342   )cc";
343 
344   const char *ID = "id";
345   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
346   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo"));
347 }
348 
349 TEST(RangeSelectorTest, MemberOpOperator) {
350   StringRef Code = R"cc(
351     struct S {
352       int operator*();
353     };
354     int f(int x) {
355       S s;
356       return s.operator *();
357     }
358   )cc";
359 
360   const char *ID = "id";
361   TestMatch Match = matchCode(Code, memberExpr().bind(ID));
362   EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *"));
363 }
364 
365 TEST(RangeSelectorTest, NameOpNamedDecl) {
366   StringRef Code = R"cc(
367     int myfun() {
368       return 3;
369     }
370   )cc";
371   const char *ID = "id";
372   TestMatch Match = matchCode(Code, functionDecl().bind(ID));
373   EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("myfun"));
374 }
375 
376 TEST(RangeSelectorTest, NameOpDeclRef) {
377   StringRef Code = R"cc(
378     int foo(int x) {
379       return x;
380     }
381     int g(int x) { return foo(x) * x; }
382   )cc";
383   const char *Ref = "ref";
384   TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));
385   EXPECT_THAT_EXPECTED(select(name(Ref), Match), HasValue("foo"));
386 }
387 
388 TEST(RangeSelectorTest, NameOpCtorInitializer) {
389   StringRef Code = R"cc(
390     class C {
391      public:
392       C() : field(3) {}
393       int field;
394     };
395   )cc";
396   const char *Init = "init";
397   TestMatch Match = matchCode(Code, cxxCtorInitializer().bind(Init));
398   EXPECT_THAT_EXPECTED(select(name(Init), Match), HasValue("field"));
399 }
400 
401 TEST(RangeSelectorTest, NameOpErrors) {
402   EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")),
403                        Failed<StringError>(withUnboundNodeMessage()));
404   EXPECT_THAT_EXPECTED(selectFromAssorted(name("stmt")),
405                        Failed<StringError>(withTypeErrorMessage("stmt")));
406 }
407 
408 TEST(RangeSelectorTest, NameOpDeclRefError) {
409   StringRef Code = R"cc(
410     struct S {
411       int operator*();
412     };
413     int f(int x) {
414       S s;
415       return *s + x;
416     }
417   )cc";
418   const char *Ref = "ref";
419   TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));
420   EXPECT_THAT_EXPECTED(
421       name(Ref)(Match.Result),
422       Failed<StringError>(testing::Property(
423           &StringError::getMessage,
424           AllOf(HasSubstr(Ref), HasSubstr("requires property 'identifier'")))));
425 }
426 
427 TEST(RangeSelectorTest, CallArgsOp) {
428   const StringRef Code = R"cc(
429     struct C {
430       int bar(int, int);
431     };
432     int f() {
433       C x;
434       return x.bar(3, 4);
435     }
436   )cc";
437   const char *ID = "id";
438   TestMatch Match = matchCode(Code, callExpr().bind(ID));
439   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));
440 }
441 
442 TEST(RangeSelectorTest, CallArgsOpNoArgs) {
443   const StringRef Code = R"cc(
444     struct C {
445       int bar();
446     };
447     int f() {
448       C x;
449       return x.bar();
450     }
451   )cc";
452   const char *ID = "id";
453   TestMatch Match = matchCode(Code, callExpr().bind(ID));
454   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(""));
455 }
456 
457 TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) {
458   const StringRef Code = R"cc(
459     struct C {
460       int bar();
461     };
462     int f() {
463       C x;
464       return x.bar(/*empty*/);
465     }
466   )cc";
467   const char *ID = "id";
468   TestMatch Match = matchCode(Code, callExpr().bind(ID));
469   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("/*empty*/"));
470 }
471 
472 // Tests that arguments are extracted correctly when a temporary (with parens)
473 // is used.
474 TEST(RangeSelectorTest, CallArgsOpWithParens) {
475   const StringRef Code = R"cc(
476     struct C {
477       int bar(int, int) { return 3; }
478     };
479     int f() {
480       C x;
481       return C().bar(3, 4);
482     }
483   )cc";
484   const char *ID = "id";
485   TestMatch Match =
486       matchCode(Code, callExpr(callee(functionDecl(hasName("bar")))).bind(ID));
487   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));
488 }
489 
490 TEST(RangeSelectorTest, CallArgsOpLeadingComments) {
491   const StringRef Code = R"cc(
492     struct C {
493       int bar(int, int) { return 3; }
494     };
495     int f() {
496       C x;
497       return x.bar(/*leading*/ 3, 4);
498     }
499   )cc";
500   const char *ID = "id";
501   TestMatch Match = matchCode(Code, callExpr().bind(ID));
502   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),
503                        HasValue("/*leading*/ 3, 4"));
504 }
505 
506 TEST(RangeSelectorTest, CallArgsOpTrailingComments) {
507   const StringRef Code = R"cc(
508     struct C {
509       int bar(int, int) { return 3; }
510     };
511     int f() {
512       C x;
513       return x.bar(3 /*trailing*/, 4);
514     }
515   )cc";
516   const char *ID = "id";
517   TestMatch Match = matchCode(Code, callExpr().bind(ID));
518   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),
519                        HasValue("3 /*trailing*/, 4"));
520 }
521 
522 TEST(RangeSelectorTest, CallArgsOpEolComments) {
523   const StringRef Code = R"cc(
524     struct C {
525       int bar(int, int) { return 3; }
526     };
527     int f() {
528       C x;
529       return x.bar(  // Header
530           1,           // foo
531           2            // bar
532       );
533     }
534   )cc";
535   const char *ID = "id";
536   TestMatch Match = matchCode(Code, callExpr().bind(ID));
537   std::string ExpectedString = R"(  // Header
538           1,           // foo
539           2            // bar
540       )";
541   EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString));
542 }
543 
544 TEST(RangeSelectorTest, CallArgsErrors) {
545   EXPECT_THAT_EXPECTED(selectFromTrivial(callArgs("unbound_id")),
546                        Failed<StringError>(withUnboundNodeMessage()));
547   EXPECT_THAT_EXPECTED(selectFromAssorted(callArgs("stmt")),
548                        Failed<StringError>(withTypeErrorMessage("stmt")));
549 }
550 
551 TEST(RangeSelectorTest, StatementsOp) {
552   StringRef Code = R"cc(
553     void g();
554     void f() { /* comment */ g(); /* comment */ g(); /* comment */ }
555   )cc";
556   const char *ID = "id";
557   TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
558   EXPECT_THAT_EXPECTED(
559       select(statements(ID), Match),
560       HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ "));
561 }
562 
563 TEST(RangeSelectorTest, StatementsOpEmptyList) {
564   StringRef Code = "void f() {}";
565   const char *ID = "id";
566   TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
567   EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue(""));
568 }
569 
570 TEST(RangeSelectorTest, StatementsOpErrors) {
571   EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")),
572                        Failed<StringError>(withUnboundNodeMessage()));
573   EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")),
574                        Failed<StringError>(withTypeErrorMessage("decl")));
575 }
576 
577 TEST(RangeSelectorTest, ElementsOp) {
578   StringRef Code = R"cc(
579     void f() {
580       int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};
581       (void)v;
582     }
583   )cc";
584   const char *ID = "id";
585   TestMatch Match = matchCode(Code, initListExpr().bind(ID));
586   EXPECT_THAT_EXPECTED(
587       select(initListElements(ID), Match),
588       HasValue("/* comment */ 3, /* comment*/ 4 /* comment */"));
589 }
590 
591 TEST(RangeSelectorTest, ElementsOpEmptyList) {
592   StringRef Code = R"cc(
593     void f() {
594       int v[] = {};
595       (void)v;
596     }
597   )cc";
598   const char *ID = "id";
599   TestMatch Match = matchCode(Code, initListExpr().bind(ID));
600   EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue(""));
601 }
602 
603 TEST(RangeSelectorTest, ElementsOpErrors) {
604   EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")),
605                        Failed<StringError>(withUnboundNodeMessage()));
606   EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")),
607                        Failed<StringError>(withTypeErrorMessage("stmt")));
608 }
609 
610 TEST(RangeSelectorTest, ElseBranchOpSingleStatement) {
611   StringRef Code = R"cc(
612     int f() {
613       int x = 0;
614       if (true) x = 3;
615       else x = 4;
616       return x + 5;
617     }
618   )cc";
619   const char *ID = "id";
620   TestMatch Match = matchCode(Code, ifStmt().bind(ID));
621   EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;"));
622 }
623 
624 TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) {
625   StringRef Code = R"cc(
626     int f() {
627       int x = 0;
628       if (true) x = 3;
629       else { x = 4; }
630       return x + 5;
631     }
632   )cc";
633   const char *ID = "id";
634   TestMatch Match = matchCode(Code, ifStmt().bind(ID));
635   EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match),
636                        HasValue("else { x = 4; }"));
637 }
638 
639 // Tests case where the matched node is the complete expanded text.
640 TEST(RangeSelectorTest, ExpansionOp) {
641   StringRef Code = R"cc(
642 #define BADDECL(E) int bad(int x) { return E; }
643     BADDECL(x * x)
644   )cc";
645 
646   const char *Fun = "Fun";
647   TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun));
648   EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match),
649                        HasValue("BADDECL(x * x)"));
650 }
651 
652 // Tests case where the matched node is (only) part of the expanded text.
653 TEST(RangeSelectorTest, ExpansionOpPartial) {
654   StringRef Code = R"cc(
655 #define BADDECL(E) int bad(int x) { return E; }
656     BADDECL(x * x)
657   )cc";
658 
659   const char *Ret = "Ret";
660   TestMatch Match = matchCode(Code, returnStmt().bind(Ret));
661   EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match),
662                        HasValue("BADDECL(x * x)"));
663 }
664 
665 TEST(RangeSelectorTest, IfBoundOpBound) {
666   StringRef Code = R"cc(
667     int f() {
668       return 3 + 5;
669     }
670   )cc";
671   const char *ID = "id", *Op = "op";
672   TestMatch Match =
673       matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));
674   EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
675                        HasValue("3"));
676 }
677 
678 TEST(RangeSelectorTest, IfBoundOpUnbound) {
679   StringRef Code = R"cc(
680     int f() {
681       return 3 + 5;
682     }
683   )cc";
684   const char *ID = "id", *Op = "op";
685   TestMatch Match = matchCode(Code, binaryOperator().bind(Op));
686   EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
687                        HasValue("3 + 5"));
688 }
689 
690 } // namespace
691