From 4a5b01ddd7dd12f9a5826741e57104e8bf54748b Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 20 Oct 2018 09:13:59 +0000 Subject: [PATCH] [clang-query] Add option to print matcher expression Summary: This is useful if using clang-query -f with a file containing multiple matchers. Reviewers: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D52859 llvm-svn: 344840 --- clang-tools-extra/clang-query/Query.cpp | 8 +++++++ clang-tools-extra/clang-query/Query.h | 7 ++++-- clang-tools-extra/clang-query/QueryParser.cpp | 26 +++++++++++++++------- clang-tools-extra/clang-query/QuerySession.h | 4 +++- .../unittests/clang-query/QueryEngineTest.cpp | 14 +++++++----- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index 63b4f35..463e52c 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -41,6 +41,8 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { "as part of other expressions.\n" " set bind-root (true|false) " "Set whether to bind the root matcher to \"root\".\n" + " set print-matcher (true|false) " + "Set whether to print the current matcher,\n" " set output (diag|print|dump) " "Set whether to print bindings as diagnostics,\n" " " @@ -86,6 +88,12 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { } Finder.matchAST(AST->getASTContext()); + if (QS.PrintMatcher) { + std::string prefixText = "Matcher: "; + OS << "\n " << prefixText << Source << "\n"; + OS << " " << std::string(prefixText.size() + Source.size(), '=') << '\n'; + } + for (auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) { OS << "\nMatch #" << ++MatchCount << ":\n\n"; diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index b8c59cb..7771139 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -83,12 +83,15 @@ struct QuitQuery : Query { /// Query for "match MATCHER". struct MatchQuery : Query { - MatchQuery(const ast_matchers::dynamic::DynTypedMatcher &Matcher) - : Query(QK_Match), Matcher(Matcher) {} + MatchQuery(StringRef Source, + const ast_matchers::dynamic::DynTypedMatcher &Matcher) + : Query(QK_Match), Matcher(Matcher), Source(Source) {} bool run(llvm::raw_ostream &OS, QuerySession &QS) const override; ast_matchers::dynamic::DynTypedMatcher Matcher; + StringRef Source; + static bool classof(const Query *Q) { return Q->Kind == QK_Match; } }; diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 55504f7..e7312d8 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -142,7 +142,12 @@ enum ParsedQueryKind { PQK_Quit }; -enum ParsedQueryVariable { PQV_Invalid, PQV_Output, PQV_BindRoot }; +enum ParsedQueryVariable { + PQV_Invalid, + PQV_Output, + PQV_BindRoot, + PQV_PrintMatcher +}; QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) { std::string ErrStr; @@ -214,21 +219,23 @@ QueryRef QueryParser::doParse() { return completeMatcherExpression(); Diagnostics Diag; + auto MatcherSource = StringRef(Begin, End - Begin).trim(); Optional Matcher = Parser::parseMatcherExpression( - StringRef(Begin, End - Begin), nullptr, &QS.NamedValues, &Diag); + MatcherSource, nullptr, &QS.NamedValues, &Diag); if (!Matcher) { return makeInvalidQueryFromDiagnostics(Diag); } - return new MatchQuery(*Matcher); + return new MatchQuery(MatcherSource, *Matcher); } case PQK_Set: { StringRef VarStr; - ParsedQueryVariable Var = LexOrCompleteWord(this, - VarStr) - .Case("output", PQV_Output) - .Case("bind-root", PQV_BindRoot) - .Default(PQV_Invalid); + ParsedQueryVariable Var = + LexOrCompleteWord(this, VarStr) + .Case("output", PQV_Output) + .Case("bind-root", PQV_BindRoot) + .Case("print-matcher", PQV_PrintMatcher) + .Default(PQV_Invalid); if (VarStr.empty()) return new InvalidQuery("expected variable name"); if (Var == PQV_Invalid) @@ -242,6 +249,9 @@ QueryRef QueryParser::doParse() { case PQV_BindRoot: Q = parseSetBool(&QuerySession::BindRoot); break; + case PQV_PrintMatcher: + Q = parseSetBool(&QuerySession::PrintMatcher); + break; case PQV_Invalid: llvm_unreachable("Invalid query kind"); } diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h index 162289f..a211aa0 100644 --- a/clang-tools-extra/clang-query/QuerySession.h +++ b/clang-tools-extra/clang-query/QuerySession.h @@ -25,11 +25,13 @@ namespace query { class QuerySession { public: QuerySession(llvm::ArrayRef> ASTs) - : ASTs(ASTs), OutKind(OK_Diag), BindRoot(true), Terminate(false) {} + : ASTs(ASTs), OutKind(OK_Diag), BindRoot(true), PrintMatcher(false), + Terminate(false) {} llvm::ArrayRef> ASTs; OutputKind OutKind; bool BindRoot; + bool PrintMatcher; bool Terminate; llvm::StringMap NamedValues; }; diff --git a/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp b/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp index f95d315..74fd6d1 100644 --- a/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryEngineTest.cpp @@ -52,6 +52,8 @@ TEST_F(QueryEngineTest, Basic) { DynTypedMatcher FnMatcher = functionDecl(); DynTypedMatcher FooMatcher = functionDecl(hasName("foo1")); + std::string FooMatcherString = "functionDecl(hasName(\"foo1\"))"; + EXPECT_TRUE(NoOpQuery().run(OS, S)); EXPECT_EQ("", OS.str()); @@ -70,7 +72,7 @@ TEST_F(QueryEngineTest, Basic) { Str.clear(); - EXPECT_TRUE(MatchQuery(FnMatcher).run(OS, S)); + EXPECT_TRUE(MatchQuery("functionDecl()", FnMatcher).run(OS, S)); EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") != std::string::npos); @@ -84,7 +86,7 @@ TEST_F(QueryEngineTest, Basic) { Str.clear(); - EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); + EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S)); EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") != std::string::npos); @@ -94,7 +96,7 @@ TEST_F(QueryEngineTest, Basic) { EXPECT_TRUE( SetQuery(&QuerySession::OutKind, OK_Print).run(OS, S)); - EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); + EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S)); EXPECT_TRUE(OS.str().find("Binding for \"root\":\nvoid foo1()") != std::string::npos); @@ -102,20 +104,20 @@ TEST_F(QueryEngineTest, Basic) { Str.clear(); EXPECT_TRUE(SetQuery(&QuerySession::OutKind, OK_Dump).run(OS, S)); - EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); + EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S)); EXPECT_TRUE(OS.str().find("FunctionDecl") != std::string::npos); Str.clear(); EXPECT_TRUE(SetQuery(&QuerySession::BindRoot, false).run(OS, S)); - EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); + EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S)); EXPECT_TRUE(OS.str().find("No bindings.") != std::string::npos); Str.clear(); - EXPECT_FALSE(MatchQuery(isMain()).run(OS, S)); + EXPECT_FALSE(MatchQuery("isMain()", isMain()).run(OS, S)); EXPECT_EQ("Not a valid top-level matcher.\n", OS.str()); } -- 2.7.4