mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-04 02:31:36 +00:00
feat(csharp-scope): parity Unit 3c — static call + default-namespace
Closes 2 parity failures (22 → 21). - `receiver-bound-calls.ts`: add Case 5 for class-as-receiver. When `Animal.Classify()` has an identifier receiver that resolves to a Class binding (rather than a variable with a typeBinding), look up the member on the class's MRO chain. Covers C#-style static calls and any type-qualified member access. Python doesn't hit this because `ClassName.method()` is syntactically identical to a free call there. - `namespace-siblings.ts`: treat files with no `namespace X;` declaration as living in the default (empty-name) bucket, so types declared in no-namespace files share cross-file visibility. Required for fixtures without explicit namespaces (e.g. the method-enrichment fixture's Animal/App/Dog classes). Legacy 175/175 green; 21 parity failures remain.
This commit is contained in:
parent
f0805640e9
commit
a77153d860
2 changed files with 34 additions and 1 deletions
|
|
@ -73,7 +73,10 @@ export function populateCsharpNamespaceSiblings(
|
|||
NAMESPACE_RE.lastIndex = 0;
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = NAMESPACE_RE.exec(content)) !== null) names.push(m[1]!);
|
||||
if (names.length === 0) continue;
|
||||
// Files with no `namespace X;` declaration still share visibility
|
||||
// — they all live in the default (global) namespace. Use the
|
||||
// empty-string bucket key for this case.
|
||||
if (names.length === 0) names.push('');
|
||||
|
||||
const namespaceScopes = parsed.scopes.filter((s) => s.kind === 'Namespace');
|
||||
// With file-scoped namespaces (`namespace X;`), the Namespace
|
||||
|
|
|
|||
|
|
@ -287,6 +287,36 @@ export function emitReceiverBoundCalls(
|
|||
emitted++;
|
||||
handledSites.add(siteKey);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Case 5: class-as-receiver (static call / type member) ────
|
||||
// `Animal.Classify()` — receiver name resolves to a Class
|
||||
// binding, not a typeBinding. Look up the member on the class's
|
||||
// MRO chain. Python syntactically collapses this with free
|
||||
// calls; C# (and other statically-typed languages) distinguish
|
||||
// via the member_access_expression shape.
|
||||
if (typeRef === undefined) {
|
||||
const classDef = findClassBindingInScope(site.inScope, receiverName, scopes);
|
||||
if (classDef !== undefined) {
|
||||
const chain = [classDef.nodeId, ...scopes.methodDispatch.mroFor(classDef.nodeId)];
|
||||
let memberDef: SymbolDefinition | undefined;
|
||||
for (const ownerId of chain) {
|
||||
memberDef = findOwnedMember(ownerId, memberName, index);
|
||||
if (memberDef !== undefined) break;
|
||||
}
|
||||
if (memberDef !== undefined) {
|
||||
const reason =
|
||||
site.kind === 'write' || site.kind === 'read'
|
||||
? site.kind
|
||||
: 'scope-resolution: class-receiver';
|
||||
const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen);
|
||||
if (ok) {
|
||||
emitted++;
|
||||
handledSites.add(siteKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue