13 #include "clang/ASTMatchers/Dynamic/Parser.h"
14 #include "clang/Basic/CharInfo.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/StringSwitch.h"
20 using namespace clang::ast_matchers::dynamic;
29 StringRef QueryParser::lexWord() {
32 return StringRef(Begin, 0);
34 if (!isWhitespace(*Begin))
40 const char *WordBegin = Begin;
45 if (Begin == End || isWhitespace(*Begin))
46 return StringRef(WordBegin, Begin - WordBegin);
62 : Switch(Word), P(P), Word(Word), WordCompletionPos(WCP) {}
66 bool IsCompletion =
true) {
67 StringRef CaseStr(S, N - 1);
69 if (WordCompletionPos == StringRef::npos)
70 Switch.Case(S, Value);
71 else if (N != 1 && IsCompletion && WordCompletionPos <= CaseStr.size() &&
72 CaseStr.substr(0, WordCompletionPos) ==
73 Word.substr(0, WordCompletionPos))
74 P->Completions.push_back(LineEditor::Completion(
75 (CaseStr.substr(WordCompletionPos) +
" ").str(), CaseStr));
79 T
Default(
const T &Value)
const {
return Switch.Default(Value); }
87 QueryParser::lexOrCompleteWord(StringRef &Word) {
89 size_t WordCompletionPos = StringRef::npos;
90 if (CompletionPos && CompletionPos <= Word.data() + Word.size()) {
91 if (CompletionPos < Word.data())
92 WordCompletionPos = 0;
94 WordCompletionPos = CompletionPos - Word.data();
96 return LexOrCompleteWord<T>(
this, Word, WordCompletionPos);
99 QueryRef QueryParser::parseSetBool(
bool QuerySession::*Var) {
101 unsigned Value = lexOrCompleteWord<unsigned>(ValStr)
106 return new InvalidQuery(
"expected 'true' or 'false', got '" + ValStr +
"'");
108 return new SetQuery<bool>(Var, Value);
111 QueryRef QueryParser::parseSetOutputKind() {
113 unsigned OutKind = lexOrCompleteWord<unsigned>(ValStr)
118 if (OutKind == ~0u) {
119 return new InvalidQuery(
"expected 'diag', 'print' or 'dump', got '" +
122 return new SetQuery<OutputKind>(&QuerySession::OutKind,
OutputKind(OutKind));
126 const char *Extra = Begin;
127 if (!lexWord().empty())
128 return new InvalidQuery(
"unexpected extra input: '" +
129 StringRef(Extra, End - Extra) +
"'");
135 enum ParsedQueryKind {
146 enum ParsedQueryVariable { PQV_Invalid, PQV_Output, PQV_BindRoot };
148 QueryRef makeInvalidQueryFromDiagnostics(
const Diagnostics &Diag) {
150 llvm::raw_string_ostream OS(ErrStr);
151 Diag.printToStreamFull(OS);
152 return new InvalidQuery(OS.str());
157 QueryRef QueryParser::completeMatcherExpression() {
158 std::vector<MatcherCompletion> Comps = Parser::completeExpression(
159 StringRef(Begin, End - Begin), CompletionPos - Begin,
nullptr,
161 for (
auto I = Comps.begin(), E = Comps.end(); I != E; ++I) {
162 Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
168 StringRef CommandStr;
169 ParsedQueryKind QKind = lexOrCompleteWord<ParsedQueryKind>(CommandStr)
171 .Case(
"help", PQK_Help)
172 .Case(
"m", PQK_Match,
false)
173 .Case(
"let", PQK_Let)
174 .Case(
"match", PQK_Match)
175 .Case(
"set", PQK_Set)
176 .Case(
"unlet", PQK_Unlet)
177 .Case(
"quit", PQK_Quit)
178 .Default(PQK_Invalid);
182 return new NoOpQuery;
185 return endQuery(
new HelpQuery);
188 return endQuery(
new QuitQuery);
191 StringRef
Name = lexWord();
194 return new InvalidQuery(
"expected variable name");
197 return completeMatcherExpression();
200 ast_matchers::dynamic::VariantValue Value;
201 if (!Parser::parseExpression(StringRef(Begin, End - Begin),
nullptr,
202 &QS.NamedValues, &Value, &Diag)) {
203 return makeInvalidQueryFromDiagnostics(Diag);
206 return new LetQuery(Name, Value);
211 return completeMatcherExpression();
214 Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
215 StringRef(Begin, End - Begin),
nullptr, &QS.NamedValues, &Diag);
217 return makeInvalidQueryFromDiagnostics(Diag);
219 return new MatchQuery(*Matcher);
224 ParsedQueryVariable Var = lexOrCompleteWord<ParsedQueryVariable>(VarStr)
225 .Case(
"output", PQV_Output)
226 .Case(
"bind-root", PQV_BindRoot)
227 .Default(PQV_Invalid);
229 return new InvalidQuery(
"expected variable name");
230 if (Var == PQV_Invalid)
231 return new InvalidQuery(
"unknown variable: '" + VarStr +
"'");
236 Q = parseSetOutputKind();
239 Q = parseSetBool(&QuerySession::BindRoot);
242 llvm_unreachable(
"Invalid query kind");
249 StringRef Name = lexWord();
252 return new InvalidQuery(
"expected variable name");
254 return endQuery(
new LetQuery(Name, VariantValue()));
258 return new InvalidQuery(
"unknown command: " + CommandStr);
261 llvm_unreachable(
"Invalid query kind");
268 std::vector<LineEditor::Completion>
271 P.CompletionPos = Line.data() + Pos;
274 return P.Completions;
Represents the state for a particular clang-query session.
llvm::IntrusiveRefCntPtr< Query > QueryRef
LexOrCompleteWord & Case(const char(&S)[N], const T &Value, bool IsCompletion=true)
T Default(const T &Value) const
LexOrCompleteWord(QueryParser *P, StringRef Word, size_t WCP)