Tree-sitter provides a Lisp-like query language to search for patterns in the syntax tree.

tsc-make-query language patterns [tag-assigner]
Create a new query for the given language. This query cannot be run on syntax nodes of other languages.

Patterns can be specified as either a sequence (usually a vector, for convenience) of S-expressions, or their textual representations, concatenated into a string.

When the query is executed, each captured node is tagged with a symbol, whose name is the corresponding capture name defined in patterns. For example, nodes that are captured as @function.builtin will be tagged with the symbol function.builtin. This behavior can be customized by the optional function tag-assigner, which should return a tag value when given a capture name (without the prefix @). If it returns nil, the associated capture name is disabled.

Create a new query cursor to execute queries. It stores the state that is needed to iteratively search for matches.
tsc-query-captures query node text-function [query-cursor]
tsc-query-matches query node text-function [query-cursor]
Execute a query on the given syntax node. tsc-query-captures returns a sequence of captures, sorted in the order they appear in the source code. tsc-query-matches returns a sequence of matches, sorted in the order they were found.

Each capture has the form (capture-tag . captured-node), where capture-tag is a symbol, whose name is the corresponding capture name defined in query (without the prefix @). If query was created with a custom tag assigner, capture-tag is instead the value returned by that function.

Each match has the form (pattern-index . match-captures), where pattern-index is the 0-based position of the matched pattern within query, and match-captures is a sequence of captures associated with the match.

Since the syntax tree doesn’t store the source code’s text, text-function is called to get nodes' texts (for text-based predicates). It should take 2 parameters: (beg-byte end-byte), and return the corresponding chunk of text in the source code. Usually this should be #'ts--buffer-substring-no-properties.

For performance reason, query-cursor should typically be created once, and reused between query executions. It should be omitted only for one-off experimentation.