Repository navigation
fix(remove-memoization): replace useMemo with the factory result, preserve untouched imports - #11
Conversation
… the factory
`useMemo(factory, deps)` evaluates to what the factory returns, but the
codemod replaced the call with the factory function itself, so every
memoized value became a function. Context providers received a function
instead of an object, `states.some(...)` threw on a function, and so on.
The `use-memo` fixtures encoded this: a boolean turned into `() => boolean`.
An expression-bodied arrow now becomes its body (parenthesised outside
declarators, arguments, returns, pairs, arrays and JSX expressions so
precedence survives); a block-bodied or async factory is invoked in place
as an IIFE; a bare identifier is called.
Import rewriting is also narrowed. An import that loses no specifier is
left untouched, which stops `import type { X } from 'react'` being
rewritten as a value import and stops a trailing semicolon being added to
semicolon-free files. Only the memoization specifiers themselves are
candidates for removal; unrelated unused React imports are no longer
deleted. A rewritten import keeps the file's semicolon style.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
thank you for your contributions @rjolaverria. will check this out soon |
Cover parenthesized factories, block bodies that only return an expression, and preserving an unused default React import while stripping useMemo. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Thanks for this fix — the core I pushed three additional fixtures that currently fail ( 1.
|
… factories - `useMemo((() => x), deps)` unwraps like a bare arrow - a block body that is only `return <expr>;` becomes that expression; blocks with other statements or comments, empty blocks and `function` factories are still invoked in place - sequence-expression results keep their parentheses - a default or namespace React import is only removed when the codemod removed its last uses; an already-unused one is left alone Adds fixtures for the paths mutation testing (Stryker) showed untested: blocks kept as IIFEs, sequence results, contexts where the result needs no parentheses, and removal of a default-only React import. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UzRWcG4VtigDwQdDeqTvhk
|
Thanks for the fixtures! All three pass now (f22bb65), plus a few more edge-case tests. Ready for another look whenever you have time. |
|
can you also resolve the conflicts? i recent made some improvements to the codemods by utilizing jssg utils... @rjolaverria |
Resolves the remove-memoization conflict with the @jssg/utils import refactor: keeps upstream's import helpers and ports this branch's useMemo result unwrapping onto them. - the unused-default-import rule moves into cleanupUnusedImports: a default or namespace import is only removed when the codemod removed its last uses - several memoization specifiers removed from one statement that keeps a sibling are cut in non-overlapping edits; per-name removeImport edits overlapped and left e.g. `useMemo` behind - corrects the new no-semicolon-keep-sibling fixture, which encoded the useMemo-becomes-a-function bug, and keeps multi-line import formatting in type-only-import-preserved - adds fixtures for multi-specifier removal and a kept default import Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UzRWcG4VtigDwQdDeqTvhk
|
/codex-review |
Codex ReviewReviewed all 46 changed files statically. Five correctness issues remain. No PR code or tests were executed. Findings
|
|
i'll take care of the comments above, push the fix, and merge the PR |
Address Codex review: keep parameterized factories as invocations, preserve return/generic types, invoke member factories unbound, convert nested memo calls inside-out, and remove unused import aliases by local binding. Add fixtures, update the README/changeset, and ignore local .pnpm-store caches. Co-authored-by: Cursor <cursoragent@cursor.com>
Fixes #10.
What changed
useMemois replaced by the factory's result, not the factory.useMemo(factory, deps)evaluates to what the factory returns, but the codemod substituted the factory function itself, so every memoized value became a function. Now:useMemo(() => ({ a }), [a])→{ a }. Outside declarators, arguments, returns, pairs, arrays, parentheses and JSX expressions the body is parenthesised so precedence survives:1 + useMemo(() => a * 2)→1 + (a * 2)asyncfactory is invoked in place:useMemo(() => { ... }, deps)→(() => { ... })()useMemo(compute, [compute])→compute()Import rewriting is narrowed.
import type { X } from 'react'becoming a value import and stops;being appended in semicolon-free filesFixtures
Six existing
expected.tsxfiles encoded theuseMemobug (a memoized boolean became() => boolean) and are corrected. Three new fixtures cover the expression-body forms, precedence wrapping,asyncand identifier factories, a type-only import beside a rewritten value import in a semicolon-free file, and an inlinetypespecifier surviving a rewrite.Verification
pnpm testincodemods/remove-memoization: 16 passedpnpm check-types: clean🤖 Generated with Claude Code