127872b8dSYitzhak Mandelbaum //===- unittest/Tooling/RangeSelectorTest.cpp -----------------------------===//
227872b8dSYitzhak Mandelbaum //
327872b8dSYitzhak Mandelbaum // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
427872b8dSYitzhak Mandelbaum // See https://llvm.org/LICENSE.txt for license information.
527872b8dSYitzhak Mandelbaum // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
627872b8dSYitzhak Mandelbaum //
727872b8dSYitzhak Mandelbaum //===----------------------------------------------------------------------===//
827872b8dSYitzhak Mandelbaum
9fbdf8352SYitzhak Mandelbaum #include "clang/Tooling/Transformer/RangeSelector.h"
1027872b8dSYitzhak Mandelbaum #include "clang/ASTMatchers/ASTMatchers.h"
11ef29c6a6SYitzhak Mandelbaum #include "clang/Frontend/ASTUnit.h"
1227872b8dSYitzhak Mandelbaum #include "clang/Tooling/Tooling.h"
139ca50e88SYitzhak Mandelbaum #include "clang/Tooling/Transformer/Parsing.h"
148bb47cd8SYitzhak Mandelbaum #include "clang/Tooling/Transformer/SourceCode.h"
1527872b8dSYitzhak Mandelbaum #include "llvm/Support/Error.h"
1627872b8dSYitzhak Mandelbaum #include "llvm/Testing/Support/Error.h"
1727872b8dSYitzhak Mandelbaum #include "gmock/gmock.h"
1827872b8dSYitzhak Mandelbaum #include "gtest/gtest.h"
1927872b8dSYitzhak Mandelbaum
2027872b8dSYitzhak Mandelbaum using namespace clang;
218bb47cd8SYitzhak Mandelbaum using namespace transformer;
2227872b8dSYitzhak Mandelbaum using namespace ast_matchers;
2327872b8dSYitzhak Mandelbaum
2427872b8dSYitzhak Mandelbaum namespace {
2527872b8dSYitzhak Mandelbaum using ::llvm::Expected;
2627872b8dSYitzhak Mandelbaum using ::llvm::Failed;
2727872b8dSYitzhak Mandelbaum using ::llvm::HasValue;
2827872b8dSYitzhak Mandelbaum using ::llvm::StringError;
29e1312c54SYitzhak Mandelbaum using ::testing::AllOf;
30e1312c54SYitzhak Mandelbaum using ::testing::HasSubstr;
31e1312c54SYitzhak Mandelbaum
32e1312c54SYitzhak Mandelbaum using MatchResult = MatchFinder::MatchResult;
3327872b8dSYitzhak Mandelbaum
3427872b8dSYitzhak Mandelbaum struct TestMatch {
3527872b8dSYitzhak Mandelbaum // The AST unit from which `result` is built. We bundle it because it backs
3627872b8dSYitzhak Mandelbaum // the result. Users are not expected to access it.
37ef29c6a6SYitzhak Mandelbaum std::unique_ptr<clang::ASTUnit> ASTUnit;
3827872b8dSYitzhak Mandelbaum // The result to use in the test. References `ast_unit`.
3927872b8dSYitzhak Mandelbaum MatchResult Result;
4027872b8dSYitzhak Mandelbaum };
4127872b8dSYitzhak Mandelbaum
matchCode(StringRef Code,M Matcher)4227872b8dSYitzhak Mandelbaum template <typename M> TestMatch matchCode(StringRef Code, M Matcher) {
438bb47cd8SYitzhak Mandelbaum auto ASTUnit = tooling::buildASTFromCode(Code);
4427872b8dSYitzhak Mandelbaum assert(ASTUnit != nullptr && "AST construction failed");
4527872b8dSYitzhak Mandelbaum
4627872b8dSYitzhak Mandelbaum ASTContext &Context = ASTUnit->getASTContext();
4727872b8dSYitzhak Mandelbaum assert(!Context.getDiagnostics().hasErrorOccurred() && "Compilation error");
4827872b8dSYitzhak Mandelbaum
49027899daSAlexander Kornienko TraversalKindScope RAII(Context, TK_AsIs);
5027872b8dSYitzhak Mandelbaum auto Matches = ast_matchers::match(Matcher, Context);
5127872b8dSYitzhak Mandelbaum // We expect a single, exact match.
5227872b8dSYitzhak Mandelbaum assert(Matches.size() != 0 && "no matches found");
5327872b8dSYitzhak Mandelbaum assert(Matches.size() == 1 && "too many matches");
5427872b8dSYitzhak Mandelbaum
5527872b8dSYitzhak Mandelbaum return TestMatch{std::move(ASTUnit), MatchResult(Matches[0], &Context)};
5627872b8dSYitzhak Mandelbaum }
5727872b8dSYitzhak Mandelbaum
5827872b8dSYitzhak Mandelbaum // Applies \p Selector to \p Match and, on success, returns the selected source.
select(RangeSelector Selector,const TestMatch & Match)5976e3a049SDmitri Gribenko Expected<StringRef> select(RangeSelector Selector, const TestMatch &Match) {
6027872b8dSYitzhak Mandelbaum Expected<CharSourceRange> Range = Selector(Match.Result);
6127872b8dSYitzhak Mandelbaum if (!Range)
6227872b8dSYitzhak Mandelbaum return Range.takeError();
638bb47cd8SYitzhak Mandelbaum return tooling::getText(*Range, *Match.Result.Context);
6427872b8dSYitzhak Mandelbaum }
6527872b8dSYitzhak Mandelbaum
6627872b8dSYitzhak Mandelbaum // Applies \p Selector to a trivial match with only a single bound node with id
6727872b8dSYitzhak Mandelbaum // "bound_node_id". For use in testing unbound-node errors.
selectFromTrivial(const RangeSelector & Selector)6876e3a049SDmitri Gribenko Expected<CharSourceRange> selectFromTrivial(const RangeSelector &Selector) {
6927872b8dSYitzhak Mandelbaum // We need to bind the result to something, or the match will fail. Use a
7027872b8dSYitzhak Mandelbaum // binding that is not used in the unbound node tests.
7127872b8dSYitzhak Mandelbaum TestMatch Match =
7227872b8dSYitzhak Mandelbaum matchCode("static int x = 0;", varDecl().bind("bound_node_id"));
7327872b8dSYitzhak Mandelbaum return Selector(Match.Result);
7427872b8dSYitzhak Mandelbaum }
7527872b8dSYitzhak Mandelbaum
7627872b8dSYitzhak Mandelbaum // Matches the message expected for unbound-node failures.
withUnboundNodeMessage()7727872b8dSYitzhak Mandelbaum testing::Matcher<StringError> withUnboundNodeMessage() {
7827872b8dSYitzhak Mandelbaum return testing::Property(
7927872b8dSYitzhak Mandelbaum &StringError::getMessage,
8027872b8dSYitzhak Mandelbaum AllOf(HasSubstr("unbound_id"), HasSubstr("not bound")));
8127872b8dSYitzhak Mandelbaum }
8227872b8dSYitzhak Mandelbaum
8327872b8dSYitzhak Mandelbaum // Applies \p Selector to code containing assorted node types, where the match
8427872b8dSYitzhak Mandelbaum // binds each one: a statement ("stmt"), a (non-member) ctor-initializer
8527872b8dSYitzhak Mandelbaum // ("init"), an expression ("expr") and a (nameless) declaration ("decl"). Used
8627872b8dSYitzhak Mandelbaum // to test failures caused by applying selectors to nodes of the wrong type.
selectFromAssorted(RangeSelector Selector)8776e3a049SDmitri Gribenko Expected<CharSourceRange> selectFromAssorted(RangeSelector Selector) {
8827872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
8927872b8dSYitzhak Mandelbaum struct A {};
9027872b8dSYitzhak Mandelbaum class F : public A {
9127872b8dSYitzhak Mandelbaum public:
9227872b8dSYitzhak Mandelbaum F(int) {}
9327872b8dSYitzhak Mandelbaum };
9427872b8dSYitzhak Mandelbaum void g() { F f(1); }
9527872b8dSYitzhak Mandelbaum )cc";
9627872b8dSYitzhak Mandelbaum
9727872b8dSYitzhak Mandelbaum auto Matcher =
9827872b8dSYitzhak Mandelbaum compoundStmt(
9927872b8dSYitzhak Mandelbaum hasDescendant(
10027872b8dSYitzhak Mandelbaum cxxConstructExpr(
10127872b8dSYitzhak Mandelbaum hasDeclaration(
10227872b8dSYitzhak Mandelbaum decl(hasDescendant(cxxCtorInitializer(isBaseInitializer())
10327872b8dSYitzhak Mandelbaum .bind("init")))
10427872b8dSYitzhak Mandelbaum .bind("decl")))
10527872b8dSYitzhak Mandelbaum .bind("expr")))
10627872b8dSYitzhak Mandelbaum .bind("stmt");
10727872b8dSYitzhak Mandelbaum
10827872b8dSYitzhak Mandelbaum return Selector(matchCode(Code, Matcher).Result);
10927872b8dSYitzhak Mandelbaum }
11027872b8dSYitzhak Mandelbaum
11127872b8dSYitzhak Mandelbaum // Matches the message expected for type-error failures.
withTypeErrorMessage(const std::string & NodeID)112adcd0268SBenjamin Kramer testing::Matcher<StringError> withTypeErrorMessage(const std::string &NodeID) {
11327872b8dSYitzhak Mandelbaum return testing::Property(
11427872b8dSYitzhak Mandelbaum &StringError::getMessage,
11527872b8dSYitzhak Mandelbaum AllOf(HasSubstr(NodeID), HasSubstr("mismatched type")));
11627872b8dSYitzhak Mandelbaum }
11727872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,UnboundNode)11827872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, UnboundNode) {
11976e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromTrivial(node("unbound_id")),
12027872b8dSYitzhak Mandelbaum Failed<StringError>(withUnboundNodeMessage()));
12127872b8dSYitzhak Mandelbaum }
12227872b8dSYitzhak Mandelbaum
123e1312c54SYitzhak Mandelbaum MATCHER_P(EqualsCharSourceRange, Range, "") {
124e1312c54SYitzhak Mandelbaum return Range.getAsRange() == arg.getAsRange() &&
125e1312c54SYitzhak Mandelbaum Range.isTokenRange() == arg.isTokenRange();
126e1312c54SYitzhak Mandelbaum }
127e1312c54SYitzhak Mandelbaum
128e1312c54SYitzhak Mandelbaum // FIXME: here and elsewhere: use llvm::Annotations library to explicitly mark
129e1312c54SYitzhak Mandelbaum // points and ranges of interest, enabling more readable tests.
TEST(RangeSelectorTest,BeforeOp)130e1312c54SYitzhak Mandelbaum TEST(RangeSelectorTest, BeforeOp) {
131e1312c54SYitzhak Mandelbaum StringRef Code = R"cc(
132e1312c54SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
133e1312c54SYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
134e1312c54SYitzhak Mandelbaum )cc";
1359ca50e88SYitzhak Mandelbaum StringRef CallID = "call";
1369ca50e88SYitzhak Mandelbaum ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID);
1379ca50e88SYitzhak Mandelbaum RangeSelector R = before(node(CallID.str()));
1389ca50e88SYitzhak Mandelbaum
1399ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, M);
1409ca50e88SYitzhak Mandelbaum const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID);
141e1312c54SYitzhak Mandelbaum assert(E != nullptr);
142e1312c54SYitzhak Mandelbaum auto ExprBegin = E->getSourceRange().getBegin();
143e1312c54SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(
1449ca50e88SYitzhak Mandelbaum R(Match.Result),
1459ca50e88SYitzhak Mandelbaum HasValue(EqualsCharSourceRange(
1469ca50e88SYitzhak Mandelbaum CharSourceRange::getCharRange(ExprBegin, ExprBegin))));
1479ca50e88SYitzhak Mandelbaum }
1489ca50e88SYitzhak Mandelbaum
TEST(RangeSelectorTest,BeforeOpParsed)1499ca50e88SYitzhak Mandelbaum TEST(RangeSelectorTest, BeforeOpParsed) {
1509ca50e88SYitzhak Mandelbaum StringRef Code = R"cc(
1519ca50e88SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
1529ca50e88SYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
1539ca50e88SYitzhak Mandelbaum )cc";
1549ca50e88SYitzhak Mandelbaum StringRef CallID = "call";
1559ca50e88SYitzhak Mandelbaum ast_matchers::internal::Matcher<Stmt> M = callExpr().bind(CallID);
1569ca50e88SYitzhak Mandelbaum auto R = parseRangeSelector(R"rs(before(node("call")))rs");
1579ca50e88SYitzhak Mandelbaum ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
1589ca50e88SYitzhak Mandelbaum
1599ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, M);
1609ca50e88SYitzhak Mandelbaum const auto *E = Match.Result.Nodes.getNodeAs<Expr>(CallID);
1619ca50e88SYitzhak Mandelbaum assert(E != nullptr);
1629ca50e88SYitzhak Mandelbaum auto ExprBegin = E->getSourceRange().getBegin();
1639ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(
1649ca50e88SYitzhak Mandelbaum (*R)(Match.Result),
165e1312c54SYitzhak Mandelbaum HasValue(EqualsCharSourceRange(
166e1312c54SYitzhak Mandelbaum CharSourceRange::getCharRange(ExprBegin, ExprBegin))));
167e1312c54SYitzhak Mandelbaum }
168e1312c54SYitzhak Mandelbaum
TEST(RangeSelectorTest,AfterOp)169e1312c54SYitzhak Mandelbaum TEST(RangeSelectorTest, AfterOp) {
170e1312c54SYitzhak Mandelbaum StringRef Code = R"cc(
171e1312c54SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
172e1312c54SYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
173e1312c54SYitzhak Mandelbaum )cc";
174e1312c54SYitzhak Mandelbaum StringRef Call = "call";
175e1312c54SYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(Call));
176e1312c54SYitzhak Mandelbaum const auto* E = Match.Result.Nodes.getNodeAs<Expr>(Call);
177e1312c54SYitzhak Mandelbaum assert(E != nullptr);
178e1312c54SYitzhak Mandelbaum const SourceRange Range = E->getSourceRange();
179e1312c54SYitzhak Mandelbaum // The end token, a right paren, is one character wide, so advance by one,
180e1312c54SYitzhak Mandelbaum // bringing us to the semicolon.
181e1312c54SYitzhak Mandelbaum const SourceLocation SemiLoc = Range.getEnd().getLocWithOffset(1);
182e1312c54SYitzhak Mandelbaum const auto ExpectedAfter = CharSourceRange::getCharRange(SemiLoc, SemiLoc);
183e1312c54SYitzhak Mandelbaum
184e1312c54SYitzhak Mandelbaum // Test with a char range.
185e1312c54SYitzhak Mandelbaum auto CharRange = CharSourceRange::getCharRange(Range.getBegin(), SemiLoc);
186e1312c54SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(after(charRange(CharRange))(Match.Result),
187e1312c54SYitzhak Mandelbaum HasValue(EqualsCharSourceRange(ExpectedAfter)));
188e1312c54SYitzhak Mandelbaum
189e1312c54SYitzhak Mandelbaum // Test with a token range.
190e1312c54SYitzhak Mandelbaum auto TokenRange = CharSourceRange::getTokenRange(Range);
191e1312c54SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(after(charRange(TokenRange))(Match.Result),
192e1312c54SYitzhak Mandelbaum HasValue(EqualsCharSourceRange(ExpectedAfter)));
193e1312c54SYitzhak Mandelbaum }
194e1312c54SYitzhak Mandelbaum
19565cb4fddSYitzhak Mandelbaum // Gets the spelling location `Length` characters after the start of AST node
19665cb4fddSYitzhak Mandelbaum // `Id`.
getSpellingLocAfter(const MatchResult & Result,StringRef Id,int Length)19765cb4fddSYitzhak Mandelbaum static SourceLocation getSpellingLocAfter(const MatchResult &Result,
19865cb4fddSYitzhak Mandelbaum StringRef Id, int Length) {
19965cb4fddSYitzhak Mandelbaum const auto *E = Result.Nodes.getNodeAs<Expr>(Id);
20065cb4fddSYitzhak Mandelbaum assert(E != nullptr);
20165cb4fddSYitzhak Mandelbaum return Result.SourceManager->getSpellingLoc(E->getBeginLoc())
20265cb4fddSYitzhak Mandelbaum .getLocWithOffset(Length);
20365cb4fddSYitzhak Mandelbaum }
20465cb4fddSYitzhak Mandelbaum
20565cb4fddSYitzhak Mandelbaum // Test with a range that is the entire macro arg, but does not end the
20665cb4fddSYitzhak Mandelbaum // expansion itself.
TEST(RangeSelectorTest,AfterOpInMacroArg)20765cb4fddSYitzhak Mandelbaum TEST(RangeSelectorTest, AfterOpInMacroArg) {
20865cb4fddSYitzhak Mandelbaum StringRef Code = R"cc(
20965cb4fddSYitzhak Mandelbaum #define ISNULL(x) x == nullptr
21065cb4fddSYitzhak Mandelbaum bool g() { int* y; return ISNULL(y); }
21165cb4fddSYitzhak Mandelbaum )cc";
21265cb4fddSYitzhak Mandelbaum
21365cb4fddSYitzhak Mandelbaum TestMatch Match =
21465cb4fddSYitzhak Mandelbaum matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
21565cb4fddSYitzhak Mandelbaum int YVarLen = 1;
21665cb4fddSYitzhak Mandelbaum SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);
21765cb4fddSYitzhak Mandelbaum CharSourceRange Expected = CharSourceRange::getCharRange(After, After);
21865cb4fddSYitzhak Mandelbaum EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),
21965cb4fddSYitzhak Mandelbaum HasValue(EqualsCharSourceRange(Expected)));
22065cb4fddSYitzhak Mandelbaum }
22165cb4fddSYitzhak Mandelbaum
22265cb4fddSYitzhak Mandelbaum // Test with a range that is the entire macro arg and ends the expansion itself.
TEST(RangeSelectorTest,AfterOpInMacroArgEndsExpansion)22365cb4fddSYitzhak Mandelbaum TEST(RangeSelectorTest, AfterOpInMacroArgEndsExpansion) {
22465cb4fddSYitzhak Mandelbaum StringRef Code = R"cc(
22565cb4fddSYitzhak Mandelbaum #define ISNULL(x) nullptr == x
22665cb4fddSYitzhak Mandelbaum bool g() { int* y; return ISNULL(y); }
22765cb4fddSYitzhak Mandelbaum )cc";
22865cb4fddSYitzhak Mandelbaum
22965cb4fddSYitzhak Mandelbaum TestMatch Match =
23065cb4fddSYitzhak Mandelbaum matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
23165cb4fddSYitzhak Mandelbaum int YVarLen = 1;
23265cb4fddSYitzhak Mandelbaum SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);
23365cb4fddSYitzhak Mandelbaum CharSourceRange Expected = CharSourceRange::getCharRange(After, After);
23465cb4fddSYitzhak Mandelbaum EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),
23565cb4fddSYitzhak Mandelbaum HasValue(EqualsCharSourceRange(Expected)));
23665cb4fddSYitzhak Mandelbaum }
23765cb4fddSYitzhak Mandelbaum
TEST(RangeSelectorTest,AfterOpInPartOfMacroArg)23865cb4fddSYitzhak Mandelbaum TEST(RangeSelectorTest, AfterOpInPartOfMacroArg) {
23965cb4fddSYitzhak Mandelbaum StringRef Code = R"cc(
24065cb4fddSYitzhak Mandelbaum #define ISNULL(x) x == nullptr
24165cb4fddSYitzhak Mandelbaum int* f(int*);
24265cb4fddSYitzhak Mandelbaum bool g() { int* y; return ISNULL(f(y)); }
24365cb4fddSYitzhak Mandelbaum )cc";
24465cb4fddSYitzhak Mandelbaum
24565cb4fddSYitzhak Mandelbaum TestMatch Match =
24665cb4fddSYitzhak Mandelbaum matchCode(Code, declRefExpr(to(namedDecl(hasName("y")))).bind("yvar"));
24765cb4fddSYitzhak Mandelbaum int YVarLen = 1;
24865cb4fddSYitzhak Mandelbaum SourceLocation After = getSpellingLocAfter(Match.Result, "yvar", YVarLen);
24965cb4fddSYitzhak Mandelbaum CharSourceRange Expected = CharSourceRange::getCharRange(After, After);
25065cb4fddSYitzhak Mandelbaum EXPECT_THAT_EXPECTED(after(node("yvar"))(Match.Result),
25165cb4fddSYitzhak Mandelbaum HasValue(EqualsCharSourceRange(Expected)));
25265cb4fddSYitzhak Mandelbaum }
25365cb4fddSYitzhak Mandelbaum
TEST(RangeSelectorTest,BetweenOp)25404a21318SYitzhak Mandelbaum TEST(RangeSelectorTest, BetweenOp) {
25504a21318SYitzhak Mandelbaum StringRef Code = R"cc(
25604a21318SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
25704a21318SYitzhak Mandelbaum int g() { return f(3, /* comment */ 7 /* comment */, 9); }
25804a21318SYitzhak Mandelbaum )cc";
25904a21318SYitzhak Mandelbaum auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
26004a21318SYitzhak Mandelbaum hasArgument(1, expr().bind("a1")));
26104a21318SYitzhak Mandelbaum RangeSelector R = between(node("a0"), node("a1"));
26204a21318SYitzhak Mandelbaum TestMatch Match = matchCode(Code, Matcher);
26304a21318SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(R, Match), HasValue(", /* comment */ "));
26404a21318SYitzhak Mandelbaum }
26504a21318SYitzhak Mandelbaum
TEST(RangeSelectorTest,BetweenOpParsed)26604a21318SYitzhak Mandelbaum TEST(RangeSelectorTest, BetweenOpParsed) {
26704a21318SYitzhak Mandelbaum StringRef Code = R"cc(
26804a21318SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
26904a21318SYitzhak Mandelbaum int g() { return f(3, /* comment */ 7 /* comment */, 9); }
27004a21318SYitzhak Mandelbaum )cc";
27104a21318SYitzhak Mandelbaum auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
27204a21318SYitzhak Mandelbaum hasArgument(1, expr().bind("a1")));
27304a21318SYitzhak Mandelbaum auto R = parseRangeSelector(R"rs(between(node("a0"), node("a1")))rs");
27404a21318SYitzhak Mandelbaum ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
27504a21318SYitzhak Mandelbaum TestMatch Match = matchCode(Code, Matcher);
27604a21318SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(*R, Match), HasValue(", /* comment */ "));
27704a21318SYitzhak Mandelbaum }
27804a21318SYitzhak Mandelbaum
2799ca50e88SYitzhak Mandelbaum // Node-id specific version.
TEST(RangeSelectorTest,EncloseOpNodes)28004a21318SYitzhak Mandelbaum TEST(RangeSelectorTest, EncloseOpNodes) {
28127872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
28227872b8dSYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
28327872b8dSYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
28427872b8dSYitzhak Mandelbaum )cc";
2859ca50e88SYitzhak Mandelbaum auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
2869ca50e88SYitzhak Mandelbaum hasArgument(1, expr().bind("a1")));
287056a539eSYitzhak Mandelbaum RangeSelector R = encloseNodes("a0", "a1");
28827872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, Matcher);
2899ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));
2909ca50e88SYitzhak Mandelbaum }
29127872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,EncloseOpGeneral)29204a21318SYitzhak Mandelbaum TEST(RangeSelectorTest, EncloseOpGeneral) {
2939ca50e88SYitzhak Mandelbaum StringRef Code = R"cc(
2949ca50e88SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
2959ca50e88SYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
2969ca50e88SYitzhak Mandelbaum )cc";
2979ca50e88SYitzhak Mandelbaum auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
2989ca50e88SYitzhak Mandelbaum hasArgument(1, expr().bind("a1")));
299056a539eSYitzhak Mandelbaum RangeSelector R = enclose(node("a0"), node("a1"));
3009ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, Matcher);
3019ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3, 7"));
3029ca50e88SYitzhak Mandelbaum }
3039ca50e88SYitzhak Mandelbaum
TEST(RangeSelectorTest,EncloseOpNodesParsed)30404a21318SYitzhak Mandelbaum TEST(RangeSelectorTest, EncloseOpNodesParsed) {
3059ca50e88SYitzhak Mandelbaum StringRef Code = R"cc(
3069ca50e88SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
3079ca50e88SYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
3089ca50e88SYitzhak Mandelbaum )cc";
3099ca50e88SYitzhak Mandelbaum auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
3109ca50e88SYitzhak Mandelbaum hasArgument(1, expr().bind("a1")));
3119ca50e88SYitzhak Mandelbaum auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs");
3129ca50e88SYitzhak Mandelbaum ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
3139ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, Matcher);
3149ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));
3159ca50e88SYitzhak Mandelbaum }
3169ca50e88SYitzhak Mandelbaum
TEST(RangeSelectorTest,EncloseOpGeneralParsed)31704a21318SYitzhak Mandelbaum TEST(RangeSelectorTest, EncloseOpGeneralParsed) {
3189ca50e88SYitzhak Mandelbaum StringRef Code = R"cc(
3199ca50e88SYitzhak Mandelbaum int f(int x, int y, int z) { return 3; }
3209ca50e88SYitzhak Mandelbaum int g() { return f(/* comment */ 3, 7 /* comment */, 9); }
3219ca50e88SYitzhak Mandelbaum )cc";
3229ca50e88SYitzhak Mandelbaum auto Matcher = callExpr(hasArgument(0, expr().bind("a0")),
3239ca50e88SYitzhak Mandelbaum hasArgument(1, expr().bind("a1")));
3249ca50e88SYitzhak Mandelbaum auto R = parseRangeSelector(R"rs(encloseNodes("a0", "a1"))rs");
3259ca50e88SYitzhak Mandelbaum ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
3269ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, Matcher);
3279ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3, 7"));
32827872b8dSYitzhak Mandelbaum }
32927872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NodeOpStatement)33027872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NodeOpStatement) {
33127872b8dSYitzhak Mandelbaum StringRef Code = "int f() { return 3; }";
3329ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, returnStmt().bind("id"));
3339ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("return 3;"));
33427872b8dSYitzhak Mandelbaum }
33527872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NodeOpExpression)33627872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NodeOpExpression) {
33727872b8dSYitzhak Mandelbaum StringRef Code = "int f() { return 3; }";
3389ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, expr().bind("id"));
3399ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(node("id"), Match), HasValue("3"));
34027872b8dSYitzhak Mandelbaum }
34127872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,StatementOp)34227872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, StatementOp) {
34327872b8dSYitzhak Mandelbaum StringRef Code = "int f() { return 3; }";
3449ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, expr().bind("id"));
3459ca50e88SYitzhak Mandelbaum RangeSelector R = statement("id");
3469ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(R, Match), HasValue("3;"));
3479ca50e88SYitzhak Mandelbaum }
3489ca50e88SYitzhak Mandelbaum
TEST(RangeSelectorTest,StatementOpParsed)3499ca50e88SYitzhak Mandelbaum TEST(RangeSelectorTest, StatementOpParsed) {
3509ca50e88SYitzhak Mandelbaum StringRef Code = "int f() { return 3; }";
3519ca50e88SYitzhak Mandelbaum TestMatch Match = matchCode(Code, expr().bind("id"));
3529ca50e88SYitzhak Mandelbaum auto R = parseRangeSelector(R"rs(statement("id"))rs");
3539ca50e88SYitzhak Mandelbaum ASSERT_THAT_EXPECTED(R, llvm::Succeeded());
3549ca50e88SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(*R, Match), HasValue("3;"));
35527872b8dSYitzhak Mandelbaum }
35627872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,MemberOp)35727872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, MemberOp) {
35827872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
35927872b8dSYitzhak Mandelbaum struct S {
36027872b8dSYitzhak Mandelbaum int member;
36127872b8dSYitzhak Mandelbaum };
36227872b8dSYitzhak Mandelbaum int g() {
36327872b8dSYitzhak Mandelbaum S s;
36427872b8dSYitzhak Mandelbaum return s.member;
36527872b8dSYitzhak Mandelbaum }
36627872b8dSYitzhak Mandelbaum )cc";
367adcd0268SBenjamin Kramer const char *ID = "id";
36827872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, memberExpr().bind(ID));
36976e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));
37027872b8dSYitzhak Mandelbaum }
37127872b8dSYitzhak Mandelbaum
37227872b8dSYitzhak Mandelbaum // Tests that member does not select any qualifiers on the member name.
TEST(RangeSelectorTest,MemberOpQualified)37327872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, MemberOpQualified) {
37427872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
37527872b8dSYitzhak Mandelbaum struct S {
37627872b8dSYitzhak Mandelbaum int member;
37727872b8dSYitzhak Mandelbaum };
37827872b8dSYitzhak Mandelbaum struct T : public S {
37927872b8dSYitzhak Mandelbaum int field;
38027872b8dSYitzhak Mandelbaum };
38127872b8dSYitzhak Mandelbaum int g() {
38227872b8dSYitzhak Mandelbaum T t;
38327872b8dSYitzhak Mandelbaum return t.S::member;
38427872b8dSYitzhak Mandelbaum }
38527872b8dSYitzhak Mandelbaum )cc";
386adcd0268SBenjamin Kramer const char *ID = "id";
38727872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, memberExpr().bind(ID));
38876e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("member"));
38927872b8dSYitzhak Mandelbaum }
39027872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,MemberOpTemplate)39127872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, MemberOpTemplate) {
39227872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
39327872b8dSYitzhak Mandelbaum struct S {
39427872b8dSYitzhak Mandelbaum template <typename T> T foo(T t);
39527872b8dSYitzhak Mandelbaum };
39627872b8dSYitzhak Mandelbaum int f(int x) {
39727872b8dSYitzhak Mandelbaum S s;
39827872b8dSYitzhak Mandelbaum return s.template foo<int>(3);
39927872b8dSYitzhak Mandelbaum }
40027872b8dSYitzhak Mandelbaum )cc";
40127872b8dSYitzhak Mandelbaum
402adcd0268SBenjamin Kramer const char *ID = "id";
40327872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, memberExpr().bind(ID));
40476e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("foo"));
40527872b8dSYitzhak Mandelbaum }
40627872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,MemberOpOperator)40727872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, MemberOpOperator) {
40827872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
40927872b8dSYitzhak Mandelbaum struct S {
41027872b8dSYitzhak Mandelbaum int operator*();
41127872b8dSYitzhak Mandelbaum };
41227872b8dSYitzhak Mandelbaum int f(int x) {
41327872b8dSYitzhak Mandelbaum S s;
41427872b8dSYitzhak Mandelbaum return s.operator *();
41527872b8dSYitzhak Mandelbaum }
41627872b8dSYitzhak Mandelbaum )cc";
41727872b8dSYitzhak Mandelbaum
418adcd0268SBenjamin Kramer const char *ID = "id";
41927872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, memberExpr().bind(ID));
42076e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(member(ID), Match), HasValue("operator *"));
42127872b8dSYitzhak Mandelbaum }
42227872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NameOpNamedDecl)42327872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NameOpNamedDecl) {
42427872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
42527872b8dSYitzhak Mandelbaum int myfun() {
42627872b8dSYitzhak Mandelbaum return 3;
42727872b8dSYitzhak Mandelbaum }
42827872b8dSYitzhak Mandelbaum )cc";
429adcd0268SBenjamin Kramer const char *ID = "id";
43027872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, functionDecl().bind(ID));
43176e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("myfun"));
43227872b8dSYitzhak Mandelbaum }
43327872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NameOpDeclRef)43427872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NameOpDeclRef) {
43527872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
43627872b8dSYitzhak Mandelbaum int foo(int x) {
43727872b8dSYitzhak Mandelbaum return x;
43827872b8dSYitzhak Mandelbaum }
43927872b8dSYitzhak Mandelbaum int g(int x) { return foo(x) * x; }
44027872b8dSYitzhak Mandelbaum )cc";
441adcd0268SBenjamin Kramer const char *Ref = "ref";
44227872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));
44376e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(name(Ref), Match), HasValue("foo"));
44427872b8dSYitzhak Mandelbaum }
44527872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NameOpCtorInitializer)44627872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NameOpCtorInitializer) {
44727872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
44827872b8dSYitzhak Mandelbaum class C {
44927872b8dSYitzhak Mandelbaum public:
45027872b8dSYitzhak Mandelbaum C() : field(3) {}
45127872b8dSYitzhak Mandelbaum int field;
45227872b8dSYitzhak Mandelbaum };
45327872b8dSYitzhak Mandelbaum )cc";
454adcd0268SBenjamin Kramer const char *Init = "init";
45527872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, cxxCtorInitializer().bind(Init));
45676e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(name(Init), Match), HasValue("field"));
45727872b8dSYitzhak Mandelbaum }
45827872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NameOpTypeLoc)459be5c7c5dSWeston Carvalho TEST(RangeSelectorTest, NameOpTypeLoc) {
460be5c7c5dSWeston Carvalho StringRef Code = R"cc(
461be5c7c5dSWeston Carvalho namespace ns {
462be5c7c5dSWeston Carvalho struct Foo {
463be5c7c5dSWeston Carvalho Foo();
464be5c7c5dSWeston Carvalho Foo(int);
465be5c7c5dSWeston Carvalho Foo(int, int);
466be5c7c5dSWeston Carvalho };
467be5c7c5dSWeston Carvalho } // namespace ns
468be5c7c5dSWeston Carvalho
469be5c7c5dSWeston Carvalho ns::Foo a;
470be5c7c5dSWeston Carvalho auto b = ns::Foo(3);
471be5c7c5dSWeston Carvalho auto c = ns::Foo(1, 2);
472be5c7c5dSWeston Carvalho )cc";
473be5c7c5dSWeston Carvalho const char *CtorTy = "ctor_ty";
474be5c7c5dSWeston Carvalho // Matches declaration of `a`
475be5c7c5dSWeston Carvalho TestMatch MatchA = matchCode(
476be5c7c5dSWeston Carvalho Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(CtorTy))));
477be5c7c5dSWeston Carvalho EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchA), HasValue("Foo"));
478be5c7c5dSWeston Carvalho // Matches call of Foo(int)
479be5c7c5dSWeston Carvalho TestMatch MatchB = matchCode(
480be5c7c5dSWeston Carvalho Code, cxxFunctionalCastExpr(hasTypeLoc(typeLoc().bind(CtorTy))));
481be5c7c5dSWeston Carvalho EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchB), HasValue("Foo"));
482be5c7c5dSWeston Carvalho // Matches call of Foo(int, int)
483be5c7c5dSWeston Carvalho TestMatch MatchC = matchCode(
484be5c7c5dSWeston Carvalho Code, cxxTemporaryObjectExpr(hasTypeLoc(typeLoc().bind(CtorTy))));
485be5c7c5dSWeston Carvalho EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchC), HasValue("Foo"));
486be5c7c5dSWeston Carvalho }
487be5c7c5dSWeston Carvalho
TEST(RangeSelectorTest,NameOpTemplateSpecializationTypeLoc)488c7832581SYitzhak Mandelbaum TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) {
489c7832581SYitzhak Mandelbaum StringRef Code = R"cc(
490c7832581SYitzhak Mandelbaum namespace ns {
491c7832581SYitzhak Mandelbaum template <typename T>
492c7832581SYitzhak Mandelbaum struct Foo {};
493c7832581SYitzhak Mandelbaum } // namespace ns
494c7832581SYitzhak Mandelbaum
495c7832581SYitzhak Mandelbaum ns::Foo<int> a;
496c7832581SYitzhak Mandelbaum )cc";
497c7832581SYitzhak Mandelbaum const char *Loc = "tyloc";
498c7832581SYitzhak Mandelbaum // Matches declaration of `a`.
499c7832581SYitzhak Mandelbaum TestMatch MatchA =
500c7832581SYitzhak Mandelbaum matchCode(Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(Loc))));
501c7832581SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(name(Loc), MatchA), HasValue("Foo"));
502c7832581SYitzhak Mandelbaum }
503c7832581SYitzhak Mandelbaum
TEST(RangeSelectorTest,NameOpErrors)50427872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NameOpErrors) {
50576e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")),
50627872b8dSYitzhak Mandelbaum Failed<StringError>(withUnboundNodeMessage()));
50776e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromAssorted(name("stmt")),
50827872b8dSYitzhak Mandelbaum Failed<StringError>(withTypeErrorMessage("stmt")));
50927872b8dSYitzhak Mandelbaum }
51027872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,NameOpDeclRefError)51127872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, NameOpDeclRefError) {
51227872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
51327872b8dSYitzhak Mandelbaum struct S {
51427872b8dSYitzhak Mandelbaum int operator*();
51527872b8dSYitzhak Mandelbaum };
51627872b8dSYitzhak Mandelbaum int f(int x) {
51727872b8dSYitzhak Mandelbaum S s;
51827872b8dSYitzhak Mandelbaum return *s + x;
51927872b8dSYitzhak Mandelbaum }
52027872b8dSYitzhak Mandelbaum )cc";
521adcd0268SBenjamin Kramer const char *Ref = "ref";
52227872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, declRefExpr(to(functionDecl())).bind(Ref));
52327872b8dSYitzhak Mandelbaum EXPECT_THAT_EXPECTED(
52427872b8dSYitzhak Mandelbaum name(Ref)(Match.Result),
52527872b8dSYitzhak Mandelbaum Failed<StringError>(testing::Property(
52627872b8dSYitzhak Mandelbaum &StringError::getMessage,
52727872b8dSYitzhak Mandelbaum AllOf(HasSubstr(Ref), HasSubstr("requires property 'identifier'")))));
52827872b8dSYitzhak Mandelbaum }
52927872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsOp)53027872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOp) {
53127872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
53227872b8dSYitzhak Mandelbaum struct C {
53327872b8dSYitzhak Mandelbaum int bar(int, int);
53427872b8dSYitzhak Mandelbaum };
53527872b8dSYitzhak Mandelbaum int f() {
53627872b8dSYitzhak Mandelbaum C x;
53727872b8dSYitzhak Mandelbaum return x.bar(3, 4);
53827872b8dSYitzhak Mandelbaum }
53927872b8dSYitzhak Mandelbaum )cc";
540adcd0268SBenjamin Kramer const char *ID = "id";
54127872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(ID));
54276e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));
54327872b8dSYitzhak Mandelbaum }
54427872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsOpNoArgs)54527872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOpNoArgs) {
54627872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
54727872b8dSYitzhak Mandelbaum struct C {
54827872b8dSYitzhak Mandelbaum int bar();
54927872b8dSYitzhak Mandelbaum };
55027872b8dSYitzhak Mandelbaum int f() {
55127872b8dSYitzhak Mandelbaum C x;
55227872b8dSYitzhak Mandelbaum return x.bar();
55327872b8dSYitzhak Mandelbaum }
55427872b8dSYitzhak Mandelbaum )cc";
555adcd0268SBenjamin Kramer const char *ID = "id";
55627872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(ID));
55776e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(""));
55827872b8dSYitzhak Mandelbaum }
55927872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsOpNoArgsWithComments)56027872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOpNoArgsWithComments) {
56127872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
56227872b8dSYitzhak Mandelbaum struct C {
56327872b8dSYitzhak Mandelbaum int bar();
56427872b8dSYitzhak Mandelbaum };
56527872b8dSYitzhak Mandelbaum int f() {
56627872b8dSYitzhak Mandelbaum C x;
56727872b8dSYitzhak Mandelbaum return x.bar(/*empty*/);
56827872b8dSYitzhak Mandelbaum }
56927872b8dSYitzhak Mandelbaum )cc";
570adcd0268SBenjamin Kramer const char *ID = "id";
57127872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(ID));
57276e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("/*empty*/"));
57327872b8dSYitzhak Mandelbaum }
57427872b8dSYitzhak Mandelbaum
57527872b8dSYitzhak Mandelbaum // Tests that arguments are extracted correctly when a temporary (with parens)
57627872b8dSYitzhak Mandelbaum // is used.
TEST(RangeSelectorTest,CallArgsOpWithParens)57727872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOpWithParens) {
57827872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
57927872b8dSYitzhak Mandelbaum struct C {
58027872b8dSYitzhak Mandelbaum int bar(int, int) { return 3; }
58127872b8dSYitzhak Mandelbaum };
58227872b8dSYitzhak Mandelbaum int f() {
58327872b8dSYitzhak Mandelbaum C x;
58427872b8dSYitzhak Mandelbaum return C().bar(3, 4);
58527872b8dSYitzhak Mandelbaum }
58627872b8dSYitzhak Mandelbaum )cc";
587adcd0268SBenjamin Kramer const char *ID = "id";
58827872b8dSYitzhak Mandelbaum TestMatch Match =
58927872b8dSYitzhak Mandelbaum matchCode(Code, callExpr(callee(functionDecl(hasName("bar")))).bind(ID));
59076e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue("3, 4"));
59127872b8dSYitzhak Mandelbaum }
59227872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsOpLeadingComments)59327872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOpLeadingComments) {
59427872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
59527872b8dSYitzhak Mandelbaum struct C {
59627872b8dSYitzhak Mandelbaum int bar(int, int) { return 3; }
59727872b8dSYitzhak Mandelbaum };
59827872b8dSYitzhak Mandelbaum int f() {
59927872b8dSYitzhak Mandelbaum C x;
60027872b8dSYitzhak Mandelbaum return x.bar(/*leading*/ 3, 4);
60127872b8dSYitzhak Mandelbaum }
60227872b8dSYitzhak Mandelbaum )cc";
603adcd0268SBenjamin Kramer const char *ID = "id";
60427872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(ID));
60576e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),
60627872b8dSYitzhak Mandelbaum HasValue("/*leading*/ 3, 4"));
60727872b8dSYitzhak Mandelbaum }
60827872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsOpTrailingComments)60927872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOpTrailingComments) {
61027872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
61127872b8dSYitzhak Mandelbaum struct C {
61227872b8dSYitzhak Mandelbaum int bar(int, int) { return 3; }
61327872b8dSYitzhak Mandelbaum };
61427872b8dSYitzhak Mandelbaum int f() {
61527872b8dSYitzhak Mandelbaum C x;
61627872b8dSYitzhak Mandelbaum return x.bar(3 /*trailing*/, 4);
61727872b8dSYitzhak Mandelbaum }
61827872b8dSYitzhak Mandelbaum )cc";
619adcd0268SBenjamin Kramer const char *ID = "id";
62027872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(ID));
62176e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(callArgs(ID), Match),
62227872b8dSYitzhak Mandelbaum HasValue("3 /*trailing*/, 4"));
62327872b8dSYitzhak Mandelbaum }
62427872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsOpEolComments)62527872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsOpEolComments) {
62627872b8dSYitzhak Mandelbaum const StringRef Code = R"cc(
62727872b8dSYitzhak Mandelbaum struct C {
62827872b8dSYitzhak Mandelbaum int bar(int, int) { return 3; }
62927872b8dSYitzhak Mandelbaum };
63027872b8dSYitzhak Mandelbaum int f() {
63127872b8dSYitzhak Mandelbaum C x;
63227872b8dSYitzhak Mandelbaum return x.bar( // Header
63327872b8dSYitzhak Mandelbaum 1, // foo
63427872b8dSYitzhak Mandelbaum 2 // bar
63527872b8dSYitzhak Mandelbaum );
63627872b8dSYitzhak Mandelbaum }
63727872b8dSYitzhak Mandelbaum )cc";
638adcd0268SBenjamin Kramer const char *ID = "id";
63927872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, callExpr().bind(ID));
6404522e266SNico Weber std::string ExpectedString = R"( // Header
64127872b8dSYitzhak Mandelbaum 1, // foo
64227872b8dSYitzhak Mandelbaum 2 // bar
6434522e266SNico Weber )";
6444522e266SNico Weber EXPECT_THAT_EXPECTED(select(callArgs(ID), Match), HasValue(ExpectedString));
64527872b8dSYitzhak Mandelbaum }
64627872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,CallArgsErrors)64727872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, CallArgsErrors) {
64876e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromTrivial(callArgs("unbound_id")),
64927872b8dSYitzhak Mandelbaum Failed<StringError>(withUnboundNodeMessage()));
65076e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromAssorted(callArgs("stmt")),
65127872b8dSYitzhak Mandelbaum Failed<StringError>(withTypeErrorMessage("stmt")));
65227872b8dSYitzhak Mandelbaum }
65327872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,ConstructExprArgs)654*6b931ab5SClement Courbet TEST(RangeSelectorTest, ConstructExprArgs) {
655*6b931ab5SClement Courbet const StringRef Code = R"cc(
656*6b931ab5SClement Courbet struct C {
657*6b931ab5SClement Courbet C(int, int);
658*6b931ab5SClement Courbet };
659*6b931ab5SClement Courbet C f() {
660*6b931ab5SClement Courbet return C(1, 2);
661*6b931ab5SClement Courbet }
662*6b931ab5SClement Courbet )cc";
663*6b931ab5SClement Courbet const char *ID = "id";
664*6b931ab5SClement Courbet TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));
665*6b931ab5SClement Courbet EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));
666*6b931ab5SClement Courbet }
667*6b931ab5SClement Courbet
TEST(RangeSelectorTest,ConstructExprBracedArgs)668*6b931ab5SClement Courbet TEST(RangeSelectorTest, ConstructExprBracedArgs) {
669*6b931ab5SClement Courbet const StringRef Code = R"cc(
670*6b931ab5SClement Courbet struct C {
671*6b931ab5SClement Courbet C(int, int);
672*6b931ab5SClement Courbet };
673*6b931ab5SClement Courbet C f() {
674*6b931ab5SClement Courbet return {1, 2};
675*6b931ab5SClement Courbet }
676*6b931ab5SClement Courbet )cc";
677*6b931ab5SClement Courbet const char *ID = "id";
678*6b931ab5SClement Courbet TestMatch Match = matchCode(Code, cxxConstructExpr().bind(ID));
679*6b931ab5SClement Courbet EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue("1, 2"));
680*6b931ab5SClement Courbet }
681*6b931ab5SClement Courbet
TEST(RangeSelectorTest,ConstructExprNoArgs)682*6b931ab5SClement Courbet TEST(RangeSelectorTest, ConstructExprNoArgs) {
683*6b931ab5SClement Courbet const StringRef Code = R"cc(
684*6b931ab5SClement Courbet struct C {
685*6b931ab5SClement Courbet C();
686*6b931ab5SClement Courbet };
687*6b931ab5SClement Courbet C f() {
688*6b931ab5SClement Courbet return C();
689*6b931ab5SClement Courbet }
690*6b931ab5SClement Courbet )cc";
691*6b931ab5SClement Courbet const char *ID = "id";
692*6b931ab5SClement Courbet TestMatch Match = matchCode(Code, cxxTemporaryObjectExpr().bind(ID));
693*6b931ab5SClement Courbet EXPECT_THAT_EXPECTED(select(constructExprArgs(ID), Match), HasValue(""));
694*6b931ab5SClement Courbet }
695*6b931ab5SClement Courbet
TEST(RangeSelectorTest,StatementsOp)69627872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, StatementsOp) {
69727872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
69827872b8dSYitzhak Mandelbaum void g();
69927872b8dSYitzhak Mandelbaum void f() { /* comment */ g(); /* comment */ g(); /* comment */ }
70027872b8dSYitzhak Mandelbaum )cc";
701adcd0268SBenjamin Kramer const char *ID = "id";
70227872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
70327872b8dSYitzhak Mandelbaum EXPECT_THAT_EXPECTED(
70476e3a049SDmitri Gribenko select(statements(ID), Match),
70527872b8dSYitzhak Mandelbaum HasValue(" /* comment */ g(); /* comment */ g(); /* comment */ "));
70627872b8dSYitzhak Mandelbaum }
70727872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,StatementsOpEmptyList)70827872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, StatementsOpEmptyList) {
70927872b8dSYitzhak Mandelbaum StringRef Code = "void f() {}";
710adcd0268SBenjamin Kramer const char *ID = "id";
71127872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, compoundStmt().bind(ID));
71276e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(statements(ID), Match), HasValue(""));
71327872b8dSYitzhak Mandelbaum }
71427872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,StatementsOpErrors)71527872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, StatementsOpErrors) {
71676e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromTrivial(statements("unbound_id")),
71727872b8dSYitzhak Mandelbaum Failed<StringError>(withUnboundNodeMessage()));
71876e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromAssorted(statements("decl")),
71927872b8dSYitzhak Mandelbaum Failed<StringError>(withTypeErrorMessage("decl")));
72027872b8dSYitzhak Mandelbaum }
72127872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,ElementsOp)72227872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, ElementsOp) {
72327872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
72427872b8dSYitzhak Mandelbaum void f() {
72527872b8dSYitzhak Mandelbaum int v[] = {/* comment */ 3, /* comment*/ 4 /* comment */};
72627872b8dSYitzhak Mandelbaum (void)v;
72727872b8dSYitzhak Mandelbaum }
72827872b8dSYitzhak Mandelbaum )cc";
729adcd0268SBenjamin Kramer const char *ID = "id";
73027872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, initListExpr().bind(ID));
73127872b8dSYitzhak Mandelbaum EXPECT_THAT_EXPECTED(
73276e3a049SDmitri Gribenko select(initListElements(ID), Match),
73327872b8dSYitzhak Mandelbaum HasValue("/* comment */ 3, /* comment*/ 4 /* comment */"));
73427872b8dSYitzhak Mandelbaum }
73527872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,ElementsOpEmptyList)73627872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, ElementsOpEmptyList) {
73727872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
73827872b8dSYitzhak Mandelbaum void f() {
73927872b8dSYitzhak Mandelbaum int v[] = {};
74027872b8dSYitzhak Mandelbaum (void)v;
74127872b8dSYitzhak Mandelbaum }
74227872b8dSYitzhak Mandelbaum )cc";
743adcd0268SBenjamin Kramer const char *ID = "id";
74427872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, initListExpr().bind(ID));
74576e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(initListElements(ID), Match), HasValue(""));
74627872b8dSYitzhak Mandelbaum }
74727872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,ElementsOpErrors)74827872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, ElementsOpErrors) {
74976e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromTrivial(initListElements("unbound_id")),
75027872b8dSYitzhak Mandelbaum Failed<StringError>(withUnboundNodeMessage()));
75176e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(selectFromAssorted(initListElements("stmt")),
75227872b8dSYitzhak Mandelbaum Failed<StringError>(withTypeErrorMessage("stmt")));
75327872b8dSYitzhak Mandelbaum }
75427872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,ElseBranchOpSingleStatement)755eff88e42SYitzhak Mandelbaum TEST(RangeSelectorTest, ElseBranchOpSingleStatement) {
756eff88e42SYitzhak Mandelbaum StringRef Code = R"cc(
757eff88e42SYitzhak Mandelbaum int f() {
758eff88e42SYitzhak Mandelbaum int x = 0;
759eff88e42SYitzhak Mandelbaum if (true) x = 3;
760eff88e42SYitzhak Mandelbaum else x = 4;
761eff88e42SYitzhak Mandelbaum return x + 5;
762eff88e42SYitzhak Mandelbaum }
763eff88e42SYitzhak Mandelbaum )cc";
764adcd0268SBenjamin Kramer const char *ID = "id";
765eff88e42SYitzhak Mandelbaum TestMatch Match = matchCode(Code, ifStmt().bind(ID));
766eff88e42SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;"));
767eff88e42SYitzhak Mandelbaum }
768eff88e42SYitzhak Mandelbaum
TEST(RangeSelectorTest,ElseBranchOpCompoundStatement)769eff88e42SYitzhak Mandelbaum TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) {
770eff88e42SYitzhak Mandelbaum StringRef Code = R"cc(
771eff88e42SYitzhak Mandelbaum int f() {
772eff88e42SYitzhak Mandelbaum int x = 0;
773eff88e42SYitzhak Mandelbaum if (true) x = 3;
774eff88e42SYitzhak Mandelbaum else { x = 4; }
775eff88e42SYitzhak Mandelbaum return x + 5;
776eff88e42SYitzhak Mandelbaum }
777eff88e42SYitzhak Mandelbaum )cc";
778adcd0268SBenjamin Kramer const char *ID = "id";
779eff88e42SYitzhak Mandelbaum TestMatch Match = matchCode(Code, ifStmt().bind(ID));
780eff88e42SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match),
781eff88e42SYitzhak Mandelbaum HasValue("else { x = 4; }"));
782eff88e42SYitzhak Mandelbaum }
783eff88e42SYitzhak Mandelbaum
78427872b8dSYitzhak Mandelbaum // Tests case where the matched node is the complete expanded text.
TEST(RangeSelectorTest,ExpansionOp)78527872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, ExpansionOp) {
78627872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
78727872b8dSYitzhak Mandelbaum #define BADDECL(E) int bad(int x) { return E; }
78827872b8dSYitzhak Mandelbaum BADDECL(x * x)
78927872b8dSYitzhak Mandelbaum )cc";
79027872b8dSYitzhak Mandelbaum
791adcd0268SBenjamin Kramer const char *Fun = "Fun";
79227872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, functionDecl(hasName("bad")).bind(Fun));
79376e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(expansion(node(Fun)), Match),
79427872b8dSYitzhak Mandelbaum HasValue("BADDECL(x * x)"));
79527872b8dSYitzhak Mandelbaum }
79627872b8dSYitzhak Mandelbaum
79727872b8dSYitzhak Mandelbaum // Tests case where the matched node is (only) part of the expanded text.
TEST(RangeSelectorTest,ExpansionOpPartial)79827872b8dSYitzhak Mandelbaum TEST(RangeSelectorTest, ExpansionOpPartial) {
79927872b8dSYitzhak Mandelbaum StringRef Code = R"cc(
80027872b8dSYitzhak Mandelbaum #define BADDECL(E) int bad(int x) { return E; }
80127872b8dSYitzhak Mandelbaum BADDECL(x * x)
80227872b8dSYitzhak Mandelbaum )cc";
80327872b8dSYitzhak Mandelbaum
804adcd0268SBenjamin Kramer const char *Ret = "Ret";
80527872b8dSYitzhak Mandelbaum TestMatch Match = matchCode(Code, returnStmt().bind(Ret));
80676e3a049SDmitri Gribenko EXPECT_THAT_EXPECTED(select(expansion(node(Ret)), Match),
80727872b8dSYitzhak Mandelbaum HasValue("BADDECL(x * x)"));
80827872b8dSYitzhak Mandelbaum }
80927872b8dSYitzhak Mandelbaum
TEST(RangeSelectorTest,IfBoundOpBound)810eff88e42SYitzhak Mandelbaum TEST(RangeSelectorTest, IfBoundOpBound) {
811eff88e42SYitzhak Mandelbaum StringRef Code = R"cc(
812eff88e42SYitzhak Mandelbaum int f() {
813eff88e42SYitzhak Mandelbaum return 3 + 5;
814eff88e42SYitzhak Mandelbaum }
815eff88e42SYitzhak Mandelbaum )cc";
816adcd0268SBenjamin Kramer const char *ID = "id", *Op = "op";
817eff88e42SYitzhak Mandelbaum TestMatch Match =
818eff88e42SYitzhak Mandelbaum matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));
819eff88e42SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
820eff88e42SYitzhak Mandelbaum HasValue("3"));
821eff88e42SYitzhak Mandelbaum }
822eff88e42SYitzhak Mandelbaum
TEST(RangeSelectorTest,IfBoundOpUnbound)823eff88e42SYitzhak Mandelbaum TEST(RangeSelectorTest, IfBoundOpUnbound) {
824eff88e42SYitzhak Mandelbaum StringRef Code = R"cc(
825eff88e42SYitzhak Mandelbaum int f() {
826eff88e42SYitzhak Mandelbaum return 3 + 5;
827eff88e42SYitzhak Mandelbaum }
828eff88e42SYitzhak Mandelbaum )cc";
829adcd0268SBenjamin Kramer const char *ID = "id", *Op = "op";
830eff88e42SYitzhak Mandelbaum TestMatch Match = matchCode(Code, binaryOperator().bind(Op));
831eff88e42SYitzhak Mandelbaum EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
832eff88e42SYitzhak Mandelbaum HasValue("3 + 5"));
833eff88e42SYitzhak Mandelbaum }
834eff88e42SYitzhak Mandelbaum
83527872b8dSYitzhak Mandelbaum } // namespace
836