Skip to content

fix: eliminate false positives in v1.51.0 codemods#93

Merged
schultzp2020 merged 2 commits into
mainfrom
fix/codemod-false-positives
Jun 3, 2026
Merged

fix: eliminate false positives in v1.51.0 codemods#93
schultzp2020 merged 2 commits into
mainfrom
fix/codemod-false-positives

Conversation

@schultzp2020

Copy link
Copy Markdown
Contributor

What

Fixes false positives in two v1.51.0 codemods discovered by running the migration recipe against the Backstage monorepo with --target packages and --target plugins.

Changes

@backstage/experimental-form-decorators-to-stable

The AST rule matched property_identifier nodes at any depth inside a pair, which incorrectly renamed property accesses like template.spec.EXPERIMENTAL_formDecorators when they appeared inside a pair's value. This turned backward-compat fallback patterns (formDecorators ?? EXPERIMENTAL_formDecorators) into the redundant formDecorators ?? formDecorators.

Fix: Skip any property_identifier whose parent is a member_expression.

@backstage/migrate-policy-query-user

False positive scoping — The codemod processed ALL object patterns with token fields in any file importing from @backstage/plugin-permission-node, not just PolicyQueryUser-typed patterns. This caused incorrect modifications to unrelated destructuring ({ token, context } from req.body) and type aliases (AutocompleteHandler).

Fix: Added isPolicyQueryUserObjectPattern() guard — only process object patterns that are directly typed as PolicyQueryUser or destructure a tracked PolicyQueryUser binding.

Empty destructuring — When all fields were removed, const {} = await expr was left behind.

Fix: Detect empty {} result and simplify to await expr (preserving side-effects) or remove the statement entirely.

Deleted declarations still referencedreplaceStatementWithTodo replaced entire statements referencing removed fields, even when those statements defined variables used elsewhere (e.g., const secrets = { ..., backstageToken: token }), breaking downstream references.

Fix: declaresUsedBinding() checks if the statement's declared bindings are used elsewhere (including shorthand_property_identifier nodes like { secrets }). When found, a TODO comment is inserted above instead of replacing the statement.

New test fixtures

Codemod Test What it covers
experimental-form-decorators-to-stable nullish-coalescing-fallback Property access inside ?? fallback is not renamed
migrate-policy-query-user no-op-unrelated-token Unrelated { token } patterns are not modified
migrate-policy-query-user empty-destructuring-await const { token }: PolicyQueryUser = await exprawait expr
migrate-policy-query-user token-in-used-declaration TODO added above statement instead of replacing when binding is used elsewhere

experimental-form-decorators-to-stable:
- Skip property accesses (member expressions) when renaming object keys.
  Previously, `obj.EXPERIMENTAL_formDecorators` inside a pair value was
  incorrectly renamed, turning `X ?? EXPERIMENTAL_X` into `X ?? X`.

migrate-policy-query-user:
- Scope object pattern processing to PolicyQueryUser-typed patterns only.
  Previously, ANY `{ token }` destructuring in files importing from
  @backstage/plugin-permission-node was modified, causing false positives
  on unrelated patterns like `req.body` and type aliases.
- Clean up empty destructuring: `const {} = await expr` becomes `await expr`.
- Preserve variable declarations whose bindings are used elsewhere: add
  TODO comment above instead of replacing the entire statement.
- Detect shorthand_property_identifier usages when checking if a declared
  binding is referenced downstream.
@schultzp2020 schultzp2020 force-pushed the fix/codemod-false-positives branch from 1b17394 to a3e3d35 Compare June 3, 2026 19:05
The readme script now runs `yarn format` on README.md after generating
it, so the committed output always matches what prettier expects. This
avoids the CI freshness check failing when prettier table formatting
differs from the generator output.
@schultzp2020 schultzp2020 merged commit 8e32c92 into main Jun 3, 2026
2 checks passed
@schultzp2020 schultzp2020 deleted the fix/codemod-false-positives branch June 3, 2026 19:08
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