Skip to content

Commit a49fe5d

Browse files
committedOct 29, 2018
[clang-query] Add non-exclusive output API
Summary: Add granular options for AST dumping, text printing and diagnostics. This makes it possible to * Have both diag and dump active at once * Extend the output with other queryable content in the future. Reviewers: aaron.ballman, pcc, ioeric, ilya-biryukov, klimek, sammccall Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D52857 llvm-svn: 345522
1 parent eb15d00 commit a49fe5d

File tree

6 files changed

+118
-10
lines changed

6 files changed

+118
-10
lines changed
 

Diff for: ‎clang-tools-extra/clang-query/Query.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
4545
"Set whether to print the current matcher,\n"
4646
" set output <feature> "
4747
"Set whether to output only <feature> content.\n"
48+
" enable output <feature> "
49+
"Enable <feature> content non-exclusively.\n"
50+
" disable output <feature> "
51+
"Disable <feature> content non-exclusively.\n"
4852
" quit, q "
4953
"Terminates the query session.\n\n"
5054
"Several commands accept a <feature> parameter. The available features "

Diff for: ‎clang-tools-extra/clang-query/Query.h

+32
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ enum QueryKind {
2929
QK_Match,
3030
QK_SetBool,
3131
QK_SetOutputKind,
32+
QK_EnableOutputKind,
33+
QK_DisableOutputKind,
3234
QK_Quit
3335
};
3436

@@ -151,6 +153,36 @@ struct SetExclusiveOutputQuery : Query {
151153
bool QuerySession::*Var;
152154
};
153155

156+
// Implements the non-exclusive 'set output dump|diag|print' options.
157+
struct SetNonExclusiveOutputQuery : Query {
158+
SetNonExclusiveOutputQuery(QueryKind Kind, bool QuerySession::*Var,
159+
bool Value)
160+
: Query(Kind), Var(Var), Value(Value) {}
161+
bool run(llvm::raw_ostream &OS, QuerySession &QS) const override {
162+
QS.*Var = Value;
163+
return true;
164+
}
165+
166+
bool QuerySession::*Var;
167+
bool Value;
168+
};
169+
170+
struct EnableOutputQuery : SetNonExclusiveOutputQuery {
171+
EnableOutputQuery(bool QuerySession::*Var)
172+
: SetNonExclusiveOutputQuery(QK_EnableOutputKind, Var, true) {}
173+
174+
static bool classof(const Query *Q) { return Q->Kind == QK_EnableOutputKind; }
175+
};
176+
177+
struct DisableOutputQuery : SetNonExclusiveOutputQuery {
178+
DisableOutputQuery(bool QuerySession::*Var)
179+
: SetNonExclusiveOutputQuery(QK_DisableOutputKind, Var, false) {}
180+
181+
static bool classof(const Query *Q) {
182+
return Q->Kind == QK_DisableOutputKind;
183+
}
184+
};
185+
154186
} // namespace query
155187
} // namespace clang
156188

Diff for: ‎clang-tools-extra/clang-query/QueryParser.cpp

+32-6
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) {
106106
return new SetQuery<bool>(Var, Value);
107107
}
108108

