Summary
The JS/TS extractor classifies destructured object-pattern binding targets (including renamed bindings, e.g. const { values: flags } = parseArgs(...)) as kind: "function" instead of kind: "variable"/"constant". Because these bindings have no call-graph edges pointing at them by name, codegraph roles --role dead then flags them as dead-unresolved even when they are read repeatedly elsewhere in the file.
This is distinct from #1723 (which covers kind: parameter and interface/type member false positives) — the root cause here is extractor-level miscategorization of destructuring-pattern declarations, not the dead-code classifier's zero-fan-in heuristic on parameters.
Repro
$ codegraph roles --role dead --file scripts/token-benchmark.ts -T --json
scripts/token-benchmark.ts:42:
const { values: flags } = parseArgs({
options: { runs: { type: 'string', default: '3' }, /* ... */ },
strict: false,
});
flags is reported as kind: "function", role: "dead-unresolved", totalDependents: 0, despite being read 8+ times later in the same file (flags.runs, flags.model, flags['max-turns'], flags['nextjs-dir'], etc. at lines 56-64 and 531-532).
Also reproduces with non-renamed destructuring:
// tests/unit/snapshot-race-worker.mjs:13
const { dbPath, name, force } = workerData;
codegraph deps/codegraph where report dbPath, name, and force all as kind: "function" at line 13, and force is flagged dead-unresolved by the dead-code classifier.
Impact
Any top-level or block-scoped destructured binding (renamed or not) risks a false dead-unresolved classification, and more generally the kind metadata for these bindings is wrong (function instead of variable/constant), which pollutes any query filtering by kind.
Suggested fix
In the JS/TS extractor, object-pattern destructuring targets (ObjectPattern / ShorthandPropertyIdentifierPattern / PairPattern value nodes) should be extracted with kind: "variable" (or constant" when declared via const), not kind: "function". The dead-code classifier should then treat these like any other variable binding for reference counting.
Summary
The JS/TS extractor classifies destructured object-pattern binding targets (including renamed bindings, e.g.
const { values: flags } = parseArgs(...)) askind: "function"instead ofkind: "variable"/"constant". Because these bindings have no call-graph edges pointing at them by name,codegraph roles --role deadthen flags them asdead-unresolvedeven when they are read repeatedly elsewhere in the file.This is distinct from #1723 (which covers
kind: parameterand interface/type member false positives) — the root cause here is extractor-level miscategorization of destructuring-pattern declarations, not the dead-code classifier's zero-fan-in heuristic on parameters.Repro
scripts/token-benchmark.ts:42:flagsis reported askind: "function",role: "dead-unresolved",totalDependents: 0, despite being read 8+ times later in the same file (flags.runs,flags.model,flags['max-turns'],flags['nextjs-dir'], etc. at lines 56-64 and 531-532).Also reproduces with non-renamed destructuring:
codegraph deps/codegraph wherereportdbPath,name, andforceall askind: "function"at line 13, andforceis flaggeddead-unresolvedby the dead-code classifier.Impact
Any top-level or block-scoped destructured binding (renamed or not) risks a false
dead-unresolvedclassification, and more generally thekindmetadata for these bindings is wrong (functioninstead ofvariable/constant), which pollutes any query filtering by kind.Suggested fix
In the JS/TS extractor, object-pattern destructuring targets (
ObjectPattern/ShorthandPropertyIdentifierPattern/PairPatternvalue nodes) should be extracted withkind: "variable"(orconstant"when declared viaconst), notkind: "function". The dead-code classifier should then treat these like any other variable binding for reference counting.