1 //===- unittest/Tooling/RangeSelectorTest.cpp -----------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
20 using namespace clang
;
21 using namespace transformer
;
22 using namespace ast_matchers
;
25 using ::llvm::Expected
;
27 using ::llvm::HasValue
;
28 using ::llvm::StringError
;
29 using ::testing::AllOf
;
30 using ::testing::HasSubstr
;
32 using MatchResult
= MatchFinder::MatchResult
;
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`.
42 template <typename M
> TestMatch
matchCode(StringRef Code
, M Matcher
) {
43 auto ASTUnit
= tooling::buildASTFromCode(Code
);
44 assert(ASTUnit
!= nullptr && "AST construction failed");
46 ASTContext
&Context
= ASTUnit
->getASTContext();
47 assert(!Context
.getDiagnostics().hasErrorOccurred() && "Compilation error");
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");
55 return TestMatch
{std::move(ASTUnit
), MatchResult(Matches
[0], &Context
)};
58 // Applies \p Selector to \p Match and, on success, returns the selected source.
59 Expected
<StringRef
> select(RangeSelector Selector
, const TestMatch
&Match
) {
60 Expected
<CharSourceRange
> Range
= Selector(Match
.Result
);
62 return Range
.takeError();
63 return tooling::getText(*Range
, *Match
.Result
.Context
);
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.
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.
72 matchCode("static int x = 0;", varDecl().bind("bound_node_id"));
73 return Selector(Match
.Result
);
76 // Matches the message expected for unbound-node failures.
77 testing::Matcher
<StringError
> withUnboundNodeMessage() {
78 return testing::Property(
79 &StringError::getMessage
,
80 AllOf(HasSubstr("unbound_id"), HasSubstr("not bound")));
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.
87 Expected
<CharSourceRange
> selectFromAssorted(RangeSelector Selector
) {
88 StringRef Code
= R
"cc(
102 decl(hasDescendant(cxxCtorInitializer(isBaseInitializer())
108 return Selector(matchCode(Code
, Matcher
).Result
);
111 // Matches the message expected for type-error failures.
112 testing::Matcher
<StringError
> withTypeErrorMessage(const std::string
&NodeID
) {
113 return testing::Property(
114 &StringError::getMessage
,
115 AllOf(HasSubstr(NodeID
), HasSubstr("mismatched type")));
118 TEST(RangeSelectorTest
, UnboundNode
) {
119 EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")),
120 Failed
<StringError
>(withUnboundNodeMessage()));
123 MATCHER_P(EqualsCharSourceRange
, Range
, "") {
124 return Range
.getAsRange() == arg
.getAsRange() &&
125 Range
.isTokenRange() == arg
.isTokenRange();
128 // FIXME: here and elsewhere: use llvm::Annotations library to explicitly mark
129 // points and ranges of interest, enabling more readable tests.
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); }
135 StringRef CallID
= "call";
136 ast_matchers::internal::Matcher
<Stmt
> M
= callExpr().bind(CallID
);
137 RangeSelector R
= before(node(CallID
.str()));
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(
145 HasValue(EqualsCharSourceRange(
146 CharSourceRange::getCharRange(ExprBegin
, ExprBegin
))));
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); }
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());
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(
165 HasValue(EqualsCharSourceRange(
166 CharSourceRange::getCharRange(ExprBegin
, ExprBegin
))));
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); }
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
);
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
)));
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
)));
195 // Gets the spelling location `Length` characters after the start of AST node
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
);
205 // Test with a range that is the entire macro arg, but does not end the
207 TEST(RangeSelectorTest
, AfterOpInMacroArg
) {
208 StringRef Code
= R
"cc(
209 #define ISNULL(x) x == nullptr
210 bool g() { int* y; return ISNULL(y); }
214 matchCode(Code
, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
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
)));
222 // Test with a range that is the entire macro arg and ends the expansion itself.
223 TEST(RangeSelectorTest
, AfterOpInMacroArgEndsExpansion
) {
224 StringRef Code
= R
"cc(
225 #define ISNULL(x) nullptr == x
226 bool g() { int* y; return ISNULL(y); }
230 matchCode(Code
, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
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
)));
238 TEST(RangeSelectorTest
, AfterOpInPartOfMacroArg
) {
239 StringRef Code
= R
"cc(
240 #define ISNULL(x) x == nullptr
242 bool g() { int* y; return ISNULL(f(y)); }
246 matchCode(Code
, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
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
)));
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); }
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 */ "));
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); }
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 */ "));
279 // Node-id specific version.
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); }
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"));
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); }
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"));
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); }
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"));
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); }
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"));
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;"));
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"));
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;"));
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;"));
357 TEST(RangeSelectorTest
, MemberOp
) {
358 StringRef Code
= R
"cc(
367 const char *ID
= "id";
368 TestMatch Match
= matchCode(Code
, memberExpr().bind(ID
));
369 EXPECT_THAT_EXPECTED(select(member(ID
), Match
), HasValue("member"));
372 // Tests that member does not select any qualifiers on the member name.
373 TEST(RangeSelectorTest
, MemberOpQualified
) {
374 StringRef Code
= R
"cc(
378 struct T : public S {
386 const char *ID
= "id";
387 TestMatch Match
= matchCode(Code
, memberExpr().bind(ID
));
388 EXPECT_THAT_EXPECTED(select(member(ID
), Match
), HasValue("member"));
391 TEST(RangeSelectorTest
, MemberOpTemplate
) {
392 StringRef Code
= R
"cc(
394 template <typename T> T foo(T t);
398 return s.template foo<int>(3);
402 const char *ID
= "id";
403 TestMatch Match
= matchCode(Code
, memberExpr().bind(ID
));
404 EXPECT_THAT_EXPECTED(select(member(ID
), Match
), HasValue("foo"));
407 TEST(RangeSelectorTest
, MemberOpOperator
) {
408 StringRef Code
= R
"cc(
414 return s.operator *();
418 const char *ID
= "id";
419 TestMatch Match
= matchCode(Code
, memberExpr().bind(ID
));
420 EXPECT_THAT_EXPECTED(select(member(ID
), Match
), HasValue("operator *"));
423 TEST(RangeSelectorTest
, NameOpNamedDecl
) {
424 StringRef Code
= R
"cc(
429 const char *ID
= "id";
430 TestMatch Match
= matchCode(Code
, functionDecl().bind(ID
));
431 EXPECT_THAT_EXPECTED(select(name(ID
), Match
), HasValue("myfun"));
434 TEST(RangeSelectorTest
, NameOpDeclRef
) {
435 StringRef Code
= R
"cc(
439 int g(int x) { return foo(x) * x; }
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"));
446 TEST(RangeSelectorTest
, NameOpCtorInitializer
) {
447 StringRef Code
= R
"cc(
454 const char *Init
= "init";
455 TestMatch Match
= matchCode(Code
, cxxCtorInitializer().bind(Init
));
456 EXPECT_THAT_EXPECTED(select(name(Init
), Match
), HasValue("field"));
459 TEST(RangeSelectorTest
, NameOpTypeLoc
) {
460 StringRef Code
= R
"cc(
471 auto c = ns::Foo(1, 2);
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"));
488 TEST(RangeSelectorTest
, NameOpTemplateSpecializationTypeLoc
) {
489 StringRef Code
= R
"cc(
491 template <typename T>
497 const char *Loc
= "tyloc";
498 // Matches declaration of `a`.
500 matchCode(Code
, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(Loc
))));
501 EXPECT_THAT_EXPECTED(select(name(Loc
), MatchA
), HasValue("Foo"));
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")));
511 TEST(RangeSelectorTest
, NameOpDeclRefError
) {
512 StringRef Code
= R
"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'")))));
530 TEST(RangeSelectorTest
, CallArgsOp
) {
531 const StringRef Code
= R
"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"));
545 TEST(RangeSelectorTest
, CallArgsOpNoArgs
) {
546 const StringRef Code
= R
"cc(
555 const char *ID
= "id";
556 TestMatch Match
= matchCode(Code
, callExpr().bind(ID
));
557 EXPECT_THAT_EXPECTED(select(callArgs(ID
), Match
), HasValue(""));
560 TEST(RangeSelectorTest
, CallArgsOpNoArgsWithComments
) {
561 const StringRef Code
= R
"cc(
567 return x.bar(/*empty*/);
570 const char *ID
= "id";
571 TestMatch Match
= matchCode(Code
, callExpr().bind(ID
));
572 EXPECT_THAT_EXPECTED(select(callArgs(ID
), Match
), HasValue("/*empty*/"));
575 // Tests that arguments are extracted correctly when a temporary (with parens)
577 TEST(RangeSelectorTest
, CallArgsOpWithParens
) {
578 const StringRef Code
= R
"cc(
580 int bar(int, int) { return 3; }
584 return C().bar(3, 4);
587 const char *ID
= "id";
589 matchCode(Code
, callExpr(callee(functionDecl(hasName("bar")))).bind(ID
));
590 EXPECT_THAT_EXPECTED(select(callArgs(ID
), Match
), HasValue("3, 4"));
593 TEST(RangeSelectorTest
, CallArgsOpLeadingComments
) {
594 const StringRef Code
= R
"cc(
596 int bar(int, int) { return 3; }
600 return x.bar(/*leading*/ 3, 4);
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"));
609 TEST(RangeSelectorTest
, CallArgsOpTrailingComments
) {
610 const StringRef Code
= R
"cc(
612 int bar(int, int) { return 3; }
616 return x.bar(3 /*trailing*/, 4);
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"));
625 TEST(RangeSelectorTest
, CallArgsOpEolComments
) {
626 const StringRef Code
= R
"cc(
628 int bar(int, int) { return 3; }
632 return x.bar( // Header
638 const char *ID
= "id";
639 TestMatch Match
= matchCode(Code
, callExpr().bind(ID
));
640 std::string ExpectedString
= R
"( // Header
644 EXPECT_THAT_EXPECTED(select(callArgs(ID
), Match
), HasValue(ExpectedString
));
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")));
654 TEST(RangeSelectorTest
, StatementsOp
) {
655 StringRef Code
= R
"cc(
657 void f() { /* comment */ g(); /* comment */ g(); /* comment */ }
659 const char *ID
= "id";
660 TestMatch Match
= matchCode(Code
, compoundStmt().bind(ID
));
661 EXPECT_THAT_EXPECTED(
662 select(statements(ID
), Match
),
663 HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ "));
666 TEST(RangeSelectorTest
, StatementsOpEmptyList
) {
667 StringRef Code
= "void f() {}";
668 const char *ID
= "id";
669 TestMatch Match
= matchCode(Code
, compoundStmt().bind(ID
));
670 EXPECT_THAT_EXPECTED(select(statements(ID
), Match
), HasValue(""));
673 TEST(RangeSelectorTest
, StatementsOpErrors
) {
674 EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")),
675 Failed
<StringError
>(withUnboundNodeMessage()));
676 EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")),
677 Failed
<StringError
>(withTypeErrorMessage("decl")));
680 TEST(RangeSelectorTest
, ElementsOp
) {
681 StringRef Code
= R
"cc(
683 int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};
687 const char *ID
= "id";
688 TestMatch Match
= matchCode(Code
, initListExpr().bind(ID
));
689 EXPECT_THAT_EXPECTED(
690 select(initListElements(ID
), Match
),
691 HasValue("/* comment */ 3, /* comment*/ 4 /* comment */"));
694 TEST(RangeSelectorTest
, ElementsOpEmptyList
) {
695 StringRef Code
= R
"cc(
701 const char *ID
= "id";
702 TestMatch Match
= matchCode(Code
, initListExpr().bind(ID
));
703 EXPECT_THAT_EXPECTED(select(initListElements(ID
), Match
), HasValue(""));
706 TEST(RangeSelectorTest
, ElementsOpErrors
) {
707 EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")),
708 Failed
<StringError
>(withUnboundNodeMessage()));
709 EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")),
710 Failed
<StringError
>(withTypeErrorMessage("stmt")));
713 TEST(RangeSelectorTest
, ElseBranchOpSingleStatement
) {
714 StringRef Code
= R
"cc(
722 const char *ID
= "id";
723 TestMatch Match
= matchCode(Code
, ifStmt().bind(ID
));
724 EXPECT_THAT_EXPECTED(select(elseBranch(ID
), Match
), HasValue("else x = 4;"));
727 TEST(RangeSelectorTest
, ElseBranchOpCompoundStatement
) {
728 StringRef Code
= R
"cc(
736 const char *ID
= "id";
737 TestMatch Match
= matchCode(Code
, ifStmt().bind(ID
));
738 EXPECT_THAT_EXPECTED(select(elseBranch(ID
), Match
),
739 HasValue("else { x = 4; }"));
742 // Tests case where the matched node is the complete expanded text.
743 TEST(RangeSelectorTest
, ExpansionOp
) {
744 StringRef Code
= R
"cc(
745 #define BADDECL(E) int bad(int x) { return E; }
749 const char *Fun
= "Fun";
750 TestMatch Match
= matchCode(Code
, functionDecl(hasName("bad")).bind(Fun
));
751 EXPECT_THAT_EXPECTED(select(expansion(node(Fun
)), Match
),
752 HasValue("BADDECL(x * x)"));
755 // Tests case where the matched node is (only) part of the expanded text.
756 TEST(RangeSelectorTest
, ExpansionOpPartial
) {
757 StringRef Code
= R
"cc(
758 #define BADDECL(E) int bad(int x) { return E; }
762 const char *Ret
= "Ret";
763 TestMatch Match
= matchCode(Code
, returnStmt().bind(Ret
));
764 EXPECT_THAT_EXPECTED(select(expansion(node(Ret
)), Match
),
765 HasValue("BADDECL(x * x)"));
768 TEST(RangeSelectorTest
, IfBoundOpBound
) {
769 StringRef Code
= R
"cc(
774 const char *ID
= "id", *Op
= "op";
776 matchCode(Code
, binaryOperator(hasLHS(expr().bind(ID
))).bind(Op
));
777 EXPECT_THAT_EXPECTED(select(ifBound(ID
, node(ID
), node(Op
)), Match
),
781 TEST(RangeSelectorTest
, IfBoundOpUnbound
) {
782 StringRef Code
= R
"cc(
787 const char *ID
= "id", *Op
= "op";
788 TestMatch Match
= matchCode(Code
, binaryOperator().bind(Op
));
789 EXPECT_THAT_EXPECTED(select(ifBound(ID
, node(ID
), node(Op
)), Match
),