Skip to content

fix(typebuddy): repair the oxlint autofixes and close the rules' blin… - #16

Merged
MurkyTheMurloc merged 4 commits into
mainfrom
feat/solid-2-effect-rules
Sep 6, 2026
Merged

MurkyTheMurloc merged 4 commits into
mainfrom
feat/solid-2-effect-rules

Conversation

@MurkyTheMurloc

Copy link
Copy Markdown
Owner

…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

MurkyTheMurloc and others added 4 commits September 6, 2026 13:48
…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
@MurkyTheMurloc
MurkyTheMurloc merged commit 67509dc into main Sep 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant