9#include "clang/ASTMatchers/ASTMatchFinder.h"
10#include "clang/ASTMatchers/ASTMatchers.h"
11#include "clang/Tooling/Tooling.h"
12#include "gmock/gmock-matchers.h"
13#include "gtest/gtest.h"
17using testing::ElementsAre;
27MATCHER_P2(matchAdapter, MatcherForElement, MatchFunction,
"matchAdapter") {
28 return MatchFunction(MatcherForElement, arg);
31template <
typename InputNode>
32using ResolveFnT = std::function<std::vector<const NamedDecl *>(
41template <
typename InputNode,
typename InputMatcher,
typename... OutputMatchers>
42void expectResolution(llvm::StringRef Code, ResolveFnT<InputNode> ResolveFn,
43 const InputMatcher &IM,
const OutputMatchers &...OMS) {
44 auto TU = tooling::buildASTFromCodeWithArgs(Code, {
"-std=c++20"});
45 auto &Ctx = TU->getASTContext();
46 auto InputMatches =
match(IM, Ctx);
47 ASSERT_EQ(1u, InputMatches.size());
48 const auto *Input = InputMatches[0].template getNodeAs<InputNode>(
"input");
51 auto OutputNodeMatches = [&](
auto &OutputMatcher,
auto &Actual) {
52 auto OutputMatches =
match(OutputMatcher, Ctx);
53 if (OutputMatches.size() != 1u)
55 const auto *ExpectedOutput =
56 OutputMatches[0].template getNodeAs<NamedDecl>(
"output");
59 return ExpectedOutput == Actual;
63 auto Results = ResolveFn(&H, Input);
64 EXPECT_THAT(
Results, ElementsAre(matchAdapter(OMS, OutputNodeMatches)...));
69template <
typename InputNode,
typename InputMatcher,
typename... OutputMatchers>
70void expectResolution(llvm::StringRef Code,
71 std::vector<const NamedDecl *> (
74 const InputMatcher &IM,
const OutputMatchers &...OMS) {
75 expectResolution(Code, ResolveFnT<InputNode>(std::mem_fn(ResolveFn)), IM,
80 std::string Code = R
"cpp(
93 Code, &HeuristicResolver::resolveMemberExpr,
94 cxxDependentScopeMemberExpr(hasMemberName(
"bar")).bind(
"input"),
95 cxxMethodDecl(hasName(
"bar")).bind(
"output"));
99 std::string Code = R
"cpp(
100 template <typename T>
106 template <typename T, typename U>
107 void foo(S<T> arg, U u) {
113 Code, &HeuristicResolver::resolveMemberExpr,
114 cxxDependentScopeMemberExpr(hasMemberName(
"bar")).bind(
"input"),
115 cxxMethodDecl(hasName(
"bar"), hasParameter(0, hasType(asString(
"int"))))
117 cxxMethodDecl(hasName(
"bar"), hasParameter(0, hasType(asString(
"float"))))
122 std::string Code = R
"cpp(
123 template <typename> struct S { void foo() {} };
124 template <typename T> struct unique_ptr {
127 template <typename T>
128 void test(unique_ptr<S<T>>& v) {
134 Code, &HeuristicResolver::resolveMemberExpr,
135 cxxDependentScopeMemberExpr(hasMemberName(
"foo")).bind(
"input"),
136 cxxMethodDecl(hasName(
"foo")).bind(
"output"));
140 std::string Code = R
"cpp(
141 struct A { void foo() {} };
142 template <typename T>
152 Code, &HeuristicResolver::resolveMemberExpr,
153 cxxDependentScopeMemberExpr(hasMemberName(
"foo")).bind(
"input"),
154 cxxMethodDecl(hasName(
"foo")).bind(
"output"));
158 std::string Code = R
"cpp(
161 template <typename T> T convert();
163 template <typename T>
165 Foo::k(T()).template convert<T>();
170 Code, &HeuristicResolver::resolveMemberExpr,
171 cxxDependentScopeMemberExpr(hasMemberName(
"convert")).bind(
"input"),
172 functionTemplateDecl(hasName(
"convert")).bind(
"output"));
176 std::string Code = R
"cpp(
177 template <typename T>
181 template <typename T>
182 using Wally = Waldo<T>;
183 template <typename T>
184 void foo(Wally<T> w) {
190 Code, &HeuristicResolver::resolveMemberExpr,
191 cxxDependentScopeMemberExpr(hasMemberName(
"find")).bind(
"input"),
192 cxxMethodDecl(hasName(
"find")).bind(
"output"));
196 std::string Code = R
"cpp(
197 template <typename T>
201 template <typename T>
202 using Wally = Waldo<T>;
203 template <typename T>
204 struct S : Wally<T> {
212 Code, &HeuristicResolver::resolveMemberExpr,
213 cxxDependentScopeMemberExpr(hasMemberName(
"find")).bind(
"input"),
214 cxxMethodDecl(hasName(
"find")).bind(
"output"));
218 std::string Code = R
"cpp(
219 template <typename T>
223 template <typename T>
225 using Type = Waldo<T>;
227 template <typename T>
228 void foo(typename MetaWaldo<T>::Type w) {
234 Code, &HeuristicResolver::resolveMemberExpr,
235 cxxDependentScopeMemberExpr(hasMemberName(
"find")).bind(
"input"),
236 cxxMethodDecl(hasName(
"find")).bind(
"output"));
240 std::string Code = R
"cpp(
252 Code, &HeuristicResolver::resolveMemberExpr,
253 cxxDependentScopeMemberExpr(hasMemberName(
"found")).bind(
"input"),
254 fieldDecl(hasName(
"found")).bind(
"output"));
258 std::string Code = R
"cpp(
259 template <typename T>
264 template <typename T>
271 Code, &HeuristicResolver::resolveDeclRefExpr,
272 dependentScopeDeclRefExpr(hasDependentName(
"bar")).bind(
"input"),
273 cxxMethodDecl(hasName(
"bar")).bind(
"output"));
277 std::string Code = R
"cpp(
278 template <typename T>
280 static void bar(int);
281 static void bar(float);
284 template <typename T, typename U>
291 Code, &HeuristicResolver::resolveDeclRefExpr,
292 dependentScopeDeclRefExpr(hasDependentName(
"bar")).bind(
"input"),
293 cxxMethodDecl(hasName(
"bar"), hasParameter(0, hasType(asString(
"int"))))
295 cxxMethodDecl(hasName(
"bar"), hasParameter(0, hasType(asString(
"float"))))
300 std::string Code = R
"cpp(
301 template <typename T>
303 enum class E { A, B };
309 Code, &HeuristicResolver::resolveDeclRefExpr,
310 dependentScopeDeclRefExpr(hasDependentName(
"A")).bind(
"input"),
311 enumConstantDecl(hasName(
"A")).bind(
"output"));
315 std::string Code = R
"cpp(
316 template <typename Info>
317 struct PointerIntPair {
318 void *getPointer() const { return Info::getPointer(); }
325 Code, &HeuristicResolver::resolveDeclRefExpr,
326 dependentScopeDeclRefExpr(hasDependentName(
"getPointer")).bind(
"input"));
330 std::string Code = R
"cpp(
335 template <typename T>
336 void foo(typename A<T>::B);
340 Code, &HeuristicResolver::resolveDependentNameType,
341 functionDecl(hasParameter(0, hasType(dependentNameType().bind(
"input")))),
343 has(cxxRecordDecl(has(cxxRecordDecl(hasName(
"B")).bind(
"output"))))));
347 std::string Code = R
"cpp(
354 template <typename T>
355 void foo(typename A<T>::B::C);
359 Code, &HeuristicResolver::resolveDependentNameType,
360 functionDecl(hasParameter(0, hasType(dependentNameType().bind(
"input")))),
361 classTemplateDecl(has(cxxRecordDecl(has(
362 cxxRecordDecl(has(cxxRecordDecl(hasName(
"C")).bind(
"output"))))))));
366 std::string Code = R
"cpp(
369 using Type = typename Waldo<N - 1>::Type::Next;
374 expectResolution(Code, &HeuristicResolver::resolveDependentNameType,
375 typeAliasDecl(hasType(dependentNameType().bind(
"input"))));
379 std::string Code = R
"cpp(
384 using Type = typename Odd<N - 1>::Type::Next;
388 using Type = typename Even<N - 1>::Type::Next;
394 Code, &HeuristicResolver::resolveDependentNameType,
395 classTemplateDecl(hasName(
"Odd"),
396 has(cxxRecordDecl(has(typeAliasDecl(
397 hasType(dependentNameType().bind(
"input"))))))));
404 std::string Code = R
"cpp(
411 template <typename T>
412 void foo(typename A<T>::B::C);
416 ResolveFnT<NestedNameSpecifier> ResolveFn =
418 const NestedNameSpecifier *NNS) -> std::vector<const NamedDecl *> {
419 return {H->resolveNestedNameSpecifierToType(NNS)->getAsCXXRecordDecl()};
421 expectResolution(Code, ResolveFn,
422 nestedNameSpecifier(hasPrefix(specifiesType(hasDeclaration(
423 classTemplateDecl(hasName(
"A"))))))
425 classTemplateDecl(has(cxxRecordDecl(
426 has(cxxRecordDecl(hasName(
"B")).bind(
"output"))))));
430 std::string Code = R
"cpp(
436 template <typename T>
437 void foo(typename A<T>::template B<int>);
440 expectResolution(Code, &HeuristicResolver::resolveTemplateSpecializationType,
441 functionDecl(hasParameter(0, hasType(type().bind(
"input")))),
442 classTemplateDecl(has(cxxRecordDecl(
443 has(classTemplateDecl(hasName(
"B")).bind(
"output"))))));
447 std::string Code = R
"cpp(
448 template <typename T>
450 template <typename T>
456 expectResolution(Code, &HeuristicResolver::resolveCalleeOfCallExpr,
457 callExpr(callee(unresolvedLookupExpr(hasAnyDeclaration(
458 functionTemplateDecl(hasName(
"nonmember"))))))
460 functionTemplateDecl(hasName(
"nonmember")).bind(
"output"));
464 std::string Code = R
"cpp(
465 template <typename T>
469 template <typename T>
470 void bar(A<T> a, T t) {
476 Code, &HeuristicResolver::resolveCalleeOfCallExpr,
477 callExpr(callee(cxxDependentScopeMemberExpr(hasMemberName(
"member"))))
479 cxxMethodDecl(hasName(
"member")).bind(
"output"));
483 std::string Code = R
"cpp(
484 template <typename T>
486 static void static_member(T);
488 template <typename T>
490 A<T>::static_member(t);
494 expectResolution(Code, &HeuristicResolver::resolveCalleeOfCallExpr,
495 callExpr(callee(dependentScopeDeclRefExpr(
496 hasDependentName(
"static_member"))))
498 cxxMethodDecl(hasName(
"static_member")).bind(
"output"));
502 std::string Code = R
"cpp(
504 void overload(double);
505 template <typename T>
512 expectResolution(Code, &HeuristicResolver::resolveCalleeOfCallExpr,
513 callExpr(callee(unresolvedLookupExpr(hasAnyDeclaration(
514 functionDecl(hasName(
"overload"))))))
516 functionDecl(hasName(
"overload"),
517 hasParameter(0, hasType(asString(
"double"))))
519 functionDecl(hasName(
"overload"),
520 hasParameter(0, hasType(asString(
"int"))))
525 std::string Code = R
"cpp(
526 template <typename T>
530 template <typename T>
531 struct Derived : Base<T> {
532 using Base<T>::waldo;
536 expectResolution(Code, &HeuristicResolver::resolveUsingValueDecl,
537 unresolvedUsingValueDecl(hasName(
"waldo")).bind(
"input"),
538 cxxMethodDecl(hasName(
"waldo")).bind(
"output"));
std::vector< CodeCompletionResult > Results
MATCHER_P2(hasFlag, Flag, Path, "")
std::vector< std::string > match(const SymbolIndex &I, const FuzzyFindRequest &Req, bool *Incomplete)
TEST(BackgroundQueueTest, Priority)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//