Clang Project

clang_source_code/unittests/AST/DeclMatcher.h
1//===- unittest/AST/DeclMatcher.h - AST unit test support ---------------===//
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#ifndef LLVM_CLANG_UNITTESTS_AST_DECLMATCHER_H
10#define LLVM_CLANG_UNITTESTS_AST_DECLMATCHER_H
11
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13
14namespace clang {
15namespace ast_matchers {
16
17enum class DeclMatcherKind { FirstLast };
18
19// Matcher class to retrieve the first/last matched node under a given AST.
20template <typename NodeType, DeclMatcherKind MatcherKind>
21class DeclMatcher : public MatchFinder::MatchCallback {
22  NodeType *Node = nullptr;
23  void run(const MatchFinder::MatchResult &Result) override {
24    if ((MatcherKind == DeclMatcherKind::First && Node == nullptr) ||
25        MatcherKind == DeclMatcherKind::Last) {
26      Node = const_cast<NodeType *>(Result.Nodes.getNodeAs<NodeType>(""));
27    }
28  }
29public:
30  // Returns the first/last matched node under the tree rooted in `D`.
31  template <typename MatcherType>
32  NodeType *match(const Decl *Dconst MatcherType &AMatcher) {
33    MatchFinder Finder;
34    Finder.addMatcher(AMatcher.bind(""), this);
35    Finder.matchAST(D->getASTContext());
36    assert(Node);
37    return Node;
38  }
39};
40template <typename NodeType>
41using LastDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::Last>;
42template <typename NodeType>
43using FirstDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::First>;
44
45template <typename NodeType>
46class DeclCounterWithPredicate : public MatchFinder::MatchCallback {
47  using UnaryPredicate = std::function<bool(const NodeType *)>;
48  UnaryPredicate Predicate;
49  unsigned Count = 0;
50  void run(const MatchFinder::MatchResult &Result) override {
51    if (auto N = Result.Nodes.getNodeAs<NodeType>("")) {
52      if (Predicate(N))
53        ++Count;
54    }
55  }
56
57public:
58  DeclCounterWithPredicate()
59      : Predicate([](const NodeType *) { return true; }) {}
60  DeclCounterWithPredicate(UnaryPredicate P) : Predicate(P) {}
61  // Returns the number of matched nodes which satisfy the predicate under the
62  // tree rooted in `D`.
63  template <typename MatcherType>
64  unsigned match(const Decl *Dconst MatcherType &AMatcher) {
65    MatchFinder Finder;
66    Finder.addMatcher(AMatcher.bind(""), this);
67    Finder.matchAST(D->getASTContext());
68    return Count;
69  }
70};
71
72template <typename NodeType>
73using DeclCounter = DeclCounterWithPredicate<NodeType>;
74
75// end namespace ast_matchers
76// end namespace clang
77
78#endif
79
clang::ast_matchers::DeclMatcher::Node
clang::ast_matchers::DeclMatcher::run
clang::ast_matchers::DeclMatcher::match
clang::ast_matchers::DeclCounterWithPredicate::Predicate
clang::ast_matchers::DeclCounterWithPredicate::Count
clang::ast_matchers::DeclCounterWithPredicate::run
clang::ast_matchers::DeclCounterWithPredicate::match