blob: 65a68edea9dce3420e4ad7dc6991509f80ea796f [file] [log] [blame]
Peter Collingbourne8b1265b2013-11-08 00:08:231//===---- Query.cpp - clang-query query -----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Query.h"
11#include "QuerySession.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"
16
17using namespace clang::ast_matchers;
18using namespace clang::ast_matchers::dynamic;
19
20namespace clang {
21namespace query {
22
23Query::~Query() {}
24
25bool InvalidQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
26 OS << ErrStr << "\n";
27 return false;
28}
29
30bool NoOpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
31 return true;
32}
33
34bool 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 " set bind-root (true|false) "
39 "Set whether to bind the root matcher to \"root\".\n"
40 " set output (diag|print|dump) "
41 "Set whether to print bindings as diagnostics,\n"
42 " "
43 "AST pretty prints or AST dumps.\n\n";
44 return true;
45}
46
47namespace {
48
49struct CollectBoundNodes : MatchFinder::MatchCallback {
50 std::vector<BoundNodes> &Bindings;
51 CollectBoundNodes(std::vector<BoundNodes> &Bindings) : Bindings(Bindings) {}
52 void run(const MatchFinder::MatchResult &Result) {
53 Bindings.push_back(Result.Nodes);
54 }
55};
56
Samuel Benzaquen1f6066c2014-04-23 14:04:5257} // namespace
Peter Collingbourne8b1265b2013-11-08 00:08:2358
59bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
60 unsigned MatchCount = 0;
61
62 for (llvm::ArrayRef<ASTUnit *>::iterator I = QS.ASTs.begin(),
63 E = QS.ASTs.end();
64 I != E; ++I) {
65 ASTUnit *AST = *I;
66 MatchFinder Finder;
67 std::vector<BoundNodes> Matches;
68 DynTypedMatcher MaybeBoundMatcher = Matcher;
69 if (QS.BindRoot) {
70 llvm::Optional<DynTypedMatcher> M = Matcher.tryBind("root");
71 if (M)
72 MaybeBoundMatcher = *M;
73 }
74 CollectBoundNodes Collect(Matches);
75 if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) {
76 OS << "Not a valid top-level matcher.\n";
77 return false;
78 }
79 Finder.matchAST(AST->getASTContext());
80
81 for (std::vector<BoundNodes>::iterator MI = Matches.begin(),
82 ME = Matches.end();
83 MI != ME; ++MI) {
84 OS << "\nMatch #" << ++MatchCount << ":\n\n";
85
86 for (BoundNodes::IDToNodeMap::const_iterator BI = MI->getMap().begin(),
87 BE = MI->getMap().end();
88 BI != BE; ++BI) {
89 switch (QS.OutKind) {
90 case OK_Diag: {
91 clang::SourceRange R = BI->second.getSourceRange();
92 if (R.isValid()) {
93 TextDiagnostic TD(OS, AST->getASTContext().getLangOpts(),
94 &AST->getDiagnostics().getDiagnosticOptions());
95 TD.emitDiagnostic(
96 R.getBegin(), DiagnosticsEngine::Note,
97 "\"" + BI->first + "\" binds here",
98 ArrayRef<CharSourceRange>(CharSourceRange::getTokenRange(R)),
99 ArrayRef<FixItHint>(), &AST->getSourceManager());
100 }
101 break;
102 }
103 case OK_Print: {
104 OS << "Binding for \"" << BI->first << "\":\n";
105 BI->second.print(OS, AST->getASTContext().getPrintingPolicy());
106 OS << "\n";
107 break;
108 }
109 case OK_Dump: {
110 OS << "Binding for \"" << BI->first << "\":\n";
111 BI->second.dump(OS, AST->getSourceManager());
112 OS << "\n";
113 break;
114 }
115 }
116 }
117
118 if (MI->getMap().empty())
119 OS << "No bindings.\n";
120 }
121 }
122
123 OS << MatchCount << (MatchCount == 1 ? " match.\n" : " matches.\n");
124 return true;
125}
126
Samuel Benzaquen1f6066c2014-04-23 14:04:52127bool LetQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
128 if (Value) {
129 QS.NamedValues[Name] = Value;
130 } else {
131 QS.NamedValues.erase(Name);
132 }
133 return true;
134}
135
Peter Collingbournec7ae6102013-11-08 08:54:53136#ifndef _MSC_VER
137const QueryKind SetQueryKind<bool>::value;
138const QueryKind SetQueryKind<OutputKind>::value;
139#endif
140
Peter Collingbourne8b1265b2013-11-08 00:08:23141} // namespace query
142} // namespace clang