Skip to content

fix(core): CORRECT001 stop flagging itemless {#each} and fix backwards rationale - #137

Merged
oekazuma merged 1 commit into
mainfrom
fix/135-correct001-itemless-each
Jul 7, 2026
Merged

oekazuma merged 1 commit into
mainfrom
fix/135-correct001-itemless-each

Conversation

@oekazuma

@oekazuma oekazuma commented Jul 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes #135 — two problems in CORRECT001 (keyed each), found while auditing existing rules against the official Svelte docs.

  • False positive on itemless each blocks: the official {#each ...} docs document the itemless form ({#each { length: 8 }, i}) as a first-class "render N times" pattern (the chess-board example). CORRECT001 flagged it as unkeyed, but there is no item identity to key on — the only possible key is the index itself, which is a no-op. collectEachBlocks now skips each blocks with no item context (node.context == null), verified against the real parser.
  • Rationale described the unkeyed mechanism backwards: it claimed unkeyed each "destroys and recreates DOM nodes" on reorder. The docs describe the opposite — a key lets Svelte "insert, move, and delete" nodes, rather than adding/removing at the end and rewriting the data of nodes in between. The user-facing consequence (state/focus loss) was right; the mechanism was backwards. Reworded in the rule and the rule docs (en/ja).

Test plan

  • New tests in component-parse.test.ts: itemless each is ignored, and stays ignored even if given a (meaningless) index key.
  • pnpm build && pnpm typecheck && pnpm test && pnpm lint: all pass (core 349, cli 345, vite 84, mcp 13).
  • pnpm --filter docs check: 0 errors.
  • Patch changeset for @svelte-vitals/core + svelte-vitals (behavioral change to a shipped rule).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of itemless {#each} blocks so they are no longer treated as keyed items in error checks.
    • Reduced false positives for rendering patterns that repeat content without meaningful item identity.
  • Documentation

    • Clarified guidance for the keyed each rule, including which {#each} patterns are ignored and why keys matter for DOM updates and state retention.
  • Tests

    • Added coverage for itemless {#each} cases to confirm they are ignored correctly.

…s rationale

The official {#each} docs document the itemless form ({#each { length: 8 }, i})
as a first-class "render N times" pattern (the chess-board example). CORRECT001
flagged it as unkeyed, but there is no item identity to key on there — the only
possible key is the index itself, which is a no-op. Skip each blocks with no
item context.

Also corrected the rule's rationale, which claimed unkeyed each "destroys and
recreates DOM nodes" on reorder; the docs describe the opposite mechanism —
nodes are reused and their data rewritten in place, which is exactly why
element state/focus sticks to positions instead of items.

Fixes #135

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f9ddc34a-c72a-439b-adc9-76221c05c473

📥 Commits

Reviewing files that changed from the base of the PR and between 8598b42 and 18b11af.

📒 Files selected for processing (6)
  • .changeset/correct001-itemless-each.md
  • docs/src/content/docs/ja/rules/correct001.md
  • docs/src/content/docs/rules/correct001.md
  • packages/core/src/component-parse.ts
  • packages/core/src/rules/correctness/correct001-002.ts
  • packages/core/test/component-parse.test.ts

📝 Walkthrough

Walkthrough

CORRECT001's each-block collection now skips itemless {#each} blocks (node.context == null) so they are no longer falsely flagged for missing keys. The rule's rationale text and English/Japanese documentation were updated to accurately describe the unkeyed reorder mechanism, with new tests and a patch changeset added.

Changes

CORRECT001 itemless each fix

Layer / File(s) Summary
Skip itemless each blocks in collectEachBlocks
packages/core/src/component-parse.ts, packages/core/test/component-parse.test.ts
collectEachBlocks now guards on node.context != null before recording hasKey, and new tests assert itemless {length: n} each blocks (with or without an index key) produce empty eachBlocks.
Correct rationale text and docs
packages/core/src/rules/correctness/correct001-002.ts, docs/src/content/docs/rules/correct001.md, docs/src/content/docs/ja/rules/correct001.md
The correct001EachKey rationale and both English/Japanese docs are reworded to describe Svelte appending/removing nodes at the end and rewriting middle node data when keys are missing, and both docs now list the itemless "render N times" pattern as an ignored case.
Changeset for patch release
.changeset/correct001-itemless-each.md
Adds a patch changeset for @svelte-vitals/core and svelte-vitals describing the itemless each fix and corrected rationale.

Estimated code review effort: 2 (Simple) | ~12 minutes

Possibly related PRs

  • oekazuma/svelte-vitals#68: Prior PR introduced the collectEachBlocks/correct001EachKey pipeline that this PR directly refines to exclude itemless each blocks.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main behavioral and rationale fix.
Linked Issues check ✅ Passed The PR addresses both linked requirements: it ignores itemless {#each} blocks and rewrites the incorrect rationale in code and docs.
Out of Scope Changes check ✅ Passed The changes stay within the linked issue scope, with only the expected docs, tests, and changeset updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@oekazuma
oekazuma merged commit ed2413d into main Jul 7, 2026
7 checks passed
@oekazuma
oekazuma deleted the fix/135-correct001-itemless-each branch July 7, 2026 15:05
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.

fix(correctness): CORRECT001 false-positives on itemless {#each} and misstates the unkeyed mechanism

1 participant