210 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_H11 12#include "QuerySession.h"13#include "clang/ASTMatchers/Dynamic/VariantValue.h"14#include "llvm/ADT/IntrusiveRefCntPtr.h"15#include <string>16 17namespace clang {18namespace query {19 20enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST };21 22enum 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 QK_File35};36 37class QuerySession;38 39struct Query : llvm::RefCountedBase<Query> {40 Query(QueryKind Kind) : Kind(Kind) {}41 virtual ~Query();42 43 /// Perform the query on \p QS and print output to \p OS.44 ///45 /// \return false if an error occurs, otherwise return true.46 virtual bool run(llvm::raw_ostream &OS, QuerySession &QS) const = 0;47 48 StringRef RemainingContent;49 const QueryKind Kind;50};51 52typedef llvm::IntrusiveRefCntPtr<Query> QueryRef;53 54/// Any query which resulted in a parse error. The error message is in ErrStr.55struct InvalidQuery : Query {56 InvalidQuery(const Twine &ErrStr) : Query(QK_Invalid), ErrStr(ErrStr.str()) {}57 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;58 59 std::string ErrStr;60 61 static bool classof(const Query *Q) { return Q->Kind == QK_Invalid; }62};63 64/// No-op query (i.e. a blank line).65struct NoOpQuery : Query {66 NoOpQuery() : Query(QK_NoOp) {}67 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;68 69 static bool classof(const Query *Q) { return Q->Kind == QK_NoOp; }70};71 72/// Query for "help".73struct HelpQuery : Query {74 HelpQuery() : Query(QK_Help) {}75 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;76 77 static bool classof(const Query *Q) { return Q->Kind == QK_Help; }78};79 80/// Query for "quit".81struct QuitQuery : Query {82 QuitQuery() : Query(QK_Quit) {}83 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;84 85 static bool classof(const Query *Q) { return Q->Kind == QK_Quit; }86};87 88/// Query for "match MATCHER".89struct MatchQuery : Query {90 MatchQuery(StringRef Source,91 const ast_matchers::dynamic::DynTypedMatcher &Matcher)92 : Query(QK_Match), Matcher(Matcher), Source(Source) {}93 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;94 95 ast_matchers::dynamic::DynTypedMatcher Matcher;96 97 StringRef Source;98 99 static bool classof(const Query *Q) { return Q->Kind == QK_Match; }100};101 102struct LetQuery : Query {103 LetQuery(StringRef Name, const ast_matchers::dynamic::VariantValue &Value)104 : Query(QK_Let), Name(Name), Value(Value) {}105 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;106 107 std::string Name;108 ast_matchers::dynamic::VariantValue Value;109 110 static bool classof(const Query *Q) { return Q->Kind == QK_Let; }111};112 113template <typename T> struct SetQueryKind {};114 115template <> struct SetQueryKind<bool> {116 static const QueryKind value = QK_SetBool;117};118 119template <> struct SetQueryKind<OutputKind> {120 static const QueryKind value = QK_SetOutputKind;121};122 123template <> struct SetQueryKind<TraversalKind> {124 static const QueryKind value = QK_SetTraversalKind;125};126 127/// Query for "set VAR VALUE".128template <typename T> struct SetQuery : Query {129 SetQuery(T QuerySession::*Var, T Value)130 : Query(SetQueryKind<T>::value), Var(Var), Value(Value) {}131 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {132 QS.*Var = Value;133 return true;134 }135 136 static bool classof(const Query *Q) {137 return Q->Kind == SetQueryKind<T>::value;138 }139 140 T QuerySession::*Var;141 T Value;142};143 144// Implements the exclusive 'set output dump|diag|print' options.145struct SetExclusiveOutputQuery : Query {146 SetExclusiveOutputQuery(bool QuerySession::*Var)147 : Query(QK_SetOutputKind), Var(Var) {}148 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {149 QS.DiagOutput = false;150 QS.DetailedASTOutput = false;151 QS.PrintOutput = 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.162struct 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 175struct 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 182struct 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 191struct FileQuery : Query {192 FileQuery(StringRef File, StringRef Prefix = StringRef())193 : Query(QK_File), File(File),194 Prefix(!Prefix.empty() ? std::optional<std::string>(Prefix)195 : std::nullopt) {}196 197 bool run(llvm::raw_ostream &OS, QuerySession &QS) const override;198 199 static bool classof(const Query *Q) { return Q->Kind == QK_File; }200 201private:202 std::string File;203 std::optional<std::string> Prefix;204};205 206} // namespace query207} // namespace clang208 209#endif210