mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 16:56:35 +00:00
Add a way to set traversal mode in clang-query
Reviewers: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73037
This commit is contained in:
parent
174322c273
commit
10f0f98eac
@ -43,6 +43,15 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
|
||||
"Set whether to bind the root matcher to \"root\".\n"
|
||||
" set print-matcher (true|false) "
|
||||
"Set whether to print the current matcher,\n"
|
||||
" set traversal <kind> "
|
||||
"Set traversal kind of clang-query session. Available kinds are:\n"
|
||||
" AsIs "
|
||||
"Print and match the AST as clang sees it.\n"
|
||||
" IgnoreImplicitCastsAndParentheses "
|
||||
"Omit implicit casts and parens in matching and dumping.\n"
|
||||
" IgnoreUnlessSpelledInSource "
|
||||
"Omit AST nodes unless spelled in the source. This mode is the "
|
||||
"default.\n"
|
||||
" set output <feature> "
|
||||
"Set whether to output only <feature> content.\n"
|
||||
" enable output <feature> "
|
||||
@ -98,6 +107,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
|
||||
OS << "Not a valid top-level matcher.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
AST->getASTContext().getParentMapContext().setTraversalKind(QS.TK);
|
||||
Finder.matchAST(AST->getASTContext());
|
||||
|
||||
if (QS.PrintMatcher) {
|
||||
@ -148,6 +159,7 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
|
||||
const SourceManager &SM = Ctx.getSourceManager();
|
||||
ASTDumper Dumper(OS, &Ctx.getCommentCommandTraits(), &SM,
|
||||
SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
|
||||
Dumper.SetTraversalKind(QS.TK);
|
||||
Dumper.Visit(BI->second);
|
||||
OS << "\n";
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ enum QueryKind {
|
||||
QK_Match,
|
||||
QK_SetBool,
|
||||
QK_SetOutputKind,
|
||||
QK_SetTraversalKind,
|
||||
QK_EnableOutputKind,
|
||||
QK_DisableOutputKind,
|
||||
QK_Quit
|
||||
@ -119,6 +120,10 @@ template <> struct SetQueryKind<OutputKind> {
|
||||
static const QueryKind value = QK_SetOutputKind;
|
||||
};
|
||||
|
||||
template <> struct SetQueryKind<ast_type_traits::TraversalKind> {
|
||||
static const QueryKind value = QK_SetTraversalKind;
|
||||
};
|
||||
|
||||
/// Query for "set VAR VALUE".
|
||||
template <typename T> struct SetQuery : Query {
|
||||
SetQuery(T QuerySession::*Var, T Value)
|
||||
|
@ -128,6 +128,24 @@ template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() {
|
||||
llvm_unreachable("Invalid output kind");
|
||||
}
|
||||
|
||||
QueryRef QueryParser::parseSetTraversalKind(
|
||||
ast_type_traits::TraversalKind QuerySession::*Var) {
|
||||
StringRef ValStr;
|
||||
unsigned Value =
|
||||
LexOrCompleteWord<unsigned>(this, ValStr)
|
||||
.Case("AsIs", ast_type_traits::TK_AsIs)
|
||||
.Case("IgnoreImplicitCastsAndParentheses",
|
||||
ast_type_traits::TK_IgnoreImplicitCastsAndParentheses)
|
||||
.Case("IgnoreUnlessSpelledInSource",
|
||||
ast_type_traits::TK_IgnoreUnlessSpelledInSource)
|
||||
.Default(~0u);
|
||||
if (Value == ~0u) {
|
||||
return new InvalidQuery("expected traversal kind, got '" + ValStr + "'");
|
||||
}
|
||||
return new SetQuery<ast_type_traits::TraversalKind>(
|
||||
Var, static_cast<ast_type_traits::TraversalKind>(Value));
|
||||
}
|
||||
|
||||
QueryRef QueryParser::endQuery(QueryRef Q) {
|
||||
StringRef Extra = Line;
|
||||
StringRef ExtraTrimmed = Extra.drop_while(
|
||||
@ -171,7 +189,8 @@ enum ParsedQueryVariable {
|
||||
PQV_Invalid,
|
||||
PQV_Output,
|
||||
PQV_BindRoot,
|
||||
PQV_PrintMatcher
|
||||
PQV_PrintMatcher,
|
||||
PQV_Traversal
|
||||
};
|
||||
|
||||
QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
|
||||
@ -272,6 +291,7 @@ QueryRef QueryParser::doParse() {
|
||||
.Case("output", PQV_Output)
|
||||
.Case("bind-root", PQV_BindRoot)
|
||||
.Case("print-matcher", PQV_PrintMatcher)
|
||||
.Case("traversal", PQV_Traversal)
|
||||
.Default(PQV_Invalid);
|
||||
if (VarStr.empty())
|
||||
return new InvalidQuery("expected variable name");
|
||||
@ -289,6 +309,9 @@ QueryRef QueryParser::doParse() {
|
||||
case PQV_PrintMatcher:
|
||||
Q = parseSetBool(&QuerySession::PrintMatcher);
|
||||
break;
|
||||
case PQV_Traversal:
|
||||
Q = parseSetTraversalKind(&QuerySession::TK);
|
||||
break;
|
||||
case PQV_Invalid:
|
||||
llvm_unreachable("Invalid query kind");
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ private:
|
||||
template <typename T> struct LexOrCompleteWord;
|
||||
|
||||
QueryRef parseSetBool(bool QuerySession::*Var);
|
||||
QueryRef
|
||||
parseSetTraversalKind(ast_type_traits::TraversalKind QuerySession::*Var);
|
||||
template <typename QueryType> QueryRef parseSetOutputKind();
|
||||
QueryRef completeMatcherExpression();
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_SESSION_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_SESSION_H
|
||||
|
||||
#include "clang/AST/ASTTypeTraits.h"
|
||||
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
@ -25,7 +26,7 @@ public:
|
||||
QuerySession(llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs)
|
||||
: ASTs(ASTs), PrintOutput(false), DiagOutput(true),
|
||||
DetailedASTOutput(false), BindRoot(true), PrintMatcher(false),
|
||||
Terminate(false) {}
|
||||
Terminate(false), TK(ast_type_traits::TK_IgnoreUnlessSpelledInSource) {}
|
||||
|
||||
llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs;
|
||||
|
||||
@ -36,6 +37,8 @@ public:
|
||||
bool BindRoot;
|
||||
bool PrintMatcher;
|
||||
bool Terminate;
|
||||
|
||||
ast_type_traits::TraversalKind TK;
|
||||
llvm::StringMap<ast_matchers::dynamic::VariantValue> NamedValues;
|
||||
};
|
||||
|
||||
|
@ -110,6 +110,18 @@ TEST_F(QueryParserTest, Set) {
|
||||
ASSERT_TRUE(isa<SetQuery<bool> >(Q));
|
||||
EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var);
|
||||
EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value);
|
||||
|
||||
Q = parse("set traversal AsIs");
|
||||
ASSERT_TRUE(isa<SetQuery<ast_type_traits::TraversalKind>>(Q));
|
||||
EXPECT_EQ(&QuerySession::TK,
|
||||
cast<SetQuery<ast_type_traits::TraversalKind>>(Q)->Var);
|
||||
EXPECT_EQ(ast_type_traits::TK_AsIs,
|
||||
cast<SetQuery<ast_type_traits::TraversalKind>>(Q)->Value);
|
||||
|
||||
Q = parse("set traversal NotATraversal");
|
||||
ASSERT_TRUE(isa<InvalidQuery>(Q));
|
||||
EXPECT_EQ("expected traversal kind, got 'NotATraversal'",
|
||||
cast<InvalidQuery>(Q)->ErrStr);
|
||||
}
|
||||
|
||||
TEST_F(QueryParserTest, Match) {
|
||||
@ -197,6 +209,11 @@ TEST_F(QueryParserTest, Complete) {
|
||||
EXPECT_EQ("utput ", Comps[0].TypedText);
|
||||
EXPECT_EQ("output", Comps[0].DisplayText);
|
||||
|
||||
Comps = QueryParser::complete("set t", 5, QS);
|
||||
ASSERT_EQ(1u, Comps.size());
|
||||
EXPECT_EQ("raversal ", Comps[0].TypedText);
|
||||
EXPECT_EQ("traversal", Comps[0].DisplayText);
|
||||
|
||||
Comps = QueryParser::complete("enable ", 7, QS);
|
||||
ASSERT_EQ(1u, Comps.size());
|
||||
EXPECT_EQ("output ", Comps[0].TypedText);
|
||||
@ -214,6 +231,16 @@ TEST_F(QueryParserTest, Complete) {
|
||||
EXPECT_EQ("dump ", Comps[3].TypedText);
|
||||
EXPECT_EQ("dump", Comps[3].DisplayText);
|
||||
|
||||
Comps = QueryParser::complete("set traversal ", 14, QS);
|
||||
ASSERT_EQ(3u, Comps.size());
|
||||
|
||||
EXPECT_EQ("AsIs ", Comps[0].TypedText);
|
||||
EXPECT_EQ("AsIs", Comps[0].DisplayText);
|
||||
EXPECT_EQ("IgnoreImplicitCastsAndParentheses ", Comps[1].TypedText);
|
||||
EXPECT_EQ("IgnoreImplicitCastsAndParentheses", Comps[1].DisplayText);
|
||||
EXPECT_EQ("IgnoreUnlessSpelledInSource ", Comps[2].TypedText);
|
||||
EXPECT_EQ("IgnoreUnlessSpelledInSource", Comps[2].DisplayText);
|
||||
|
||||
Comps = QueryParser::complete("match while", 11, QS);
|
||||
ASSERT_EQ(1u, Comps.size());
|
||||
EXPECT_EQ("Stmt(", Comps[0].TypedText);
|
||||
|
Loading…
x
Reference in New Issue
Block a user