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