feat: generalize new-class advisory into config-driven advice block (#347)#349
Merged
Conversation
…#347) Replace the single-purpose `adviseForNewTest` bool with a top-level `advice` map of named rules. Each rule gates (all optional) on `hooks_into` (ops, default all mutating), `match` (path glob), `when` (new-file|existing-file| always), `contains` (regex over the content the op *added* — lines present after but not before), and `resolve`/`resolveFromValidator` (a subprocess emitting a would-be target via the exit-3 + stderr contract). `message` is the rendered line, with `{target}`/`{path}`/`{op}` interpolation. `resolveFromValidator` accepts a validator NAME (not just `true`) so a rule can reuse a specific validator's resolver — `true` grabs the first resolver declared, which in a multi-resolver config (DVSI: phpstan-component precedes phpunit) is the wrong one. BREAKING: `adviseForNewTest: true` removed — express as an `advice.newTest` rule. See `.supertool.example.json` and docs/validators.md. Closes #347 Co-Authored-By: Max <noreply>
…erpolation
- _advice_added_text: multiset (count-based) diff, not set membership — a line
the op duplicates now counts as added even when an identical line pre-existed.
- _advice_wants_pre + both call sites: snapshot pre-edit bytes whenever a
contains rule applies, so the added-content gate stays exact even when no
validator has rollback_on_fail and no notifier is configured (previously fell
back to whole-file matching → fired on content the op did not introduce).
- message render: interpolate {path}/{op} before inserting a resolver-produced
target, so target text can't be re-scanned for placeholders; strip the leading
space when the configured message is empty (no more 'ℹ — consider').
Adds tests for the multiset duplicate-line case and _advice_wants_pre gating.
Co-Authored-By: Max <noreply>
Contributor
Author
|
Addressed review in 0d601f1:
Tests added for the multiset case and |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
#347 asked for a hint when an
edit/pasteadds a component class or a public component attribute (XSD/cache regen reminder), gated behind a config flag like the existingadviseForNewTest. Rather than bolt on a second hardcoded advisory, this generalizes the mechanism:adviseForNewTest(a single-purpose bool) becomes a config-drivenadviceblock of named rules, so projects add nudges as data instead of code.What changed
adviceblock — top-level map of named rules. Each rule gates (all optional) on:hooks_into— ops that trigger it (default: all mutating)match— path globwhen—new-file|existing-file|alwayscontains— regex over the content the op added (lines after but not before), so it fires only when the op introduces the pattern, not when the file already held itresolve/resolveFromValidator— a subprocess emitting a would-be target via the exit-3 + stderr contractmessage—{target}/{path}/{op}interpolate; a{target}-less message gets— consider <target>appended when a resolver produced oneresolveFromValidatoraccepts a validator name, not justtrue.truegrabs the first validator declaring a resolver — in a multi-resolver config that's the wrong one (DVSI:phpstan-component's resolver precedesphpunit's, so the oldadviseForNewTestwas almost certainly resolving against the wrong script).pre_contentinto both_run_with_validatorscall sites socontainsmatches added-content.validators.md+configuration.md),.supertool.example.json, CHANGELOG.Breaking
adviseForNewTest: trueremoved. Express it as anadvice.newTestrule:Tests
Rewrote the advice test block for the new API: newTest parity (7), contains-on-added-content (3), when gate, default ops, multi-rule, interpolation, named-validator disambiguation, and a regression test asserting the
[advice]block uses real newlines (a literal-\nbug slipped past substring asserts and was caught in self-review). Full suite: 3479 passed.Closes #347
🤖 Generated by Max