mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-22 00:31:17 +00:00
feat(csharp-scope): parity Unit 3a — cross-namespace using binding
Closes 2 parity failures (27 → 25). Extends the namespace-siblings pass to resolve `using X;` directives against known namespace buckets: for each `using` that targets a namespace declared somewhere in the workspace, inject that namespace's classes into the importer's module scope with origin='namespace'. This is the scope-resolution analog of legacy's csproj-driven directory↔namespace mapping. Without it, `new User()` in `Services/UserService.cs` (namespace MyApp.Services) can't see the User class in `Models/User.cs` (namespace MyApp.Models) even with `using MyApp.Models;` — the scope-resolver layer doesn't have csproj metadata to translate the dotted namespace path into a directory lookup. Legacy 175/175 green; 25 parity failures remain.
This commit is contained in:
parent
0b0fefcbff
commit
cb8a268031
1 changed files with 35 additions and 0 deletions
|
|
@ -126,6 +126,41 @@ export function populateCsharpNamespaceSiblings(
|
|||
// pattern (see `propagateImportedReturnTypes` which does the same
|
||||
// for module-scope typeBindings).
|
||||
const finalized = indexes.bindings as Map<ScopeId, Map<string, BindingRef[]>>;
|
||||
|
||||
// Cross-namespace imports: for each file's `using X;` directive,
|
||||
// if `X` matches a known namespace bucket, inject that bucket's
|
||||
// classes into the importer's module scope. This is what makes
|
||||
// `new User()` in `namespace App;` resolve to `User` declared in
|
||||
// a sibling file with `namespace Models;` when the importer says
|
||||
// `using Models;`. Legacy uses csproj directory↔namespace mapping;
|
||||
// the scope-resolver layer uses the declared namespace directly.
|
||||
for (const parsed of parsedFiles) {
|
||||
const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
|
||||
if (moduleScope === undefined) continue;
|
||||
for (const imp of parsed.parsedImports) {
|
||||
if (imp.kind !== 'namespace') continue;
|
||||
const targetNs = imp.targetRaw;
|
||||
if (targetNs === null || targetNs === '') continue;
|
||||
const bucket = buckets.get(targetNs);
|
||||
if (bucket === undefined) continue;
|
||||
for (const def of bucket.classDefs) {
|
||||
if (def.filePath === parsed.filePath) continue;
|
||||
const q = def.qualifiedName ?? '';
|
||||
const simpleName = q.includes('.') ? q.slice(q.lastIndexOf('.') + 1) : q;
|
||||
if (simpleName === '') continue;
|
||||
let scopeBindings = finalized.get(moduleScope.id);
|
||||
if (scopeBindings === undefined) {
|
||||
scopeBindings = new Map<string, BindingRef[]>();
|
||||
finalized.set(moduleScope.id, scopeBindings);
|
||||
}
|
||||
const existing = scopeBindings.get(simpleName) ?? [];
|
||||
if (existing.some((b) => b.def.nodeId === def.nodeId)) continue;
|
||||
existing.push({ def, origin: 'namespace' });
|
||||
scopeBindings.set(simpleName, existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [, bucket] of buckets) {
|
||||
// De-dup by (nodeId, filePath) across multiple declarations (e.g.
|
||||
// partial classes declaring the same name in two files — we take
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue