mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-11 22:53:04 +00:00
fix(zig): a build-module alias bound to an unindexed root fails closed
resolveThroughBuildModules returned undefined when the containing module
bound the alias to a file that is not indexed, which let the repo-wide
addModule map answer under the same name (gitnexus-check on 5299c552).
The module's table is the authority for its aliases: bound-but-unindexed
is null, only an unbound name falls through. Unit case with a same-named
repo-wide decoy, plus the outside-module file that still reaches it.
This commit is contained in:
parent
5299c5521f
commit
fe24b37f5e
2 changed files with 23 additions and 6 deletions
|
|
@ -69,9 +69,11 @@ function zigModulesContaining(
|
|||
* tables. `undefined` when no containing module binds the name (the caller
|
||||
* falls back to the repo-wide tables); `null` when the containing modules
|
||||
* DISAGREE — two same-directory modules that bind one alias to different
|
||||
* roots. That is fail-closed on purpose: picking either would mint a
|
||||
* confident wrong `IMPORTS` edge for half the files, which is the
|
||||
* first-wins defect this table exists to remove.
|
||||
* roots — or when the alias is bound to a root that is not indexed (a
|
||||
* generated or skipped file). Both are fail-closed on purpose: the module's
|
||||
* own table is the authority for the alias, and falling through to the
|
||||
* repo-wide map would reintroduce the first-wins answer this table exists
|
||||
* to remove, under a name the module never meant.
|
||||
*/
|
||||
function resolveThroughBuildModules(
|
||||
currentFile: string,
|
||||
|
|
@ -80,11 +82,14 @@ function resolveThroughBuildModules(
|
|||
modules: readonly ZigBuildModule[],
|
||||
): string | null | undefined {
|
||||
const targets = new Set<string>();
|
||||
let bound = false;
|
||||
for (const mod of zigModulesContaining(currentFile, modules)) {
|
||||
const target = mod.imports.get(importPath);
|
||||
if (target !== undefined && allFiles.has(target)) targets.add(target);
|
||||
if (target === undefined) continue;
|
||||
bound = true;
|
||||
if (allFiles.has(target)) targets.add(target);
|
||||
}
|
||||
if (targets.size === 0) return undefined;
|
||||
if (targets.size === 0) return bound ? null : undefined;
|
||||
if (targets.size > 1) return null;
|
||||
return targets.values().next().value ?? null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -317,12 +317,24 @@ describe('resolveZigImportInternal', () => {
|
|||
buildModules: [{ root: 'src/main.zig', imports: new Map([['cfg', 'src/cfg.zig']]) }],
|
||||
};
|
||||
expect(resolveZigImportInternal('src/main.zig', 'mylib', files, config)).toBe('src/lib.zig');
|
||||
// A table entry whose root is not indexed is not an answer either.
|
||||
// A table entry whose root is not indexed is not an answer either — and
|
||||
// it does not fall through: the module's table is the authority for the
|
||||
// alias, so a same-named repo-wide `addModule("cfg")` pointing elsewhere
|
||||
// must not answer in its place (gitnexus-check on 5299c552).
|
||||
const stale = {
|
||||
...config,
|
||||
rootModules: new Map([
|
||||
['mylib', 'src/lib.zig'],
|
||||
['cfg', 'src/cfg.zig'],
|
||||
]),
|
||||
buildModules: [{ root: 'src/main.zig', imports: new Map([['cfg', 'src/gone.zig']]) }],
|
||||
};
|
||||
expect(resolveZigImportInternal('src/main.zig', 'cfg', files, stale)).toBeNull();
|
||||
// …while a file OUTSIDE that module (`src/lib.zig` shares the root's
|
||||
// directory and so belongs to it; `other/x.zig` does not) still reaches
|
||||
// the repo-wide name.
|
||||
const outside = new Set<string>([...files, 'other/x.zig']);
|
||||
expect(resolveZigImportInternal('other/x.zig', 'cfg', outside, stale)).toBe('src/cfg.zig');
|
||||
});
|
||||
|
||||
it('returns null for an unknown bare name not in build.zig.zon', () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue