[clang-tools-extra] [clang-query] Load queries and matchers from file during REPL cycle (PR #90603)
@@ -281,5 +282,26 @@ const QueryKind SetQueryKind::value; const QueryKind SetQueryKind::value; #endif +bool FileQuery::run(llvm::raw_ostream , QuerySession ) const { + auto Buffer = llvm::MemoryBuffer::getFile(StringRef{File}.trim()); + if (!Buffer) { +if (Prefix.has_value()) + llvm::errs() << *Prefix << ": "; +llvm::errs() << "cannot open " << File << ": " + << Buffer.getError().message() << "\n"; cwarner-8702 wrote: Got any tips on using `TextDiagnostic`? I am struggling to figure out what to pass as the `LangOptions` and `DiagnosticOptions` considering the error isn't coming from code per-se (getting the `ASTContext` from one of the `ASTUnit` objects and the options from it seems too hacky) https://github.com/llvm/llvm-project/pull/90603 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-query] Load queries and matchers from file during REPL cycle (PR #90603)
https://github.com/cwarner-8702 updated https://github.com/llvm/llvm-project/pull/90603 >From 9b1fe59633b5404281b5b9fd754b8a81fae411d0 Mon Sep 17 00:00:00 2001 From: Chris Warner Date: Tue, 23 Apr 2024 10:48:44 -0700 Subject: [PATCH 1/4] Load queries and matchers from file during REPL cycle The clang-query tool has the ability to execute or pre-load queries from a file when the tool is started, but doesn't have the ability to do the same from the interactive REPL prompt. Because the prompt also doesn't seem to allow multi-line matchers, this can make prototyping and iterating on more complicated matchers difficult. Supporting a dynamic load at REPL time allows the cost of reading the compilation database and building the AST to be imposed just once, and allows faster prototyping. --- clang-tools-extra/clang-query/Query.cpp | 22 +++ clang-tools-extra/clang-query/Query.h | 18 ++- clang-tools-extra/clang-query/QueryParser.cpp | 10 +++-- .../clang-query/tool/ClangQuery.cpp | 18 ++- .../test/clang-query/Inputs/file.script | 1 + .../clang-query/Inputs/runtime_file.script| 1 + .../test/clang-query/file-query.c | 11 ++ .../unittests/clang-query/QueryParserTest.cpp | 4 +++- 8 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 clang-tools-extra/test/clang-query/Inputs/file.script create mode 100644 clang-tools-extra/test/clang-query/Inputs/runtime_file.script create mode 100644 clang-tools-extra/test/clang-query/file-query.c diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index c436d6fa94986..9d5807a52fa8e 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -7,6 +7,7 @@ //===--===// #include "Query.h" +#include "QueryParser.h" #include "QuerySession.h" #include "clang/AST/ASTDumper.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -281,5 +282,26 @@ const QueryKind SetQueryKind::value; const QueryKind SetQueryKind::value; #endif +bool FileQuery::run(llvm::raw_ostream , QuerySession ) const { + auto Buffer = llvm::MemoryBuffer::getFile(StringRef{File}.trim()); + if (!Buffer) { +if (Prefix.has_value()) + llvm::errs() << *Prefix << ": "; +llvm::errs() << "cannot open " << File << ": " + << Buffer.getError().message() << "\n"; +return false; + } + + StringRef FileContentRef(Buffer.get()->getBuffer()); + + while (!FileContentRef.empty()) { +QueryRef Q = QueryParser::parse(FileContentRef, QS); +if (!Q->run(llvm::outs(), QS)) + return false; +FileContentRef = Q->RemainingContent; + } + return true; +} + } // namespace query } // namespace clang diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 7aefa6bb5ee0d..7242479633c24 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -30,7 +30,8 @@ enum QueryKind { QK_SetTraversalKind, QK_EnableOutputKind, QK_DisableOutputKind, - QK_Quit + QK_Quit, + QK_File }; class QuerySession; @@ -188,6 +189,21 @@ struct DisableOutputQuery : SetNonExclusiveOutputQuery { } }; +struct FileQuery : Query { + FileQuery(StringRef File, StringRef Prefix = StringRef()) + : Query(QK_File), File(File), +Prefix(!Prefix.empty() ? std::optional(Prefix) + : std::nullopt) {} + + bool run(llvm::raw_ostream , QuerySession ) const override; + + static bool classof(const Query *Q) { return Q->Kind == QK_File; } + +private: + std::string File; + std::optional Prefix; +}; + } // namespace query } // namespace clang diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 162acc1a598dd..85a442bdd7ded 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -183,7 +183,8 @@ enum ParsedQueryKind { PQK_Unlet, PQK_Quit, PQK_Enable, - PQK_Disable + PQK_Disable, + PQK_File }; enum ParsedQueryVariable { @@ -222,12 +223,14 @@ QueryRef QueryParser::doParse() { .Case("let", PQK_Let) .Case("m", PQK_Match, /*IsCompletion=*/false) .Case("match", PQK_Match) - .Case("q", PQK_Quit, /*IsCompletion=*/false) + .Case("q", PQK_Quit, /*IsCompletion=*/false) .Case("quit", PQK_Quit) .Case("set", PQK_Set) .Case("enable", PQK_Enable) .Case("disable", PQK_Disable) .Case("unlet", PQK_Unlet) + .Case("f", PQK_File, /*IsCompletion=*/false) +
[clang-tools-extra] [clang-query] Load queries and matchers from file during REPL cycle (PR #90603)
https://github.com/cwarner-8702 created https://github.com/llvm/llvm-project/pull/90603 The clang-query tool has the ability to execute or pre-load queries from a file when the tool is launched, but doesn't have the ability to do the same from the interactive REPL prompt. Because the prompt also doesn't seem to allow multi-line matchers, this can make prototyping and iterating on more complicated matchers difficult. Supporting a dynamic load at REPL time allows the cost of reading the compilation database and building the AST to be imposed just once, and allows faster prototyping. cc: @AaronBallman >From 9b1fe59633b5404281b5b9fd754b8a81fae411d0 Mon Sep 17 00:00:00 2001 From: Chris Warner Date: Tue, 23 Apr 2024 10:48:44 -0700 Subject: [PATCH] Load queries and matchers from file during REPL cycle The clang-query tool has the ability to execute or pre-load queries from a file when the tool is started, but doesn't have the ability to do the same from the interactive REPL prompt. Because the prompt also doesn't seem to allow multi-line matchers, this can make prototyping and iterating on more complicated matchers difficult. Supporting a dynamic load at REPL time allows the cost of reading the compilation database and building the AST to be imposed just once, and allows faster prototyping. --- clang-tools-extra/clang-query/Query.cpp | 22 +++ clang-tools-extra/clang-query/Query.h | 18 ++- clang-tools-extra/clang-query/QueryParser.cpp | 10 +++-- .../clang-query/tool/ClangQuery.cpp | 18 ++- .../test/clang-query/Inputs/file.script | 1 + .../clang-query/Inputs/runtime_file.script| 1 + .../test/clang-query/file-query.c | 11 ++ .../unittests/clang-query/QueryParserTest.cpp | 4 +++- 8 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 clang-tools-extra/test/clang-query/Inputs/file.script create mode 100644 clang-tools-extra/test/clang-query/Inputs/runtime_file.script create mode 100644 clang-tools-extra/test/clang-query/file-query.c diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index c436d6fa949868..9d5807a52fa8ed 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -7,6 +7,7 @@ //===--===// #include "Query.h" +#include "QueryParser.h" #include "QuerySession.h" #include "clang/AST/ASTDumper.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -281,5 +282,26 @@ const QueryKind SetQueryKind::value; const QueryKind SetQueryKind::value; #endif +bool FileQuery::run(llvm::raw_ostream , QuerySession ) const { + auto Buffer = llvm::MemoryBuffer::getFile(StringRef{File}.trim()); + if (!Buffer) { +if (Prefix.has_value()) + llvm::errs() << *Prefix << ": "; +llvm::errs() << "cannot open " << File << ": " + << Buffer.getError().message() << "\n"; +return false; + } + + StringRef FileContentRef(Buffer.get()->getBuffer()); + + while (!FileContentRef.empty()) { +QueryRef Q = QueryParser::parse(FileContentRef, QS); +if (!Q->run(llvm::outs(), QS)) + return false; +FileContentRef = Q->RemainingContent; + } + return true; +} + } // namespace query } // namespace clang diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 7aefa6bb5ee0dd..7242479633c24f 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -30,7 +30,8 @@ enum QueryKind { QK_SetTraversalKind, QK_EnableOutputKind, QK_DisableOutputKind, - QK_Quit + QK_Quit, + QK_File }; class QuerySession; @@ -188,6 +189,21 @@ struct DisableOutputQuery : SetNonExclusiveOutputQuery { } }; +struct FileQuery : Query { + FileQuery(StringRef File, StringRef Prefix = StringRef()) + : Query(QK_File), File(File), +Prefix(!Prefix.empty() ? std::optional(Prefix) + : std::nullopt) {} + + bool run(llvm::raw_ostream , QuerySession ) const override; + + static bool classof(const Query *Q) { return Q->Kind == QK_File; } + +private: + std::string File; + std::optional Prefix; +}; + } // namespace query } // namespace clang diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 162acc1a598dd5..85a442bdd7deda 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -183,7 +183,8 @@ enum ParsedQueryKind { PQK_Unlet, PQK_Quit, PQK_Enable, - PQK_Disable + PQK_Disable, + PQK_File }; enum ParsedQueryVariable { @@ -222,12 +223,14 @@ QueryRef QueryParser::doParse() { .Case("let", PQK_Let) .Case("m", PQK_Match, /*IsCompletion=*/false) .Case("match", PQK_Match)