12 #include "clang/ASTMatchers/Dynamic/Parser.h" 13 #include "clang/Basic/CharInfo.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/ADT/StringSwitch.h" 28 StringRef QueryParser::lexWord() {
37 if (
Line.front() ==
'#') {
42 StringRef
Word =
Line.take_until(isWhitespace);
62 : Word(P->lexWord()), Switch(Word), P(P),
63 WordCompletionPos(StringRef::npos) {
65 if (P->CompletionPos && P->CompletionPos <= Word.data() + Word.size()) {
66 if (P->CompletionPos < Word.data())
67 WordCompletionPos = 0;
69 WordCompletionPos = P->CompletionPos - Word.data();
74 bool IsCompletion =
true) {
76 if (WordCompletionPos == StringRef::npos)
77 Switch.
Case(CaseStr, Value);
78 else if (CaseStr.size() != 0 && IsCompletion && WordCompletionPos <= CaseStr.size() &&
79 CaseStr.substr(0, WordCompletionPos) ==
80 Word.substr(0, WordCompletionPos))
81 P->Completions.push_back(LineEditor::Completion(
82 (CaseStr.substr(WordCompletionPos) +
" ").str(), CaseStr));
86 T
Default(T Value) {
return Switch.Default(Value); }
96 return new InvalidQuery(
"expected 'true' or 'false', got '" + ValStr +
"'");
101 template <
typename QueryType>
QueryRef QueryParser::parseSetOutputKind() {
109 if (OutKind == ~0u) {
111 "expected 'diag', 'print', 'detailed-ast' or 'dump', got '" + ValStr +
117 return new QueryType(&QuerySession::DetailedASTOutput);
119 return new QueryType(&QuerySession::DiagOutput);
121 return new QueryType(&QuerySession::PrintOutput);
124 llvm_unreachable(
"Invalid output kind");
128 const StringRef Extra =
Line;
129 if (!lexWord().empty())
130 return new InvalidQuery(
"unexpected extra input: '" + Extra +
"'");
157 QueryRef makeInvalidQueryFromDiagnostics(
const Diagnostics &Diag) {
159 llvm::raw_string_ostream OS(ErrStr);
160 Diag.printToStreamFull(OS);
166 QueryRef QueryParser::completeMatcherExpression() {
167 std::vector<MatcherCompletion> Comps = Parser::completeExpression(
168 Line, CompletionPos -
Line.begin(),
nullptr, &QS.NamedValues);
169 for (
auto I = Comps.begin(), E = Comps.end(); I != E; ++I) {
170 Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
176 StringRef CommandStr;
177 ParsedQueryKind QKind = LexOrCompleteWord<ParsedQueryKind>(
this, CommandStr)
179 .Case(
"#", PQK_Comment,
false)
180 .Case(
"help", PQK_Help)
181 .Case(
"l", PQK_Let,
false)
182 .Case(
"let", PQK_Let)
183 .Case(
"m", PQK_Match,
false)
184 .Case(
"match", PQK_Match)
185 .Case(
"q", PQK_Quit,
false)
186 .Case(
"quit", PQK_Quit)
187 .Case(
"set", PQK_Set)
188 .Case(
"enable", PQK_Enable)
189 .Case(
"disable", PQK_Disable)
190 .Case(
"unlet", PQK_Unlet)
191 .Default(PQK_Invalid);
205 StringRef
Name = lexWord();
211 return completeMatcherExpression();
214 ast_matchers::dynamic::VariantValue Value;
215 if (!Parser::parseExpression(
Line,
nullptr, &QS.NamedValues, &Value,
217 return makeInvalidQueryFromDiagnostics(Diag);
225 return completeMatcherExpression();
228 auto MatcherSource =
Line.trim();
229 Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
230 MatcherSource,
nullptr, &QS.NamedValues, &Diag);
232 return makeInvalidQueryFromDiagnostics(Diag);
234 return new MatchQuery(MatcherSource, *Matcher);
240 LexOrCompleteWord<ParsedQueryVariable>(
this, VarStr)
241 .Case(
"output", PQV_Output)
242 .Case(
"bind-root", PQV_BindRoot)
243 .Case(
"print-matcher", PQV_PrintMatcher)
244 .Default(PQV_Invalid);
247 if (Var == PQV_Invalid)
248 return new InvalidQuery(
"unknown variable: '" + VarStr +
"'");
253 Q = parseSetOutputKind<SetExclusiveOutputQuery>();
256 Q = parseSetBool(&QuerySession::BindRoot);
258 case PQV_PrintMatcher:
259 Q = parseSetBool(&QuerySession::PrintMatcher);
262 llvm_unreachable(
"Invalid query kind");
271 LexOrCompleteWord<ParsedQueryVariable>(
this, VarStr)
272 .Case(
"output", PQV_Output)
273 .Default(PQV_Invalid);
276 if (Var == PQV_Invalid)
277 return new InvalidQuery(
"unknown variable: '" + VarStr +
"'");
281 if (QKind == PQK_Enable)
282 Q = parseSetOutputKind<EnableOutputQuery>();
283 else if (QKind == PQK_Disable)
284 Q = parseSetOutputKind<DisableOutputQuery>();
286 llvm_unreachable(
"Invalid query kind");
291 StringRef
Name = lexWord();
296 return endQuery(
new LetQuery(Name, VariantValue()));
300 return new InvalidQuery(
"unknown command: " + CommandStr);
303 llvm_unreachable(
"Invalid query kind");
310 std::vector<LineEditor::Completion>
313 P.CompletionPos = Line.data() + Pos;
316 return P.Completions;
Some operations such as code completion produce a set of candidates.
No-op query (i.e. a blank line).
Represents the state for a particular clang-query session.
Any query which resulted in a parse error. The error message is in ErrStr.
llvm::IntrusiveRefCntPtr< Query > QueryRef
Query for "match MATCHER".
static constexpr llvm::StringLiteral Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
LexOrCompleteWord & Case(llvm::StringLiteral CaseStr, const T &Value, bool IsCompletion=true)
Query for "set VAR VALUE".
LexOrCompleteWord(QueryParser *P, StringRef &OutWord)