Skip to content

Selecting by node kind

(:kind) is an escape hatch for power users who need to match constructs that SYNG doesn't have dedicated selectors for. It selects nodes by their underlying TreeSitter node kind and has the following signature:

clojure
(:kind [pattern])

When to use it

Most of the time, you should prefer SYNG's dedicated selectors like (call), (fun), or (id). These are designed to be portable across languages and express intent clearly.

However, there are cases where you need to match something SYNG doesn't cover yet, or you're debugging and want to understand what node kinds exist in a particular piece of code. That's where (:kind) comes in.

Matching specific node kinds

To find all identifier nodes in Python:

clojure
(:kind "identifier")
python
x = foo()
# matches: x, foo

Or to find all function definitions:

clojure
(:kind "function_definition")
python
def greet():
    pass
# matches the entire function definition

Using patterns

Like other selectors, (:kind) accepts regex patterns. To find any statement node:

clojure
(:kind /.*_statement/)
python
x = 1
if True:
    pass
# matches: expression_statement, if_statement, pass_statement

Composing with other selectors

(:kind) can be combined with other selectors using logical operators. For example, to find calls that are specifically call nodes (as opposed to other expression types):

clojure
(:and (call) (:kind "call"))

Or to find identifiers that appear in assignment targets:

clojure
(:and (:kind "identifier") (:text /x/))

Finding available node kinds

Node kinds are specific to each language's TreeSitter grammar. To discover what kinds exist for a given piece of code, you can use a broad pattern:

clojure
(:kind /.*/)

This will match every node, allowing you to inspect their kinds.

Copyright © 2022-present Semantic Works, Inc.