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));
80 return Switch.Default(Value);
89 QueryParser::lexOrCompleteWord(StringRef &Word) {
91 size_t WordCompletionPos = StringRef::npos;
92 if (CompletionPos && CompletionPos <= Word.data() + Word.size()) {
93 if (CompletionPos < Word.data())
94 WordCompletionPos = 0;
96 WordCompletionPos = CompletionPos - Word.data();
98 return LexOrCompleteWord<T>(
this, Word, WordCompletionPos);
101 QueryRef QueryParser::parseSetBool(
bool QuerySession::*Var) {
103 unsigned Value = lexOrCompleteWord<unsigned>(ValStr)
108 return new InvalidQuery(
"expected 'true' or 'false', got '" + ValStr +
"'");
110 return new SetQuery<bool>(Var, Value);
113 QueryRef QueryParser::parseSetOutputKind() {
115 unsigned OutKind = lexOrCompleteWord<unsigned>(ValStr)
120 if (OutKind == ~0u) {
121 return new InvalidQuery(
"expected 'diag', 'print' or 'dump', got '" +
124 return new SetQuery<OutputKind>(&QuerySession::OutKind,
OutputKind(OutKind));
128 const char *Extra = Begin;
129 if (!lexWord().empty())
130 return new InvalidQuery(
"unexpected extra input: '" +
131 StringRef(Extra, End - Extra) +
"'");
137 enum ParsedQueryKind {
148 enum ParsedQueryVariable {
154 QueryRef makeInvalidQueryFromDiagnostics(
const Diagnostics &Diag) {
156 llvm::raw_string_ostream OS(ErrStr);
157 Diag.printToStreamFull(OS);
158 return new InvalidQuery(OS.str());
163 QueryRef QueryParser::completeMatcherExpression() {
164 std::vector<MatcherCompletion> Comps = Parser::completeExpression(
165 StringRef(Begin, End - Begin), CompletionPos - Begin,
nullptr,
167 for (std::vector<MatcherCompletion>::iterator I = Comps.begin(),
170 Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
176 StringRef CommandStr;
177 ParsedQueryKind QKind = lexOrCompleteWord<ParsedQueryKind>(CommandStr)
179 .Case(
"help", PQK_Help)
180 .Case(
"m", PQK_Match,
false)
181 .Case(
"let", PQK_Let)
182 .Case(
"match", PQK_Match)
183 .Case(
"set", PQK_Set)
184 .Case(
"unlet", PQK_Unlet)
185 .Case(
"quit", PQK_Quit)
186 .Default(PQK_Invalid);
190 return new NoOpQuery;
193 return endQuery(
new HelpQuery);
196 return endQuery(
new QuitQuery);
199 StringRef
Name = lexWord();
202 return new InvalidQuery(
"expected variable name");
205 return completeMatcherExpression();
208 ast_matchers::dynamic::VariantValue Value;
209 if (!Parser::parseExpression(StringRef(Begin, End - Begin),
nullptr,
210 &QS.NamedValues, &Value, &Diag)) {
211 return makeInvalidQueryFromDiagnostics(Diag);
214 return new LetQuery(Name, Value);
219 return completeMatcherExpression();
222 Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
223 StringRef(Begin, End - Begin),
nullptr, &QS.NamedValues, &Diag);
225 return makeInvalidQueryFromDiagnostics(Diag);
227 return new MatchQuery(*Matcher);
232 ParsedQueryVariable Var = lexOrCompleteWord<ParsedQueryVariable>(VarStr)
233 .Case(
"output", PQV_Output)
234 .Case(
"bind-root", PQV_BindRoot)
235 .Default(PQV_Invalid);
237 return new InvalidQuery(
"expected variable name");
238 if (Var == PQV_Invalid)
239 return new InvalidQuery(
"unknown variable: '" + VarStr +
"'");
244 Q = parseSetOutputKind();
247 Q = parseSetBool(&QuerySession::BindRoot);
250 llvm_unreachable(
"Invalid query kind");
257 StringRef Name = lexWord();
260 return new InvalidQuery(
"expected variable name");
262 return endQuery(
new LetQuery(Name, VariantValue()));
266 return new InvalidQuery(
"unknown command: " + CommandStr);
269 llvm_unreachable(
"Invalid query kind");
276 std::vector<LineEditor::Completion>
279 P.CompletionPos = Line.data() + Pos;
282 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)