1 | //===--- Query.h - clang-query ----------------------------------*- C++ -*-===// |
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_TOOLS_EXTRA_CLANG_QUERY_QUERY_H |
10 | #define |
11 | |
12 | #include "QuerySession.h" |
13 | #include "clang/ASTMatchers/Dynamic/VariantValue.h" |
14 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
15 | #include <string> |
16 | |
17 | namespace clang { |
18 | namespace query { |
19 | |
20 | enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST, OK_SrcLoc }; |
21 | |
22 | enum QueryKind { |
23 | QK_Invalid, |
24 | QK_NoOp, |
25 | QK_Help, |
26 | QK_Let, |
27 | QK_Match, |
28 | QK_SetBool, |
29 | QK_SetOutputKind, |
30 | QK_SetTraversalKind, |
31 | QK_EnableOutputKind, |
32 | QK_DisableOutputKind, |
33 | QK_Quit |
34 | }; |
35 | |
36 | class QuerySession; |
37 | |
38 | struct Query : llvm::RefCountedBase<Query> { |
39 | Query(QueryKind Kind) : Kind(Kind) {} |
40 | virtual ~Query(); |
41 | |
42 | /// Perform the query on \p QS and print output to \p OS. |
43 | /// |
44 | /// \return false if an error occurs, otherwise return true. |
45 | virtual bool run(llvm::raw_ostream &OS, QuerySession &QS) const = 0; |
46 | |
47 | StringRef RemainingContent; |
48 | const QueryKind Kind; |
49 | }; |
50 | |
51 | typedef llvm::IntrusiveRefCntPtr<Query> QueryRef; |
52 | |
53 | /// Any query which resulted in a parse error. The error message is in ErrStr. |
54 | struct InvalidQuery : Query { |
55 | InvalidQuery(const Twine &ErrStr) : Query(QK_Invalid), ErrStr(ErrStr.str()) {} |
56 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; |
57 | |
58 | std::string ErrStr; |
59 | |
60 | static bool classof(const Query *Q) { return Q->Kind == QK_Invalid; } |
61 | }; |
62 | |
63 | /// No-op query (i.e. a blank line). |
64 | struct NoOpQuery : Query { |
65 | NoOpQuery() : Query(QK_NoOp) {} |
66 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; |
67 | |
68 | static bool classof(const Query *Q) { return Q->Kind == QK_NoOp; } |
69 | }; |
70 | |
71 | /// Query for "help". |
72 | struct HelpQuery : Query { |
73 | HelpQuery() : Query(QK_Help) {} |
74 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; |
75 | |
76 | static bool classof(const Query *Q) { return Q->Kind == QK_Help; } |
77 | }; |
78 | |
79 | /// Query for "quit". |
80 | struct QuitQuery : Query { |
81 | QuitQuery() : Query(QK_Quit) {} |
82 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; |
83 | |
84 | static bool classof(const Query *Q) { return Q->Kind == QK_Quit; } |
85 | }; |
86 | |
87 | /// Query for "match MATCHER". |
88 | struct MatchQuery : Query { |
89 | MatchQuery(StringRef Source, |
90 | const ast_matchers::dynamic::DynTypedMatcher &Matcher) |
91 | : Query(QK_Match), Matcher(Matcher), Source(Source) {} |
92 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; |
93 | |
94 | ast_matchers::dynamic::DynTypedMatcher Matcher; |
95 | |
96 | StringRef Source; |
97 | |
98 | static bool classof(const Query *Q) { return Q->Kind == QK_Match; } |
99 | }; |
100 | |
101 | struct LetQuery : Query { |
102 | LetQuery(StringRef Name, const ast_matchers::dynamic::VariantValue &Value) |
103 | : Query(QK_Let), Name(Name), Value(Value) {} |
104 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; |
105 | |
106 | std::string Name; |
107 | ast_matchers::dynamic::VariantValue Value; |
108 | |
109 | static bool classof(const Query *Q) { return Q->Kind == QK_Let; } |
110 | }; |
111 | |
112 | template <typename T> struct SetQueryKind {}; |
113 | |
114 | template <> struct SetQueryKind<bool> { |
115 | static const QueryKind value = QK_SetBool; |
116 | }; |
117 | |
118 | template <> struct SetQueryKind<OutputKind> { |
119 | static const QueryKind value = QK_SetOutputKind; |
120 | }; |
121 | |
122 | template <> struct SetQueryKind<TraversalKind> { |
123 | static const QueryKind value = QK_SetTraversalKind; |
124 | }; |
125 | |
126 | /// Query for "set VAR VALUE". |
127 | template <typename T> struct SetQuery : Query { |
128 | SetQuery(T QuerySession::*Var, T Value) |
129 | : Query(SetQueryKind<T>::value), Var(Var), Value(Value) {} |
130 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override { |
131 | QS.*Var = Value; |
132 | return true; |
133 | } |
134 | |
135 | static bool classof(const Query *Q) { |
136 | return Q->Kind == SetQueryKind<T>::value; |
137 | } |
138 | |
139 | T QuerySession::*Var; |
140 | T Value; |
141 | }; |
142 | |
143 | // Implements the exclusive 'set output dump|diag|print' options. |
144 | struct SetExclusiveOutputQuery : Query { |
145 | SetExclusiveOutputQuery(bool QuerySession::*Var) |
146 | : Query(QK_SetOutputKind), Var(Var) {} |
147 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override { |
148 | QS.DiagOutput = false; |
149 | QS.DetailedASTOutput = false; |
150 | QS.PrintOutput = false; |
151 | QS.SrcLocOutput = false; |
152 | QS.*Var = true; |
153 | return true; |
154 | } |
155 | |
156 | static bool classof(const Query *Q) { return Q->Kind == QK_SetOutputKind; } |
157 | |
158 | bool QuerySession::*Var; |
159 | }; |
160 | |
161 | // Implements the non-exclusive 'set output dump|diag|print' options. |
162 | struct SetNonExclusiveOutputQuery : Query { |
163 | SetNonExclusiveOutputQuery(QueryKind Kind, bool QuerySession::*Var, |
164 | bool Value) |
165 | : Query(Kind), Var(Var), Value(Value) {} |
166 | bool run(llvm::raw_ostream &OS, QuerySession &QS) const override { |
167 | QS.*Var = Value; |
168 | return true; |
169 | } |
170 | |
171 | bool QuerySession::*Var; |
172 | bool Value; |
173 | }; |
174 | |
175 | struct EnableOutputQuery : SetNonExclusiveOutputQuery { |
176 | EnableOutputQuery(bool QuerySession::*Var) |
177 | : SetNonExclusiveOutputQuery(QK_EnableOutputKind, Var, true) {} |
178 | |
179 | static bool classof(const Query *Q) { return Q->Kind == QK_EnableOutputKind; } |
180 | }; |
181 | |
182 | struct DisableOutputQuery : SetNonExclusiveOutputQuery { |
183 | DisableOutputQuery(bool QuerySession::*Var) |
184 | : SetNonExclusiveOutputQuery(QK_DisableOutputKind, Var, false) {} |
185 | |
186 | static bool classof(const Query *Q) { |
187 | return Q->Kind == QK_DisableOutputKind; |
188 | } |
189 | }; |
190 | |
191 | } // namespace query |
192 | } // namespace clang |
193 | |
194 | #endif |
195 | |