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
32 using MatchResult = MatchFinder::MatchResult;
33
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;
40 };
41
matchCode(StringRef Code,M Matcher)42 template <typename M> TestMatch matchCode(StringRef Code, M Matcher) {
43 auto ASTUnit = tooling::buildASTFromCode(Code);
44 assert(ASTUnit != nullptr && "AST construction failed");
45
46 ASTContext &Context = ASTUnit->getASTContext();
47 assert(!Context.getDiagnostics().hasErrorOccurred() && "Compilation error");
48
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");
54
55 return TestMatch{std::move(ASTUnit), MatchResult(Matches[0], &Context)};
56 }
57
58 // Applies \p Selector to \p Match and, on success, returns the selected source.
select(RangeSelector Selector,const TestMatch & Match)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);
64 }
65
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.
selectFromTrivial(const RangeSelector & Selector)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);
74 }
75
76 // Matches the message expected for unbound-node failures.
withUnboundNodeMessage()77 testing::Matcher<StringError> withUnboundNodeMessage() {
78 return testing::Property(
79 &StringError::getMessage,
80 AllOf(HasSubstr("unbound_id"), HasSubstr("not bound")));
81 }
82
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.
selectFromAssorted(RangeSelector Selector)87 Expected<CharSourceRange> selectFromAssorted(RangeSelector Selector) {
88 StringRef Code = R"cc(
89 struct A {};
90 class F : public A {
91 public:
92 F(int) {}
93 };
94 void g() { F f(1); }
95 )cc";
96
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");
107
108 return Selector(matchCode(Code, Matcher).Result);
109 }
110
111 // Matches the message expected for type-error failures.
withTypeErrorMessage(const std::string & NodeID)112 testing::Matcher<StringError> withTypeErrorMessage(const std::string &NodeID) {
113 return testing::Property(
114 &StringError::getMessage,
115 AllOf(HasSubstr(NodeID), HasSubstr("mismatched type")));
116 }
117
TEST(RangeSelectorTest,UnboundNode)118 TEST(RangeSelectorTest, UnboundNode) {
119 EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")),
120 Failed<StringError>(withUnboundNodeMessage()));
121 }
122
123 MATCHER_P(EqualsCharSourceRange, Range, "") {
124 return Range.getAsRange() == arg.getAsRange() &&
125 Range.isTokenRange() == arg.isTokenRange();
126 }
127
128 // FIXME: here and elsewhere: use llvm::Annotations library to explicitly mark
129 // points and ranges of interest, enabling more readable tests.
TEST(RangeSelectorTest,BeforeOp)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()));
138
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))));
147 }
148
TEST(RangeSelectorTest,BeforeOpParsed)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());
158
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))));
167 }
168
TEST(RangeSelectorTest,AfterOp)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);
183
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)));
188
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)));
193 }
194
195 // Gets the spelling location `Length` characters after the start of AST node
196 // `Id`.
getSpellingLocAfter(const MatchResult & Result,StringRef Id,int Length)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);
203 }
204
205 // Test with a range that is the entire macro arg, but does not end the
206 // expansion itself.
TEST(RangeSelectorTest,AfterOpInMacroArg)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";
212
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)));
220 }
221
222 // Test with a range that is the entire macro arg and ends the expansion itself.
TEST(RangeSelectorTest,AfterOpInMacroArgEndsExpansion)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";
228
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)));
236 }
237
TEST(RangeSelectorTest,AfterOpInPartOfMacroArg)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";
244
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)));
252 }
253
TEST(RangeSelectorTest,BetweenOp)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 */ "));
264 }
265
TEST(RangeSelectorTest,BetweenOpParsed)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 */ "));
277 }
278
279 // Node-id specific version.
TEST(RangeSelectorTest,EncloseOpNodes)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"));
290 }
291
TEST(RangeSelectorTest,EncloseOpGeneral)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"));
302 }
303
TEST(RangeSelectorTest,EncloseOpNodesParsed)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"));
315 }
316
TEST(RangeSelectorTest,EncloseOpGeneralParsed)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"));
328 }
329
TEST(RangeSelectorTest,NodeOpStatement)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;"));
334 }
335
TEST(RangeSelectorTest,NodeOpExpression)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"));
340 }
341
TEST(RangeSelectorTest,StatementOp)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;"));
347 }
348
TEST(RangeSelectorTest,StatementOpParsed)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;"));
355 }
356
TEST(RangeSelectorTest,MemberOp)357 TEST(RangeSelectorTest, MemberOp) {
358 StringRef Code = R"cc(
359 struct S {
360 int member;
361 };
362 int g() {
363 S s;
364 return s.member;
365 }
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"));
370 }
371
372 // Tests that member does not select any qualifiers on the member name.
TEST(RangeSelectorTest,MemberOpQualified)373 TEST(RangeSelectorTest, MemberOpQualified) {
374 StringRef Code = R"cc(
375 struct S {
376 int member;
377 };
378 struct T : public S {
379 int field;
380 };
381 int g() {
382 T t;
383 return t.S::member;
384 }
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"));
389 }
390
TEST(RangeSelectorTest,MemberOpTemplate)391 TEST(RangeSelectorTest, MemberOpTemplate) {
392 StringRef Code = R"cc(
393 struct S {
394 template <typename T> T foo(T t);
395 };
396 int f(int x) {
397 S s;
398 return s.template foo<int>(3);
399 }
400 )cc";
401
402 const char *ID = "id";
403 TestMatch Match = matchCode(Code, memberExpr().bind(ID));
404 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo"));
405 }
406
TEST(RangeSelectorTest,MemberOpOperator)407 TEST(RangeSelectorTest, MemberOpOperator) {
408 StringRef Code = R"cc(
409 struct S {
410 int operator*();
411 };
412 int f(int x) {
413 S s;
414 return s.operator *();
415 }
416 )cc";
417
418 const char *ID = "id";
419 TestMatch Match = matchCode(Code, memberExpr().bind(ID));
420 EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *"));
421 }
422
TEST(RangeSelectorTest,NameOpNamedDecl)423 TEST(RangeSelectorTest, NameOpNamedDecl) {
424 StringRef Code = R"cc(
425 int myfun() {
426 return 3;
427 }
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"));
432 }
433
TEST(RangeSelectorTest,NameOpDeclRef)434 TEST(RangeSelectorTest, NameOpDeclRef) {
435 StringRef Code = R"cc(
436 int foo(int x) {
437 return x;
438 }
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"));
444 }
445
TEST(RangeSelectorTest,NameOpCtorInitializer)446 TEST(RangeSelectorTest, NameOpCtorInitializer) {
447 StringRef Code = R"cc(
448 class C {
449 public:
450 C() : field(3) {}
451 int field;
452 };
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"));
457 }
458
TEST(RangeSelectorTest,NameOpTypeLoc)459 TEST(RangeSelectorTest, NameOpTypeLoc) {
460 StringRef Code = R"cc(
461 namespace ns {
462 struct Foo {
463 Foo();
464 Foo(int);
465 Foo(int, int);
466 };
467 } // namespace ns
468
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"));
486 }
487
TEST(RangeSelectorTest,NameOpTemplateSpecializationTypeLoc)488 TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) {
489 StringRef Code = R"cc(
490 namespace ns {
491 template <typename T>
492 struct Foo {};
493 } // namespace ns
494
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"));
502 }
503
TEST(RangeSelectorTest,NameOpErrors)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")));
509 }
510
TEST(RangeSelectorTest,NameOpDeclRefError)511 TEST(RangeSelectorTest, NameOpDeclRefError) {
512 StringRef Code = R"cc(
513 struct S {
514 int operator*();
515 };
516 int f(int x) {
517 S s;
518 return *s + x;
519 }
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'")))));
528 }
529
TEST(RangeSelectorTest,CallArgsOp)530 TEST(RangeSelectorTest, CallArgsOp) {
531 const StringRef Code = R"cc(
532 struct C {
533 int bar(int, int);
534 };
535 int f() {
536 C x;
537 return x.bar(3, 4);
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("3, 4"));
543 }
544
TEST(RangeSelectorTest,CallArgsOpNoArgs)545 TEST(RangeSelectorTest, CallArgsOpNoArgs) {
546 const StringRef Code = R"cc(
547 struct C {
548 int bar();
549 };
550 int f() {
551 C x;
552 return x.bar();
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(""));
558 }
559
TEST(RangeSelectorTest,CallArgsOpNoArgsWithComments)560 TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) {
561 const StringRef Code = R"cc(
562 struct C {
563 int bar();
564 };
565 int f() {
566 C x;
567 return x.bar(/*empty*/);
568 }
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*/"));
573 }
574
575 // Tests that arguments are extracted correctly when a temporary (with parens)
576 // is used.
TEST(RangeSelectorTest,CallArgsOpWithParens)577 TEST(RangeSelectorTest, CallArgsOpWithParens) {
578 const StringRef Code = R"cc(
579 struct C {
580 int bar(int, int) { return 3; }
581 };
582 int f() {
583 C x;
584 return C().bar(3, 4);
585 }
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"));
591 }
592
TEST(RangeSelectorTest,CallArgsOpLeadingComments)593 TEST(RangeSelectorTest, CallArgsOpLeadingComments) {
594 const StringRef Code = R"cc(
595 struct C {
596 int bar(int, int) { return 3; }
597 };
598 int f() {
599 C x;
600 return x.bar(/*leading*/ 3, 4);
601 }
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"));
607 }
608
TEST(RangeSelectorTest,CallArgsOpTrailingComments)609 TEST(RangeSelectorTest, CallArgsOpTrailingComments) {
610 const StringRef Code = R"cc(
611 struct C {
612 int bar(int, int) { return 3; }
613 };
614 int f() {
615 C x;
616 return x.bar(3 /*trailing*/, 4);
617 }
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"));
623 }
624
TEST(RangeSelectorTest,CallArgsOpEolComments)625 TEST(RangeSelectorTest, CallArgsOpEolComments) {
626 const StringRef Code = R"cc(
627 struct C {
628 int bar(int, int) { return 3; }
629 };
630 int f() {
631 C x;
632 return x.bar( // Header
633 1, // foo
634 2 // bar
635 );
636 }
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
643 )";
644 EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString));
645 }
646
TEST(RangeSelectorTest,CallArgsErrors)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")));
652 }
653
TEST(RangeSelectorTest,ConstructExprArgs)654 TEST(RangeSelectorTest, ConstructExprArgs) {
655 const StringRef Code = R"cc(
656 struct C {
657 C(int, int);
658 };
659 C f() {
660 return C(1, 2);
661 }
662 )cc";
663 const char *ID = "id";
664 TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));
665 EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));
666 }
667
TEST(RangeSelectorTest,ConstructExprBracedArgs)668 TEST(RangeSelectorTest, ConstructExprBracedArgs) {
669 const StringRef Code = R"cc(
670 struct C {
671 C(int, int);
672 };
673 C f() {
674 return {1, 2};
675 }
676 )cc";
677 const char *ID = "id";
678 TestMatch Match = matchCode(Code, cxxConstructExpr().bind(ID));
679 EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));
680 }
681
TEST(RangeSelectorTest,ConstructExprNoArgs)682 TEST(RangeSelectorTest, ConstructExprNoArgs) {
683 const StringRef Code = R"cc(
684 struct C {
685 C();
686 };
687 C f() {
688 return C();
689 }
690 )cc";
691 const char *ID = "id";
692 TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));
693 EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue(""));
694 }
695
TEST(RangeSelectorTest,StatementsOp)696 TEST(RangeSelectorTest, StatementsOp) {
697 StringRef Code = R"cc(
698 void g();
699 void f() { /* comment */ g(); /* comment */ g(); /* comment */ }
700 )cc";
701 const char *ID = "id";
702 TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
703 EXPECT_THAT_EXPECTED(
704 select(statements(ID), Match),
705 HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ "));
706 }
707
TEST(RangeSelectorTest,StatementsOpEmptyList)708 TEST(RangeSelectorTest, StatementsOpEmptyList) {
709 StringRef Code = "void f() {}";
710 const char *ID = "id";
711 TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
712 EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue(""));
713 }
714
TEST(RangeSelectorTest,StatementsOpErrors)715 TEST(RangeSelectorTest, StatementsOpErrors) {
716 EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")),
717 Failed<StringError>(withUnboundNodeMessage()));
718 EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")),
719 Failed<StringError>(withTypeErrorMessage("decl")));
720 }
721
TEST(RangeSelectorTest,ElementsOp)722 TEST(RangeSelectorTest, ElementsOp) {
723 StringRef Code = R"cc(
724 void f() {
725 int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};
726 (void)v;
727 }
728 )cc";
729 const char *ID = "id";
730 TestMatch Match = matchCode(Code, initListExpr().bind(ID));
731 EXPECT_THAT_EXPECTED(
732 select(initListElements(ID), Match),
733 HasValue("/* comment */ 3, /* comment*/ 4 /* comment */"));
734 }
735
TEST(RangeSelectorTest,ElementsOpEmptyList)736 TEST(RangeSelectorTest, ElementsOpEmptyList) {
737 StringRef Code = R"cc(
738 void f() {
739 int v[] = {};
740 (void)v;
741 }
742 )cc";
743 const char *ID = "id";
744 TestMatch Match = matchCode(Code, initListExpr().bind(ID));
745 EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue(""));
746 }
747
TEST(RangeSelectorTest,ElementsOpErrors)748 TEST(RangeSelectorTest, ElementsOpErrors) {
749 EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")),
750 Failed<StringError>(withUnboundNodeMessage()));
751 EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")),
752 Failed<StringError>(withTypeErrorMessage("stmt")));
753 }
754
TEST(RangeSelectorTest,ElseBranchOpSingleStatement)755 TEST(RangeSelectorTest, ElseBranchOpSingleStatement) {
756 StringRef Code = R"cc(
757 int f() {
758 int x = 0;
759 if (true) x = 3;
760 else x = 4;
761 return x + 5;
762 }
763 )cc";
764 const char *ID = "id";
765 TestMatch Match = matchCode(Code, ifStmt().bind(ID));
766 EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;"));
767 }
768
TEST(RangeSelectorTest,ElseBranchOpCompoundStatement)769 TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) {
770 StringRef Code = R"cc(
771 int f() {
772 int x = 0;
773 if (true) x = 3;
774 else { x = 4; }
775 return x + 5;
776 }
777 )cc";
778 const char *ID = "id";
779 TestMatch Match = matchCode(Code, ifStmt().bind(ID));
780 EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match),
781 HasValue("else { x = 4; }"));
782 }
783
784 // Tests case where the matched node is the complete expanded text.
TEST(RangeSelectorTest,ExpansionOp)785 TEST(RangeSelectorTest, ExpansionOp) {
786 StringRef Code = R"cc(
787 #define BADDECL(E) int bad(int x) { return E; }
788 BADDECL(x * x)
789 )cc";
790
791 const char *Fun = "Fun";
792 TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun));
793 EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match),
794 HasValue("BADDECL(x * x)"));
795 }
796
797 // Tests case where the matched node is (only) part of the expanded text.
TEST(RangeSelectorTest,ExpansionOpPartial)798 TEST(RangeSelectorTest, ExpansionOpPartial) {
799 StringRef Code = R"cc(
800 #define BADDECL(E) int bad(int x) { return E; }
801 BADDECL(x * x)
802 )cc";
803
804 const char *Ret = "Ret";
805 TestMatch Match = matchCode(Code, returnStmt().bind(Ret));
806 EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match),
807 HasValue("BADDECL(x * x)"));
808 }
809
TEST(RangeSelectorTest,IfBoundOpBound)810 TEST(RangeSelectorTest, IfBoundOpBound) {
811 StringRef Code = R"cc(
812 int f() {
813 return 3 + 5;
814 }
815 )cc";
816 const char *ID = "id", *Op = "op";
817 TestMatch Match =
818 matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));
819 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
820 HasValue("3"));
821 }
822
TEST(RangeSelectorTest,IfBoundOpUnbound)823 TEST(RangeSelectorTest, IfBoundOpUnbound) {
824 StringRef Code = R"cc(
825 int f() {
826 return 3 + 5;
827 }
828 )cc";
829 const char *ID = "id", *Op = "op";
830 TestMatch Match = matchCode(Code, binaryOperator().bind(Op));
831 EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
832 HasValue("3 + 5"));
833 }
834
835 } // namespace
836