12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Frontend/ASTUnit.h"
14 #include "clang/Frontend/TextDiagnostic.h"
15 #include "llvm/Support/raw_ostream.h"
17 using namespace clang::ast_matchers;
18 using namespace clang::ast_matchers::dynamic;
25 bool InvalidQuery::run(llvm::raw_ostream &OS,
QuerySession &QS)
const {
30 bool NoOpQuery::run(llvm::raw_ostream &OS,
QuerySession &QS)
const {
34 bool HelpQuery::run(llvm::raw_ostream &OS,
QuerySession &QS)
const {
35 OS <<
"Available commands:\n\n"
36 " match MATCHER, m MATCHER "
37 "Match the loaded ASTs against the given matcher.\n"
38 " let NAME MATCHER, l NAME MATCHER "
39 "Give a matcher expression a name, to be used later\n"
41 "as part of other expressions.\n"
42 " set bind-root (true|false) "
43 "Set whether to bind the root matcher to \"root\".\n"
44 " set output (diag|print|dump) "
45 "Set whether to print bindings as diagnostics,\n"
47 "AST pretty prints or AST dumps.\n"
49 "Terminates the query session.\n\n";
53 bool QuitQuery::run(llvm::raw_ostream &OS,
QuerySession &QS)
const {
60 struct CollectBoundNodes : MatchFinder::MatchCallback {
62 CollectBoundNodes(std::vector<BoundNodes> &
Bindings) : Bindings(Bindings) {}
63 void run(
const MatchFinder::MatchResult &Result)
override {
70 bool MatchQuery::run(llvm::raw_ostream &OS,
QuerySession &QS)
const {
71 unsigned MatchCount = 0;
73 for (
auto &AST : QS.
ASTs) {
75 std::vector<BoundNodes> Matches;
76 DynTypedMatcher MaybeBoundMatcher = Matcher;
78 llvm::Optional<DynTypedMatcher> M = Matcher.tryBind(
"root");
80 MaybeBoundMatcher = *M;
82 CollectBoundNodes Collect(Matches);
83 if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) {
84 OS <<
"Not a valid top-level matcher.\n";
87 Finder.matchAST(AST->getASTContext());
89 for (
auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) {
90 OS <<
"\nMatch #" << ++MatchCount <<
":\n\n";
92 for (
auto BI = MI->getMap().begin(), BE = MI->getMap().end(); BI != BE;
96 clang::SourceRange R = BI->second.getSourceRange();
98 TextDiagnostic TD(OS, AST->getASTContext().getLangOpts(),
99 &AST->getDiagnostics().getDiagnosticOptions());
101 FullSourceLoc(R.getBegin(), AST->getSourceManager()),
102 DiagnosticsEngine::Note,
"\"" + BI->first +
"\" binds here",
103 CharSourceRange::getTokenRange(R), None);
108 OS <<
"Binding for \"" << BI->first <<
"\":\n";
109 BI->second.print(OS, AST->getASTContext().getPrintingPolicy());
114 OS <<
"Binding for \"" << BI->first <<
"\":\n";
115 BI->second.dump(OS, AST->getSourceManager());
122 if (MI->getMap().empty())
123 OS <<
"No bindings.\n";
127 OS << MatchCount << (MatchCount == 1 ?
" match.\n" :
" matches.\n");
std::unique_ptr< ast_matchers::MatchFinder > Finder
Represents the state for a particular clang-query session.
llvm::ArrayRef< std::unique_ptr< ASTUnit > > ASTs
llvm::StringMap< ast_matchers::dynamic::VariantValue > NamedValues
std::vector< BoundNodes > & Bindings