From d742484e4d7351c57479e9437ffbacd05b1934a1 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Tue, 14 Jan 2025 23:32:48 -0800 Subject: [PATCH] Add treesit-query-first-valid This should help major modes to support grammar versions. * doc/lispref/parsing.texi (Pattern Matching): Mention new function. * lisp/treesit.el (treesit-query-first-valid): New function. (treesit-query-valid-p): New function. (cherry picked from commit 814b45775ffcfa91c03fb54b78611eb97973c387) --- doc/lispref/parsing.texi | 39 ++++++++++++++++++++++++++------------- lisp/treesit.el | 19 +++++++++++++++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index ba7fbca2de9..f69dbfece6a 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -1539,22 +1539,35 @@ the specific error. You can use @code{treesit-query-validate} to validate and debug the query. @end defun -@defun treesit-query-language query -This function returns the language of @var{query}. -@end defun +@findex treesit-query-language +@findex treesit-query-expand +@findex treesit-pattern-expand +@findex treesit-query-valid-p +There are some additional functions for queries: +@code{treesit-query-language} returns the language of a query; +@code{treesit-query-valid-p} checks whether a query is valid; +@code{treesit-query-expand} converts a s-expression query into the +string format; and @code{treesit-pattern-expand} converts a pattern. + +@findex treesit-query-first-valid +Tree-sitter grammars change overtime. To support multiple possible +versions of a grammar, a Lisp program can use +@code{treesit-query-first-valid} to pick the right query to use. For +example, if a grammar has a @code{(defun)} node in one version, and +later renamed it to @code{(function_definition)}, a Lisp program can use -@defun treesit-query-expand query -This function converts the s-expression @var{query} into the string -format. -@end defun +@example +@group +(treesit-query-first-valid 'lang + '((defun) @defun) + '((function_definition) @defun)) +@end group +@end example -@defun treesit-pattern-expand pattern -This function converts the s-expression @var{pattern} into the string -format. -@end defun +to support both versions of the grammar. -For more details, read the tree-sitter project's documentation about -pattern-matching, which can be found at +For more details, consider reading the tree-sitter project's +documentation about pattern-matching. The documentation can be found at @uref{https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries}. @node User-defined Things diff --git a/lisp/treesit.el b/lisp/treesit.el index 6c0f119dc5d..ff5fa6317ff 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -505,6 +505,23 @@ that starts with an underscore are ignored." collect (cons (+ (treesit-node-start node) offset-left) (+ (treesit-node-end node) offset-right))))) +(defun treesit-query-valid-p (language query) + "Return non-nil if QUERY is valid in LANGUAGE, nil otherwise." + (ignore-errors + (treesit-query-compile language query t) + t)) + +(defun treesit-query-first-valid (language &rest queries) + "Return the first query in QUERIES that is valid in LANGUAGE. +If none are valid, return nil." + (declare (indent 1)) + (let (query) + (catch 'valid + (while (setq query (pop queries)) + (ignore-errors + (treesit-query-compile language query t) + (throw 'valid query)))))) + ;;; Range API supplement (defvar-local treesit-range-settings nil @@ -4627,6 +4644,8 @@ If anything goes wrong, this function signals an `treesit-error'." (treesit-query-language :no-eval (treesit-query-language compiled-query) :eg-result c) + (treesit-query-valid-p) + (treesit-query-first-valid) (treesit-query-expand :eval (treesit-query-expand '((identifier) @id "return" @ret))) (treesit-pattern-expand -- 2.39.5