ESQuery Style Kind
ast-grep supports limited ESQuery style selector in the kind rule.
The selector is still written in the kind field. ast-grep will parse the selector and convert it to the corresponding rule object internally.
rule:
kind: call_expression > identifierThe example above will match the identifier node that is a direct child of call_expression.
Basic Selector
A single node kind is the same as a normal kind rule.
kind: identifieris equivalent to
kind: identifierRelationship Selectors
Child Selector
The > selector matches a direct child node.
kind: call_expression > identifieris equivalent to
kind: identifier
inside:
kind: call_expressionDescendant Selector
A space selector matches a descendant node.
kind: call_expression identifieris equivalent to
kind: identifier
inside:
kind: call_expression
stopBy: endAdjacent Sibling Selector
The + selector matches the next sibling node.
kind: decorator + method_definitionis equivalent to
kind: method_definition
follows:
kind: decoratorFollowing Sibling Selector
The ~ selector matches a following sibling node.
kind: decorator ~ method_definitionis equivalent to
kind: method_definition
follows:
kind: decorator
stopBy: endComma Selector
Comma separated selectors are converted to any.
kind: identifier, numberis equivalent to
any:
- kind: identifier
- kind: numberPseudo-classes
:has
:has matches a node if the node has a descendant matching the inner selector.
kind: function_declaration:has(return_statement)is equivalent to
kind: function_declaration
has:
kind: return_statement
stopBy: endYou can use > in :has to match a direct child.
kind: expression_statement:has(> call_expression)is equivalent to
kind: expression_statement
has:
kind: call_expression:not
:not negates the inner selector.
kind: identifier:not(number)is equivalent to
kind: identifier
not:
kind: number:is
:is accepts comma separated selectors and is converted to any.
kind: :is(identifier, number)is equivalent to
any:
- kind: identifier
- kind: numberIt can be combined with relationship selectors.
kind: call_expression > :is(identifier, number)is equivalent to
all:
- any:
- kind: identifier
- kind: number
- inside:
kind: call_expression:nth-child
:nth-child maps to ast-grep's nthChild rule.
kind: array > number:nth-child(2n+1)is equivalent to
all:
- kind: number
- nthChild: 2n+1
- inside:
kind: array:nth-child also supports of syntax.
kind: array > :nth-child(1 of number)is equivalent to
all:
- nthChild:
position: 1
ofRule:
kind: number
- inside:
kind: arraykind: array > :nth-child(2n+1 of number)is equivalent to
all:
- nthChild:
position: 2n+1
ofRule:
kind: number
- inside:
kind: array:nth-last-child
:nth-last-child is equivalent to nthChild with reverse: true.
kind: array > number:nth-last-child(1)is equivalent to
all:
- kind: number
- nthChild:
position: 1
reverse: true
- inside:
kind: arrayCompound Selector
Compound selectors are combined with all.
kind: function_declaration:has(return_statement):not(generator_function)is equivalent to
all:
- kind: function_declaration
- has:
kind: return_statement
stopBy: end
- not:
kind: generator_functionCurrent Limitations
The ESQuery style kind only supports part of ESQuery syntax:
- Class selectors like
.bodyare tokenized but rejected as unsupported. - Supported pseudo-classes are only
has,not,is,nth-childandnth-last-child. :has(...),:not(...)andof ...parse a single complex selector, not a comma selector list.:is(...)is the one pseudo-class that accepts comma separated selector lists.- Identifiers can include letters, digits,
_and-, but cannot start with a digit.