feat(csharp-scope): parity Unit 4 — callsite arity synthesis (infra)

Synthesize @reference.arity on every invocation_expression and
object_creation_expression by counting `argument` named children of
the backing `argument_list`. Wires the capture-to-Callsite pipeline
shared extractor already consumes (`scope-extractor.ts:878`).

No parity-count movement: the remaining arity-adjacent failures
(overload disambiguation, optional-parameter dedup, variadic
resolution) need type-based argument inference or member-call dedup,
both explicitly deferred in the plan's Known Limitations section.
This commit is infrastructure — future work lands on top of it.

Legacy 175/175 green; 21 parity failures remain.
This commit is contained in:
Gergo Magyar 2026-04-21 19:31:45 +01:00
parent a77153d860
commit 38b203599f

View file

@ -143,6 +143,30 @@ export function emitCsharpScopeCaptures(
}
}
// Synthesize `@reference.arity` on every callsite so the
// registry's arity filter can narrow overloads. Count the
// `argument` named children of the backing `argument_list`.
// Python doesn't synthesize this today; C# needs it because the
// language has method overloading and the suite asserts overload
// resolution.
const callTag = (
['@reference.call.free', '@reference.call.member', '@reference.call.constructor'] as const
).find((t) => grouped[t] !== undefined);
if (callTag !== undefined && grouped['@reference.arity'] === undefined) {
const anchor = grouped[callTag]!;
const callNode =
findNodeAtRange(tree.rootNode, anchor.range, 'invocation_expression') ??
findNodeAtRange(tree.rootNode, anchor.range, 'object_creation_expression');
if (callNode !== null) {
const argList = callNode.childForFieldName('arguments');
const n =
argList === null
? 0
: argList.namedChildren.filter((c) => c !== null && c.type === 'argument').length;
grouped['@reference.arity'] = syntheticCapture('@reference.arity', callNode, String(n));
}
}
out.push(grouped);
// Synthesize primary-constructor declarations on class/record