Repository navigation
fix(validate): notice has/inside without stopBy, like follows/precedes - #691
Conversation
|
@claude /review |
|
Claude finished @theCodeDrift's task in 3m 25s —— View job Review: fix/validate-has-inside-stopbyReview mode: incremental — read 0 prior review thread(s) before reviewing.
AssessmentNo correctness, security, or test-adequacy issues found. This is a clean, well-scoped PR.
One trivial wording nit, not worth blocking on: No inline comments filed — nothing rose to the level of a concrete, actionable issue. |
9a365c1 to
e83a113
Compare
Took the wording nit: — AI Coding Agent |
236cf91 to
8b228d8
Compare
`has` and `inside` default to `stopBy: neighbor`, so `has` checks only
direct children and `inside` only the direct parent. An exclusion such
as `not: { inside: { kind: try_statement } }` silently stops excluding
anything nested deeper, and a fixture written from the same assumption
passes. findSgTraps already noticed this shape for `follows`/`precedes`
but not for these two.
descentTraps now emits a notice for each `has`/`inside` that declares no
`stopBy`, saying which level it checks and, under a `not`, that the
exclusion misses anything deeper. A relation that names a `field` is
left alone, since a field already pins one parent-child link, and
`stopBy: neighbor` silences the notice where one level is meant.
The create-sg-rule recipe gets a Quirks row and section (pinned by new
vendor-contract cases), its await_expression workarounds now say
`stopBy: neighbor`, and the repo's own prefer-node-process rule states
its five deliberate direct-child relations the same way. The standing
cli-rule-validation spec lists the new trap with a scenario.
Closes #676
8b228d8 to
2c7029c
Compare
Rebasing onto main brought in text from #682, #683, #686 and #691 that pushed three outputs past 8 KiB: - create-sg-rule outline: the `taskless ast` guidance moves to an on-demand Reading kinds section, step 4 points at it, and step 5 drops its quirk enumeration (the Quirks table lists them). - create-sg-rule pattern-quirks: the relational entries (follows/precedes, has/inside, not) move to a Relational quirks section; validate-rule names it beside the other two. - route outline: #686's note on recipes that limit questions moves to an on-demand Limits on asking section, with a one-line pointer in Preconditions.
Rebasing onto main brought in text from #682, #683, #686 and #691 that pushed three outputs past 8 KiB: - create-sg-rule outline: the `taskless ast` guidance moves to an on-demand Reading kinds section, step 4 points at it, and step 5 drops its quirk enumeration (the Quirks table lists them). - create-sg-rule pattern-quirks: the relational entries (follows/precedes, has/inside, not) move to a Relational quirks section; validate-rule names it beside the other two. - route outline: #686's note on recipes that limit questions moves to an on-demand Limits on asking section, with a one-line pointer in Preconditions.
Stack (root → tip):
Stacked on #682.
Problem
hasandinsidedefault tostopBy: neighbor:haschecks only direct children andinsideonly the direct parent. An exclusion such asnot: { inside: { kind: try_statement } }silently stops excluding anything nested deeper, and a fixture written from the same assumption passes.findSgTrapsnoticed this forfollows/precedesbut not forhas/inside.Change
findSgTraps(packages/cli/src/rules/sg-traps.ts) getsdescentTraps: a notice for eachhas/insidewith nostopBy, naming the relation, the one level it checks, andstopBy: end. Under anot, the notice says the exclusion misses anything deeper. Still a notice, never an error.fieldis left alone, since a field already pins one parent-child link (this keeps the recipe'shas: { field: function, ... }idioms quiet).stopBy: neighborsilences the notice where one level is meant.create-sg-rule: a Quirks table row and section besidefollows/precedes, the step 5 checklist mentionshas/inside, and theawait_expressionworkarounds now saystopBy: neighborso the recipe's own fix draws no notice.insidemisses atrytwo levels up;hasmisses a grandchild; both fixed bystopBy: end).prefer-node-processrule drew five notices for deliberate direct-child relations; they now saystopBy: neighbor(no behavior change,verifypasses).cli-rule-validationlists the new trap with a scenario..changeset/sg-regex-needs-kind-schema.mdfrom fix(validate): state sg-regex-needs-kind in the ast-grep rule schema #682 (one changeset per stack).Closes #676
Built on top of #682
Closes #671
What changed
astGrepRuleJsonSchema(insrc/schemas/ast-grep-rule.ts) layersif: {required: [regex]}, then: {$ref: TasklessPinsKind}onto both rule definitions in ast-grep's vendored schema (SerializableRule,Relation). The generated file is untouched, so upgrades keep working, and the layering throws if a vendor bump renames either definition.getSchemaPayload()now returns the augmented schema.TasklessPinsKind): a siblingkind; a siblinganywhose every branch pins a kind (recursively); or anallwith at least one branch that pins one. Akindinsidenotor a relation does not count.z.fromJSONSchemathrows onif/then, soastGrepRuleSchemaadds a check that walks the data against the same JSON Schema. That gives the same paths by construction, including positions the old walker missed (stopBy,nthChild.ofRule, utility arguments,fix.expandStart/expandEnd, rewriters). It is built withwhen: () => truebecause a plain.superRefineis skipped when another field already failed. Issues carryparams.constraintId, sovalidateattributessg-regex-needs-kindfrom the schema layer. The old Layer 2 walker is gone.anyoption, and how to find the kind (--debug-query=ast, and what a constraint's metavariable captures).create-sg-rulerecipe (topic v15) say "everyregex, at any depth". There is a new Quirks row and section, andassets/reference.jsonis regenerated.Tests
test/ast-grep-rule-schema.test.ts:constraints,utils,not, nestedhas/inside,precedes/follows,any/allitems, the rarer positions, and the sibling-anycases (accepted; refused with an unpinned or empty branch). Alsoall, nested pins, zod attribution, the issue still being reported alongside an unrelated schema failure, and the JSON Schema augmentation leaving everything else in the upstream schema unchanged.regexis an engine config error, a bare regex in a sub-rule runs, the sibling-anyconstraint example works, and$OBJ.$M()captures aproperty_identifier.findRegexWithoutKindexactly. Ajv is not added as a dependency.Notes for review
$schemacomment and no package export). The schema now states the pairing, but how an editor picks it up is a separate decision.