109-
QueryRef QueryParser::parseSetOutputKind() {
109+
template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
110110
StringRef ValStr;
111111
unsigned OutKind = LexOrCompleteWord<unsigned>(this, ValStr)
112112
.Case("diag", OK_Diag)
@@ -122,11 +122,11 @@ QueryRef QueryParser::parseSetOutputKind() {
122122

123123
switch (OutKind) {
124124
case OK_DetailedAST:
125-
return new SetExclusiveOutputQuery(&QuerySession::DetailedASTOutput);
125+
return new QueryType(&QuerySession::DetailedASTOutput);
126126
case OK_Diag:
127-
return new SetExclusiveOutputQuery(&QuerySession::DiagOutput);
127+
return new QueryType(&QuerySession::DiagOutput);
128128
case OK_Print:
129-
return new SetExclusiveOutputQuery(&QuerySession::PrintOutput);
129+
return new QueryType(&QuerySession::PrintOutput);
130130
}
131131

132132
llvm_unreachable("Invalid output kind");
@@ -151,7 +151,9 @@ enum ParsedQueryKind {
151151
PQK_Match,
152152
PQK_Set,
153153
PQK_Unlet,
154-
PQK_Quit
154+
PQK_Quit,
155+
PQK_Enable,
156+
PQK_Disable
155157
};
156158

157159
enum ParsedQueryVariable {
@@ -193,6 +195,8 @@ QueryRef QueryParser::doParse() {
193195
.Case("q", PQK_Quit, /*IsCompletion=*/false)
194196
.Case("quit", PQK_Quit)
195197
.Case("set", PQK_Set)
198+
.Case("enable", PQK_Enable)
199+
.Case("disable", PQK_Disable)
196200
.Case("unlet", PQK_Unlet)
197201
.Default(PQK_Invalid);
198202

@@ -256,7 +260,7 @@ QueryRef QueryParser::doParse() {
256260
QueryRef Q;
257261
switch (Var) {
258262
case PQV_Output:
259-
Q = parseSetOutputKind();
263+
Q = parseSetOutputKind<SetExclusiveOutputQuery>();
260264
break;
261265
case PQV_BindRoot:
262266
Q = parseSetBool(&QuerySession::BindRoot);
@@ -270,6 +274,28 @@ QueryRef QueryParser::doParse() {
270274

271275
return endQuery(Q);
272276
}
277+
case PQK_Enable:
278+
case PQK_Disable: {
279+
StringRef VarStr;
280+
ParsedQueryVariable Var =
281+
LexOrCompleteWord<ParsedQueryVariable>(this, VarStr)
282+
.Case("output", PQV_Output)
283+
.Default(PQV_Invalid);
284+
if (VarStr.empty())
285+
return new InvalidQuery("expected variable name");
286+
if (Var == PQV_Invalid)
287+
return new InvalidQuery("unknown variable: '" + VarStr + "'");
288+
289+
QueryRef Q;
290+
291+
if (QKind == PQK_Enable)
292+
Q = parseSetOutputKind<EnableOutputQuery>();
293+
else if (QKind == PQK_Disable)
294+
Q = parseSetOutputKind<DisableOutputQuery>();
295+
else
296+
llvm_unreachable("Invalid query kind");
297+
return endQuery(Q);
298+
}
273299

274300
case PQK_Unlet: {
275301
StringRef Name = lexWord();

Diff for: ‎clang-tools-extra/clang-query/QueryParser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class QueryParser {
4444
template <typename T> struct LexOrCompleteWord;
4545

4646
QueryRef parseSetBool(bool QuerySession::*Var);
47-
QueryRef parseSetOutputKind();
47+
template <typename QueryType> QueryRef parseSetOutputKind();
4848
QueryRef completeMatcherExpression();
4949

5050
QueryRef endQuery(QueryRef Q);

Diff for: ‎clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ TEST_F(QueryEngineTest, Basic) {
111111

112112
Str.clear();
113113

114+
EXPECT_TRUE(EnableOutputQuery(&QuerySession::DiagOutput).run(OS, S));
115+
EXPECT_TRUE(EnableOutputQuery(&QuerySession::DetailedASTOutput).run(OS, S));
116+
EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));
117+
118+
{
119+
auto Output = OS.str();
120+
EXPECT_TRUE(Output.find("FunctionDecl") != std::string::npos);
121+
EXPECT_TRUE(Output.find("foo.cc:1:1: note: \"root\" binds here") !=
122+
std::string::npos);
123+
}
124+
125+
Str.clear();
126+
114127
EXPECT_TRUE(SetQuery<bool>(&QuerySession::BindRoot, false).run(OS, S));
115128
EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));
116129

Diff for: ‎clang-tools-extra/unittests/clang-query/QueryParserTest.cpp

+36-3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ TEST_F(QueryParserTest, Set) {
9090
ASSERT_TRUE(isa<SetExclusiveOutputQuery>(Q));
9191
EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<SetExclusiveOutputQuery>(Q)->Var);
9292

93+
Q = parse("enable output detailed-ast");
94+
ASSERT_TRUE(isa<EnableOutputQuery>(Q));
95+
EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<EnableOutputQuery>(Q)->Var);
96+
97+
Q = parse("enable");
98+
ASSERT_TRUE(isa<InvalidQuery>(Q));
99+
EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);
100+
101+
Q = parse("disable output detailed-ast");
102+
ASSERT_TRUE(isa<DisableOutputQuery>(Q));
103+
EXPECT_EQ(&QuerySession::DetailedASTOutput, cast<DisableOutputQuery>(Q)->Var);
104+
93105
Q = parse("set bind-root foo");
94106
ASSERT_TRUE(isa<InvalidQuery>(Q));
95107
EXPECT_EQ("expected 'true' or 'false', got 'foo'",
@@ -163,7 +175,7 @@ TEST_F(QueryParserTest, Comment) {
163175
TEST_F(QueryParserTest, Complete) {
164176
std::vector<llvm::LineEditor::Completion> Comps =
165177
QueryParser::complete("", 0, QS);
166-
ASSERT_EQ(6u, Comps.size());
178+
ASSERT_EQ(8u, Comps.size());
167179
EXPECT_EQ("help ", Comps[0].TypedText);
168180
EXPECT_EQ("help", Comps[0].DisplayText);
169181
EXPECT_EQ("let ", Comps[1].TypedText);
@@ -174,14 +186,35 @@ TEST_F(QueryParserTest, Complete) {
174186
EXPECT_EQ("quit", Comps[3].DisplayText);
175187
EXPECT_EQ("set ", Comps[4].TypedText);
176188
EXPECT_EQ("set", Comps[4].DisplayText);
177-
EXPECT_EQ("unlet ", Comps[5].TypedText);
178-
EXPECT_EQ("unlet", Comps[5].DisplayText);
189+
EXPECT_EQ("enable ", Comps[5].TypedText);
190+
EXPECT_EQ("enable", Comps[5].DisplayText);
191+
EXPECT_EQ("disable ", Comps[6].TypedText);
192+
EXPECT_EQ("disable", Comps[6].DisplayText);
193+
EXPECT_EQ("unlet ", Comps[7].TypedText);
194+
EXPECT_EQ("unlet", Comps[7].DisplayText);
179195

180196
Comps = QueryParser::complete("set o", 5, QS);
181197
ASSERT_EQ(1u, Comps.size());
182198
EXPECT_EQ("utput ", Comps[0].TypedText);
183199
EXPECT_EQ("output", Comps[0].DisplayText);
184200

201+
Comps = QueryParser::complete("enable ", 7, QS);
202+
ASSERT_EQ(1u, Comps.size());
203+
EXPECT_EQ("output ", Comps[0].TypedText);
204+
EXPECT_EQ("output", Comps[0].DisplayText);
205+
206+
Comps = QueryParser::complete("enable output ", 14, QS);
207+
ASSERT_EQ(4u, Comps.size());
208+
209+
EXPECT_EQ("diag ", Comps[0].TypedText);
210+
EXPECT_EQ("diag", Comps[0].DisplayText);
211+
EXPECT_EQ("print ", Comps[1].TypedText);
212+
EXPECT_EQ("print", Comps[1].DisplayText);
213+
EXPECT_EQ("detailed-ast ", Comps[2].TypedText);
214+
EXPECT_EQ("detailed-ast", Comps[2].DisplayText);
215+
EXPECT_EQ("dump ", Comps[3].TypedText);
216+
EXPECT_EQ("dump", Comps[3].DisplayText);
217+
185218
Comps = QueryParser::complete("match while", 11, QS);
186219
ASSERT_EQ(1u, Comps.size());
187220
EXPECT_EQ("Stmt(", Comps[0].TypedText);

0 commit comments

Comments
 (0)
Please sign in to comment.