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" 29 StringRef QueryParser::lexWord() {
38 if (
Line.front() ==
'#') {
43 StringRef Word =
Line.take_until(isWhitespace);
63 : Word(P->lexWord()), Switch(Word), P(P),
64 WordCompletionPos(StringRef::npos) {
66 if (P->CompletionPos && P->CompletionPos <= Word.data() + Word.size()) {
67 if (P->CompletionPos < Word.data())
68 WordCompletionPos = 0;
70 WordCompletionPos = P->CompletionPos - Word.data();
75 bool IsCompletion =
true) {
77 if (WordCompletionPos == StringRef::npos)
78 Switch.
Case(CaseStr, Value);
79 else if (CaseStr.size() != 0 && IsCompletion && WordCompletionPos <= CaseStr.size() &&
80 CaseStr.substr(0, WordCompletionPos) ==
81 Word.substr(0, WordCompletionPos))
82 P->Completions.push_back(LineEditor::Completion(
83 (CaseStr.substr(WordCompletionPos) +
" ").str(), CaseStr));
87 T
Default(T Value) {
return Switch.Default(Value); }
97 return new InvalidQuery(
"expected 'true' or 'false', got '" + ValStr +
"'");
102 template <
typename QueryType>
QueryRef QueryParser::parseSetOutputKind() {
110 if (OutKind == ~0u) {
112 "expected 'diag', 'print', 'detailed-ast' or 'dump', got '" + ValStr +
118 return new QueryType(&QuerySession::DetailedASTOutput);
120 return new QueryType(&QuerySession::DiagOutput);
122 return new QueryType(&QuerySession::PrintOutput);
125 llvm_unreachable(
"Invalid output kind");
129 const StringRef Extra =
Line;
130 if (!lexWord().empty())
131 return new InvalidQuery(
"unexpected extra input: '" + Extra +
"'");
158 QueryRef makeInvalidQueryFromDiagnostics(
const Diagnostics &Diag) {
160 llvm::raw_string_ostream OS(ErrStr);
161 Diag.printToStreamFull(OS);
167 QueryRef QueryParser::completeMatcherExpression() {
168 std::vector<MatcherCompletion> Comps = Parser::completeExpression(
169 Line, CompletionPos -
Line.begin(),
nullptr, &QS.NamedValues);
170 for (
auto I = Comps.begin(), E = Comps.end(); I != E; ++I) {
171 Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
177 StringRef CommandStr;
178 ParsedQueryKind QKind = LexOrCompleteWord<ParsedQueryKind>(
this, CommandStr)
180 .Case(
"#", PQK_Comment,
false)
181 .Case(
"help", PQK_Help)
182 .Case(
"l", PQK_Let,
false)
183 .Case(
"let", PQK_Let)
184 .Case(
"m", PQK_Match,
false)
185 .Case(
"match", PQK_Match)
186 .Case(
"q", PQK_Quit,
false)
187 .Case(
"quit", PQK_Quit)
188 .Case(
"set", PQK_Set)
189 .Case(
"enable", PQK_Enable)
190 .Case(
"disable", PQK_Disable)
191 .Case(
"unlet", PQK_Unlet)
192 .Default(PQK_Invalid);
206 StringRef
Name = lexWord();
212 return completeMatcherExpression();
215 ast_matchers::dynamic::VariantValue Value;
216 if (!Parser::parseExpression(
Line,
nullptr, &QS.NamedValues, &Value,
218 return makeInvalidQueryFromDiagnostics(Diag);
226 return completeMatcherExpression();
229 auto MatcherSource =
Line.trim();
230 Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
231 MatcherSource,
nullptr, &QS.NamedValues, &Diag);
233 return makeInvalidQueryFromDiagnostics(Diag);
235 return new MatchQuery(MatcherSource, *Matcher);
241 LexOrCompleteWord<ParsedQueryVariable>(
this, VarStr)
242 .Case(
"output", PQV_Output)
243 .Case(
"bind-root", PQV_BindRoot)
244 .Case(
"print-matcher", PQV_PrintMatcher)
245 .Default(PQV_Invalid);
248 if (Var == PQV_Invalid)
249 return new InvalidQuery(
"unknown variable: '" + VarStr +
"'");
254 Q = parseSetOutputKind<SetExclusiveOutputQuery>();
257 Q = parseSetBool(&QuerySession::BindRoot);
259 case PQV_PrintMatcher:
260 Q = parseSetBool(&QuerySession::PrintMatcher);
263 llvm_unreachable(
"Invalid query kind");
272 LexOrCompleteWord<ParsedQueryVariable>(
this, VarStr)
273 .Case(
"output", PQV_Output)
274 .Default(PQV_Invalid);
277 if (Var == PQV_Invalid)
278 return new InvalidQuery(
"unknown variable: '" + VarStr +
"'");
282 if (QKind == PQK_Enable)
283 Q = parseSetOutputKind<EnableOutputQuery>();
284 else if (QKind == PQK_Disable)
285 Q = parseSetOutputKind<DisableOutputQuery>();
287 llvm_unreachable(
"Invalid query kind");
292 StringRef
Name = lexWord();
297 return endQuery(
new LetQuery(Name, VariantValue()));
301 return new InvalidQuery(
"unknown command: " + CommandStr);
304 llvm_unreachable(
"Invalid query kind");
311 std::vector<LineEditor::Completion>
314 P.CompletionPos = Line.data() +
Pos;
317 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)