What
findRegexWithoutKind (packages/cli/src/schemas/ast-grep-rule.ts) warns when a regex appears with no sibling kind. It recurses into the composite fields it knows about:
any, all, not, has, inside, precedes, follows
matches is not among them, and as of the 0.45.2 upgrade (#182) it can nest full rule objects. The vendored schema widened matches from type: string to SerializableMatches:
string | { [utilId]: { [param]: SerializableRule } }
So a regex without a sibling kind inside a parameterized matches call is not flagged:
rule:
matches:
my-util:
$A:
regex: "something" # not reported
The same gap exists for rewriters[].rule — verify.ts walks only rule, constraints and utils.
Severity
Low. The check is advisory: it warns that regex-without-kind is ambiguous and slow, and it does not block a rule from running. Parameterized matches is also an advanced, rarely used construct. Nothing is broken today; this is a hole in a lint, not a correctness bug.
Why it is not a one-line fix
Adding "matches" to the recursion list does not work. The loop recurses one level into each named key, which for matches lands on the { [utilId]: ... } map — not a rule. The actual rule sits one level further down, under the parameter name, and the loop does not descend into unnamed intermediate maps. A correct fix has to walk the two-level utilId → param → rule shape specifically, and should cover rewriters[].rule at the same time.
Context
Found during review of #182. Raised there and deliberately deferred rather than grown into that PR.
Refs #182
What
findRegexWithoutKind(packages/cli/src/schemas/ast-grep-rule.ts) warns when aregexappears with no siblingkind. It recurses into the composite fields it knows about:matchesis not among them, and as of the 0.45.2 upgrade (#182) it can nest full rule objects. The vendored schema widenedmatchesfromtype: stringtoSerializableMatches:So a
regexwithout a siblingkindinside a parameterizedmatchescall is not flagged:The same gap exists for
rewriters[].rule—verify.tswalks onlyrule,constraintsandutils.Severity
Low. The check is advisory: it warns that regex-without-kind is ambiguous and slow, and it does not block a rule from running. Parameterized
matchesis also an advanced, rarely used construct. Nothing is broken today; this is a hole in a lint, not a correctness bug.Why it is not a one-line fix
Adding
"matches"to the recursion list does not work. The loop recurses one level into each named key, which formatcheslands on the{ [utilId]: ... }map — not a rule. The actual rule sits one level further down, under the parameter name, and the loop does not descend into unnamed intermediate maps. A correct fix has to walk the two-levelutilId → param → ruleshape specifically, and should coverrewriters[].ruleat the same time.Context
Found during review of #182. Raised there and deliberately deferred rather than grown into that PR.
Refs #182