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.
This commit is contained in:
Yuan Fu 2025-01-14 23:32:48 -08:00
parent d3a2ec5210
commit 814b45775f
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
2 changed files with 45 additions and 13 deletions

View file

@ -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.
@defun treesit-query-expand query
This function converts the s-expression @var{query} into the string
format.
@end defun
@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-pattern-expand pattern
This function converts the s-expression @var{pattern} into the string
format.
@end defun
@example
@group
(treesit-query-first-valid 'lang
'((defun) @defun)
'((function_definition) @defun))
@end group
@end example
For more details, read the tree-sitter project's documentation about
pattern-matching, which can be found at
to support both versions of the grammar.
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

View file

@ -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
@ -4636,6 +4653,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