[clang-tools-extra] [clangd] Add a unit test suite for HeuristicResolver (PR #121313)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 1 23:13:09 PST 2025
================
@@ -0,0 +1,521 @@
+//===-- HeuristicResolverTests.cpp --------------------------*- C++ -*-----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "HeuristicResolver.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock-matchers.h"
+#include "gtest/gtest.h"
+
+using namespace clang::ast_matchers;
+using clang::clangd::HeuristicResolver;
+using testing::ElementsAre;
+
+namespace clang {
+namespace {
+
+// Helper for matching a sequence of elements with a variadic list of matchers.
+// Usage: `ElementsAre(matchAdapter(Vs, MatchFunction)...)`, where `Vs...` is
+// a variadic list of matchers.
+// For each `V` in `Vs`, this will match the corresponding element `E` if
+// `MatchFunction(V, E)` is true.
+MATCHER_P2(matchAdapter, MatcherForElement, MatchFunction, "matchAdapter") {
+ return MatchFunction(MatcherForElement, arg);
+}
+
+template <typename InputNode>
+using ResolveFnT = std::function<std::vector<const NamedDecl *>(
+ const HeuristicResolver *, const InputNode *)>;
+
+// Test heuristic resolution on `Code` using the resolution procedure
+// `ResolveFn`, which takes a `HeuristicResolver` and an input AST node of type
+// `InputNode` and returns a `std::vector<const NamedDecl *>`.
+// `InputMatcher` should be an AST matcher that matches a single node to pass as
+// input to `ResolveFn`, bound to the ID "input". `OutputMatchers` should be AST
+// matchers that each match a single node, bound to the ID "output".
+template <typename InputNode, typename InputMatcher, typename... OutputMatchers>
+void expectResolution(llvm::StringRef Code, ResolveFnT<InputNode> ResolveFn,
+ const InputMatcher &IM, const OutputMatchers &...OMS) {
+ auto TU = tooling::buildASTFromCodeWithArgs(Code, {"-std=c++20"});
+ auto &Ctx = TU->getASTContext();
+ auto InputMatches = match(IM, Ctx);
+ ASSERT_EQ(1u, InputMatches.size());
+ const auto *Input = InputMatches[0].template getNodeAs<InputNode>("input");
+ ASSERT_TRUE(Input);
+
+ auto OutputNodeMatches = [&](auto &OutputMatcher, auto &Actual) {
+ auto OutputMatches = match(OutputMatcher, Ctx);
+ if (OutputMatches.size() != 1u)
+ return false;
+ const auto *ExpectedOutput =
+ OutputMatches[0].template getNodeAs<NamedDecl>("output");
+ if (!ExpectedOutput)
+ return false;
+ return ExpectedOutput == Actual;
+ };
+
+ HeuristicResolver H(Ctx);
+ auto Results = ResolveFn(&H, Input);
+ EXPECT_THAT(Results, ElementsAre(matchAdapter(OMS, OutputNodeMatches)...));
+}
+
+// Wrapper for the above that accepts a HeuristicResolver member function
+// pointer directly.
+template <typename InputNode, typename InputMatcher, typename... OutputMatchers>
+void expectResolution(llvm::StringRef Code,
+ std::vector<const NamedDecl *> (
+ HeuristicResolver::*ResolveFn)(const InputNode *)
+ const,
+ const InputMatcher &IM, const OutputMatchers &...OMS) {
+ expectResolution(Code, ResolveFnT<InputNode>(std::mem_fn(ResolveFn)), IM,
+ OMS...);
+}
+
+TEST(HeuristicResolver, MemberExpr) {
+ std::string Code = R"cpp(
+ template <typename T>
+ struct S {
+ void bar() {}
+ };
+
+ template <typename T>
+ void foo(S<T> arg) {
+ arg.bar();
+ }
+ )cpp";
+ // Test resolution of "bar" in "arg.bar()".
+ expectResolution(Code, &HeuristicResolver::resolveMemberExpr,
+ cxxDependentScopeMemberExpr().bind("input"),
----------------
HighCommander4 wrote:
Never mind, I _was_ overlooking something: there is a `hasMemberName()` matcher that works with `CXXDependentScopeMemberExpr`. I'll look at using that.
https://github.com/llvm/llvm-project/pull/121313
More information about the cfe-commits
mailing list