Skip to content

feat(parser-react): handler resolution through props — 4-level chains (B1)#15

Merged
officialCodeWork merged 1 commit into
developmentfrom
build/phase-2/step-2.3-handler-resolution
Jul 13, 2026
Merged

feat(parser-react): handler resolution through props — 4-level chains (B1)#15
officialCodeWork merged 1 commit into
developmentfrom
build/phase-2/step-2.3-handler-resolution

Conversation

@officialCodeWork

Copy link
Copy Markdown
Owner

Summary

TRACKER Step 2.3 — failure mode B1, the second pillar of Phase 2. <button onClick={onSave}> where onSave is a prop means the real handler lives at a call site — possibly four components up. Per-file analysis stops dead at the prop boundary; the chain resolver doesn't.

The fixture chain, resolved

SaveButton  onClick={onSave}                    ← the event
  ↑ Toolbar      onSave={onSaveDraft}           ← renamed hop
  ↑ EditorPanel  onSaveDraft={() => onPersist()} ← inline-arrow wrap
  ↑ DraftEditor  onPersist={persistDraft}        ← the real handler
      persistDraft = () => fetch("/api/drafts", { method: "POST" })

⇒  event SaveButton.onClick --triggers--> POST /api/drafts

traceLineage(SaveButton) now reports /api/drafts — through three files it never touches directly.

Honesty guarantees

  • Chains dead after 4 levels flag the event unresolved-prop-handler and emit nothing — the OrphanButton fixture (handler never passed) has a forbidden assertion against cross-chain endpoint bleed.
  • Handled shapes: renamed props, props.X access, inline arrows wrapping prop calls, destructure defaults, function-declaration and arrow-const handlers.

Found by the fixture

Expression-bodied arrows (() => onPersist()) — the body is the CallExpression, and getDescendantsOfKind excludes the node itself, so the whole chain silently died at the wrap hop. Both body scans now include the body node.

Eval

  • Scorecard: 119 pass / 0 fail / 0 xfail · precision 1.000 · recall 1.000 · match accuracy 1.000
  • 80 unit tests (3 new: 4-level grounding, lineage reachability, orphan flagging)

Documentation

  • TRACKER.md — 2.3 done, Status → 2.4

🤖 Generated with Claude Code

… (B1)

Step 2.3 (TRACKER). Failure mode B1, the core static-analysis investment:

- resolveHandlerChains: events whose handler is a prop of their own
  component follow the prop through instance call sites up to 4 levels —
  renamed hops (onSave={onSaveDraft}), inline-arrow wraps
  (onSaveDraft={() => onPersist()}), props.X access, destructure defaults —
  until a real function body grounds the chain; bodies are mined for data
  sources and wired event --triggers--> data-source.
- Chains that never ground flag the event unresolved-prop-handler and emit
  NOTHING (the orphan fixture forbids cross-chain endpoint bleed).
- Bug found by the fixture: expression-bodied arrows ARE the call node —
  getDescendantsOfKind excludes self; both body scans now include it.
- Fixture b1-prop-drilled-handler: SaveButton.onClick grounds in
  POST /api/drafts through Toolbar → EditorPanel → DraftEditor.
- Scorecard: 119 pass / 0 fail; precision/recall 1.000. 80 unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@officialCodeWork
officialCodeWork merged commit 4c01687 into development Jul 13, 2026
1 check 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.

2 participants