Tree-sitter query syntax
We use the tree-sitter query language to define our parse tree patterns. In addition to the official tree-sitter query documentation, we support a couple of additional features.
Relationships
In addition to the node corresponding to the scope itself (which we call its content range), you can tag different aspects / relationships of the scope. Assuming the internal identifier of our scope is foo, we can tag the following aspects of the scope:
@foo.domainindicates the domain of the scope. For example, you could use@collectionKey.domainto indicate that the domain of a key is the containing item, which would allow you to say"take key"from within the value of a key-value pair to select the key.@foo.leadingand@foo.trailingindicate the leading and trailing delimiters of the scope. For example, you could use@collectionKey.trailingto include all the way up to the start of the value as the trailing delimiter, so that"chuck key"will leave just the value.@foo.removalto indicate the removal range of the scope. Note that it is preferred to use@foo.leadingor@foo.trailinginstead of@foo.removalin situations where you just need to include a leading or trailing delimiter in the removal range.@foo.interiorto indicate the interior of the scope, used for"inside". For example, you could use@namedFunction.interiorto indicate the interior of a function, which would usually be the function body itself, without any leading or trailing delimiters.@foo.iterationto indicate the iteration scope of the scope. For example, you could use@namedFunction.iterationto indicate that the iteration scope for functions is a class. Note that unlike the other aspects, the iteration scope is not a part of the scope itself, but rather a separate scope that is used to determine the iteration scope of the given scope. Thus, it should nearly always appear in a separate pattern from the scope itself, unlike the other aspects, which must appear in the same pattern as the scope itself.
Inline operators
In addition to the above aspects, you can also use the following inline operators to modify the scope:
@foo.startand@foo.endto construct the scope using a range between two nodes (inclusive).@foo.startOfand@foo.endOfto refer to the start and end positions of a node. For example, you could use@foo.start.endOfto indicate that the scope should start at the end of the node.
Query predicate operators
We also support a number of query predicate operators for modifying the scope. See queryPredicateOperators.ts for a list of available operators.