fix(typebuddy): repair the oxlint autofixes and close the rules' blin… - #16
Merged
Merged
Conversation
…d spots Two fixes produced code that does not parse or that changes string values. `prefer-maybe-promise` inserted `return err()` directly before a catch block's closing brace; `require-try-catch` rebuilt the body line by line and stripped leading whitespace from every line, template literals included. Both now use zero-width insertions and leave the body byte for byte intact. The catch branch settles on `err()` and is no longer fed through the try block's code path, which used to produce two reports with opposite fixes for one return and append unreachable code. Returns that hand back a value are reported without a fix: rewriting them would drop the author's fallback. Nested returns, type-level `Promise` signatures, `MaybePromise`/`AsyncResult` annotations and expression-bodied async arrows were all invisible to the rules. The shared walk and the shared import insertion now live in `own_subtree.ts` and `typebuddy_import.ts` — both bugs existed twice because both helpers did. The fix smoke runs two fixtures now: one file with imports, one without, since the insertion behaves differently in each and only the second one caught the import bug. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CkmW7HzpL6zqpjuo1ETm2w
`solid/no-untracked-effect-read` reports a reactive read in the untracked apply phase of a two-argument `createEffect`. `reactivity` cannot report this: it marks the apply phase as a tracked scope, and its model has no state for "matches, but does not subscribe". `solid/no-owned-primitives-in-ref` reports owner-bound primitives inside a ref callback, which Solid 2.0 runs unowned — nothing disposes them. Directive factories keep working. `solid/no-setter-in-effect` also reports an async apply phase that awaits and writes the result back; its existing check requires every statement to be a setter call, which an `await` breaks. Two repairs: `prefer-class-object` matched only lowercase `classlist` and so missed every real `classList` call site, and `jsx-no-duplicate-props` recommended that same removed prop. `solid/imports` gained the three boundary primitives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CkmW7HzpL6zqpjuo1ETm2w
Neither gate existed. `packages/oxlint-plugin-solid` had no CI job at all, so its suite only ran through `release:verify`. `smoke:subpath` — the guard added with the subpath entry points, which checks that every `exports` target was actually emitted — was wired into neither CI nor `release:verify:typebuddy`. The push trigger also listened on `master` while the default branch is `main`, so it never fired; pull requests were the only thing running CI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CkmW7HzpL6zqpjuo1ETm2w
The plugin targets oxlint, but handed the whole TypeScript-ESLint toolchain to every consumer. Two things kept it there, and only one of them was real. `ESLintUtils.RuleCreator.withoutDocs` wrapped all 23 rules. It exists for TypeScript type inference, which a `.mjs` plugin gets nothing from: oxlint takes the rule object as-is, so the wrapper is gone and the rules are plain object literals now. `@oxlint/plugins` offers `defineRule` for the same purpose, but it is likewise a type helper — adopting it would trade one dependency for another and buy nothing until this package moves to TypeScript. The wrapper did do one thing at runtime: it merged `defaultOptions` into `context.options` and passed the result to a second `create` parameter. `reactivity` is the only rule that reads that parameter, and it now resolves its own default. Without this the rule threw on every file. The five real helpers — `findVariable`, `getStaticValue`, `getStringIfConstant`, `getPropertyName`, `getFunctionHeadLocation` — now come straight from `@eslint-community/eslint-utils`, which `@typescript-eslint/utils` was only re-exporting. That drops `@typescript-eslint/typescript-estree` and `@typescript-eslint/scope-manager` from the tree. Runtime dependencies go from 7 to 6, and the two heaviest are the ones removed. This does not change the advisory count: measured from an identical baseline, before and after are both 15 high / 32 moderate / 3 low, since the remaining findings come from vite, vitest, tsdown and changesets — workspace devDeps that are never published. The gain is what this package hands to its consumers, not the audit number. 45 pass, 0 fail. Every rule probe re-run against the doc-sanctioned patterns behaves exactly as before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CkmW7HzpL6zqpjuo1ETm2w
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.
…d spots
Two fixes produced code that does not parse or that changes string values.
prefer-maybe-promiseinsertedreturn err()directly before a catch block'sclosing brace;
require-try-catchrebuilt the body line by line and strippedleading whitespace from every line, template literals included. Both now use
zero-width insertions and leave the body byte for byte intact.
The catch branch settles on
err()and is no longer fed through the tryblock's code path, which used to produce two reports with opposite fixes for
one return and append unreachable code. Returns that hand back a value are
reported without a fix: rewriting them would drop the author's fallback.
Nested returns, type-level
Promisesignatures,MaybePromise/AsyncResultannotations and expression-bodied async arrows were all invisible to the rules.
The shared walk and the shared import insertion now live in
own_subtree.tsand
typebuddy_import.ts— both bugs existed twice because both helpers did.The fix smoke runs two fixtures now: one file with imports, one without, since
the insertion behaves differently in each and only the second one caught the
import bug.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01CkmW7HzpL6zqpjuo1ETm2w