* fix(ingestion): stop emitting phantom Function defs for array-method callbacks
The HOC-wrapped-arrow scope-query pattern (`const X = HOC(args => ...)`),
added for React idioms such as forwardRef/memo/useCallback, also matched
array higher-order-method callbacks like `const x = arr.map(a => ...)`.
Those produced a spurious `@declaration.function` named after the
binding, on top of its value def, so calls inside the callback attributed
to a phantom `Function:x` instead of the enclosing scope.
- Add a shared `isArrayMethodCallbackArrow` detector
(`ARRAY_CALLBACK_METHODS` blocklist) and suppress the
`@declaration.function` emit-side in both the JS and TS scope-captures
emitters, leaving the value binding as the sole def.
- Add `selectNodeBearingDef` in scope-extractor: the tested
collapse-rule contract (function-like > value > first) the deferred
node-creation migration will consume to keep one graph node per
binding.
This corrects the registry-primary scope model and CALLS-edge
attribution (calls inside array-method callbacks now source from the
enclosing File scope). The duplicate graph *node* itself is still
created by the legacy parse-worker path and is removed by the follow-up
node-creation migration.
Refs #1876
Co-authored-by: Cursor <cursoragent@cursor.com>
* test(ingestion): strengthen array-callback coverage; document receiver-blind suppression
Follow-ups from the production-readiness review of PR #1906:
- array-callback.ts: document that isArrayMethodCallbackArrow is
receiver-blind — an in-set method name on a NON-array receiver
(Map/Set.forEach, RxJS observable.map, query-builder .sort, lodash
chain .filter) is also suppressed. Accepted limitation, not a bug:
the binding holds the call's result value, not a callable.
- captures unit tests (JS + TS): add a non-array-receiver
characterization case, and extend the it.each lists to cover
findLast, findLastIndex, reduceRight — the full 13-entry
ARRAY_CALLBACK_METHODS set is now exercised in both languages.
- js-array-method-callback-attribution integration test: tighten the
File-sourced CALLS assertions from toBeGreaterThan(0) to
toHaveLength(1) (now also catches over-attribution).
- scope-extractor.ts: note that the dead selectNodeBearingDef export is
intentional and tracked by #1876 (deferred node-creation migration).
Comment-and-test only; no production behavior change. Verified locally:
tsc clean, prettier/eslint clean, captures unit 106 passed,
scope-extractor 31 passed, integration 3 passed.
Refs #1876
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>