11 #include "clang/AST/ASTDumper.h"
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"
18 using namespace clang::ast_matchers::dynamic;
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 print-matcher (true|false) "
45 "Set whether to print the current matcher,\n"
46 " set traversal <kind> "
47 "Set traversal kind of clang-query session. Available kinds are:\n"
49 "Print and match the AST as clang sees it. This mode is the "
51 " IgnoreImplicitCastsAndParentheses "
52 "Omit implicit casts and parens in matching and dumping.\n"
53 " IgnoreUnlessSpelledInSource "
54 "Omit AST nodes unless spelled in the source.\n"
55 " set output <feature> "
56 "Set whether to output only <feature> content.\n"
57 " enable output <feature> "
58 "Enable <feature> content non-exclusively.\n"
59 " disable output <feature> "
60 "Disable <feature> content non-exclusively.\n"
62 "Terminates the query session.\n\n"
63 "Several commands accept a <feature> parameter. The available features "
66 "Pretty-print bound nodes.\n"
68 "Diagnostic location for bound nodes.\n"
70 "Detailed AST output for bound nodes.\n"
72 "Detailed AST output for bound nodes (alias of detailed-ast).\n\n";
83 struct CollectBoundNodes : MatchFinder::MatchCallback {
86 void run(
const MatchFinder::MatchResult &Result)
override {
94 unsigned MatchCount = 0;
96 for (
auto &AST : QS.
ASTs) {
98 std::vector<BoundNodes> Matches;
99 DynTypedMatcher MaybeBoundMatcher = Matcher;
101 llvm::Optional<DynTypedMatcher> M = Matcher.tryBind(
"root");
103 MaybeBoundMatcher = *M;
105 CollectBoundNodes Collect(Matches);
106 if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) {
107 OS <<
"Not a valid top-level matcher.\n";
111 AST->getASTContext().getParentMapContext().setTraversalKind(QS.
TK);
112 Finder.matchAST(AST->getASTContext());
115 SmallVector<StringRef, 4>
Lines;
116 Source.split(
Lines,
"\n");
117 auto FirstLine =
Lines[0];
119 while (!
Lines.empty() &&
Lines.back().empty()) {
122 unsigned MaxLength = FirstLine.size();
123 std::string PrefixText =
"Matcher: ";
124 OS <<
"\n " << PrefixText << FirstLine;
127 OS <<
"\n" << std::string(PrefixText.size() + 2,
' ') <<
Line;
128 MaxLength = std::max<int>(MaxLength,
Line.rtrim().size());
132 <<
" " << std::string(PrefixText.size() + MaxLength,
'=') <<
"\n\n";
135 for (
auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) {
136 OS <<
"\nMatch #" << ++MatchCount <<
":\n\n";
138 for (
auto BI = MI->getMap().begin(), BE = MI->getMap().end(); BI != BE;
141 clang::SourceRange R = BI->second.getSourceRange();
143 TextDiagnostic TD(
OS, AST->getASTContext().getLangOpts(),
144 &AST->getDiagnostics().getDiagnosticOptions());
146 FullSourceLoc(R.getBegin(), AST->getSourceManager()),
147 DiagnosticsEngine::Note,
"\"" + BI->first +
"\" binds here",
148 CharSourceRange::getTokenRange(R), None);
152 OS <<
"Binding for \"" << BI->first <<
"\":\n";
153 BI->second.print(
OS, AST->getASTContext().getPrintingPolicy());
157 OS <<
"Binding for \"" << BI->first <<
"\":\n";
158 const ASTContext &
Ctx = AST->getASTContext();
159 const SourceManager &SM =
Ctx.getSourceManager();
160 ASTDumper Dumper(
OS,
Ctx, SM.getDiagnostics().getShowColors());
161 Dumper.SetTraversalKind(QS.
TK);
162 Dumper.Visit(BI->second);
167 if (MI->getMap().empty())
168 OS <<
"No bindings.\n";
172 OS << MatchCount << (MatchCount == 1 ?
" match.\n" :
" matches.\n");