[clang-tools-extra] [clang-query] Load queries and matchers from file during REPL cycle (PR #90603)

2024-05-09 Thread Chris Warner via cfe-commits


@@ -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)

2024-05-09 Thread Chris Warner via cfe-commits

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)

2024-04-30 Thread Chris Warner via cfe-commits

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)