Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / unittests / Tooling / RangeSelectorTest.cpp
blob03ab66235e43c63acb07ac332097aee7efedd743
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 //===----------------------------------------------------------------------===//
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;
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;
32 using MatchResult = MatchFinder::MatchResult;
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;
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);
61 if (!Range)
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.
71 TestMatch Match =
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(
89 struct A {};
90 class F : public A {
91 public:
92 F(int) {}
94 void g() { F f(1); }
95 )cc";
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");
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); }
134 )cc";
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(
144 R(Match.Result),
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); }
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());
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))));
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);
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
196 // `Id`.
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
206 // expansion itself.
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";
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)));
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); }
227 )cc";
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)));
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";
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)));
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 */ "));
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 */ "));
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); }
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"));
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"));
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"));
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"));
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(
359 struct S {
360 int member;
362 int g() {
363 S s;
364 return s.member;
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"));
372 // Tests that member does not select any qualifiers on the member name.
373 TEST(RangeSelectorTest, MemberOpQualified) {
374 StringRef Code = R"cc(
375 struct S {
376 int member;
378 struct T : public S {
379 int field;
381 int g() {
382 T t;
383 return t.S::member;
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"));
391 TEST(RangeSelectorTest, MemberOpTemplate) {
392 StringRef Code = R"cc(
393 struct S {
394 template <typename T> T foo(T t);
396 int f(int x) {
397 S s;
398 return s.template foo<int>(3);
400 )cc";
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(
409 struct S {
410 int operator*();
412 int f(int x) {
413 S s;
414 return s.operator *();
416 )cc";
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(
425 int myfun() {
426 return 3;
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"));
434 TEST(RangeSelectorTest, NameOpDeclRef) {
435 StringRef Code = R"cc(
436 int foo(int x) {
437 return x;
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"));
446 TEST(RangeSelectorTest, NameOpCtorInitializer) {
447 StringRef Code = R"cc(
448 class C {
449 public:
450 C() : field(3) {}
451 int field;
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"));
459 TEST(RangeSelectorTest, NameOpTypeLoc) {
460 StringRef Code = R"cc(
461 namespace ns {
462 struct Foo {
463 Foo();
464 Foo(int);
465 Foo(int, int);
467 } // namespace ns
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"));
488 TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) {
489 StringRef Code = R"cc(
490 namespace ns {
491 template <typename T>
492 struct Foo {};
493 } // namespace ns
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"));
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(
513 struct S {
514 int operator*();
516 int f(int x) {
517 S s;
518 return *s + x;
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'")))));
530 TEST(RangeSelectorTest, CallArgsOp) {
531 const StringRef Code = R"cc(
532 struct C {
533 int bar(int, int);
535 int f() {
536 C x;
537 return x.bar(3, 4);
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"));
545 TEST(RangeSelectorTest, CallArgsOpNoArgs) {
546 const StringRef Code = R"cc(
547 struct C {
548 int bar();
550 int f() {
551 C x;
552 return x.bar();
554 )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(
562 struct C {
563 int bar();
565 int f() {
566 C x;
567 return x.bar(/*empty*/);
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*/"));
575 // Tests that arguments are extracted correctly when a temporary (with parens)
576 // is used.
577 TEST(RangeSelectorTest, CallArgsOpWithParens) {
578 const StringRef Code = R"cc(
579 struct C {
580 int bar(int, int) { return 3; }
582 int f() {
583 C x;
584 return C().bar(3, 4);
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"));
593 TEST(RangeSelectorTest, CallArgsOpLeadingComments) {
594 const StringRef Code = R"cc(
595 struct C {
596 int bar(int, int) { return 3; }
598 int f() {
599 C x;
600 return x.bar(/*leading*/ 3, 4);
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"));
609 TEST(RangeSelectorTest, CallArgsOpTrailingComments) {
610 const StringRef Code = R"cc(
611 struct C {
612 int bar(int, int) { return 3; }
614 int f() {
615 C x;
616 return x.bar(3 /*trailing*/, 4);
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"));
625 TEST(RangeSelectorTest, CallArgsOpEolComments) {
626 const StringRef Code = R"cc(
627 struct C {
628 int bar(int, int) { return 3; }
630 int f() {
631 C x;
632 return x.bar( // Header
633 1, // foo
634 2 // bar
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
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(
656 void g();
657 void f() { /* comment */ g(); /* comment */ g(); /* comment */ }
658 )cc";
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(
682 void f() {
683 int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};
684 (void)v;
686 )cc";
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(
696 void f() {
697 int v[] = {};
698 (void)v;
700 )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(
715 int f() {
716 int x = 0;
717 if (true) x = 3;
718 else x = 4;
719 return x + 5;
721 )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(
729 int f() {
730 int x = 0;
731 if (true) x = 3;
732 else { x = 4; }
733 return x + 5;
735 )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; }
746 BADDECL(x * x)
747 )cc";
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; }
759 BADDECL(x * x)
760 )cc";
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(
770 int f() {
771 return 3 + 5;
773 )cc";
774 const char *ID = "id", *Op = "op";
775 TestMatch Match =
776 matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));
777 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
778 HasValue("3"));
781 TEST(RangeSelectorTest, IfBoundOpUnbound) {
782 StringRef Code = R"cc(
783 int f() {
784 return 3 + 5;
786 )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),
790 HasValue("3 + 5"));
793 } // namespace