mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
test(cfg): pin *-harvest.ts literals to their own grammar in the gate (#2195 U10)
The grammar-literal validation gate scans cfg/visitors/, but a <lang>-harvest.ts basename was not in BASENAME_LANGS, so fileLanguages() fell it through to the weak ALL_LANGS valid-if-any bucket — a node-type literal dead in its own grammar but valid in some other grammar would pass undetected. Strip the -harvest suffix and reuse the visitor basename map so go-harvest -> Go, c-cpp-harvest -> C+C++, typescript-harvest -> TS, etc. The two language-agnostic harvesters (call-site-harvest, scope-tree-harvest) name no grammar and stay valid-if-any. Also corrects the now-inaccurate mode2Files comment. Adds a fileLanguages unit test; the existing gate stays green (no harvest file has a dead literal), and a scratch probe confirmed a bogus go-harvest literal is now caught. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f47e952ba1
commit
85d25c87cf
2 changed files with 43 additions and 6 deletions
|
|
@ -139,6 +139,17 @@ function fileLanguages(relPath: string): SupportedLanguages[] {
|
|||
}
|
||||
const base = relPath.replace(/\.ts$/, '').split('/').pop() ?? '';
|
||||
if (BASENAME_LANGS[base]) return BASENAME_LANGS[base];
|
||||
// A `<lang>-harvest.ts` CFG def/use harvester is validated against the SAME
|
||||
// grammar(s) as its `<lang>.ts` CFG visitor (go-harvest → Go, c-cpp-harvest →
|
||||
// C+C++, typescript-harvest → TS, …) — strip the suffix and reuse the visitor
|
||||
// basename map. The two genuinely language-agnostic harvesters —
|
||||
// call-site-harvest.ts (pure taint-site mechanism) and scope-tree-harvest.ts
|
||||
// (shared lexical-scope substrate) — name no grammar, so their stripped base
|
||||
// (`call-site`, `scope-tree`) misses BASENAME_LANGS and they fall through to
|
||||
// the valid-if-any ALL_LANGS bucket below (correct: they pin no per-grammar
|
||||
// literal).
|
||||
const harvestBase = base.replace(/-harvest$/, '');
|
||||
if (harvestBase !== base && BASENAME_LANGS[harvestBase]) return BASENAME_LANGS[harvestBase];
|
||||
// generic / shared / cross-language helpers → any grammar (valid-if-any)
|
||||
return [...ALL_LANGS];
|
||||
}
|
||||
|
|
@ -183,12 +194,15 @@ function mode2Files(): string[] {
|
|||
if (existsSync(cap)) files.push(cap);
|
||||
}
|
||||
}
|
||||
// CFG visitors (cfg/visitors/<lang>.ts) hard-code tree-sitter node-type and
|
||||
// field literals directly; include them so the gate validates per-language
|
||||
// CFG literals against the right grammar (basename → grammar via
|
||||
// `fileLanguages`: c-cpp → C+C++, csharp → C#, java → Java, go → Go,
|
||||
// typescript[-harvest] → TS). Without this, the gate stays green on dead
|
||||
// literals in a new visitor — the exact failure KTD5 warns about.
|
||||
// CFG visitors (cfg/visitors/<lang>.ts) AND their def/use harvesters
|
||||
// (cfg/visitors/<lang>-harvest.ts) hard-code tree-sitter node-type and field
|
||||
// literals directly; include them so the gate validates per-language CFG
|
||||
// literals against the right grammar (basename → grammar via `fileLanguages`:
|
||||
// c-cpp[-harvest] → C+C++, csharp[-harvest] → C#, go[-harvest] → Go,
|
||||
// typescript[-harvest] → TS, …; the language-agnostic call-site-harvest.ts and
|
||||
// scope-tree-harvest.ts carry no grammar literal and stay valid-if-any).
|
||||
// Without this, the gate stays green on a dead literal in a new visitor or
|
||||
// harvester — the exact failure KTD5 warns about.
|
||||
const cfgVisitorsDir = join(INGESTION_DIR, 'cfg', 'visitors');
|
||||
if (existsSync(cfgVisitorsDir)) walkTs(cfgVisitorsDir, files);
|
||||
const exportDetection = join(INGESTION_DIR, 'export-detection.ts');
|
||||
|
|
|
|||
|
|
@ -82,6 +82,29 @@ describe('literal-collectors', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('fileLanguages — `*-harvest.ts` map to their grammar (U10)', () => {
|
||||
const fl = __test.fileLanguages;
|
||||
it('maps each <lang>-harvest.ts to the same grammar(s) as its <lang>.ts visitor', () => {
|
||||
expect(fl('cfg/visitors/go-harvest.ts')).toEqual([SupportedLanguages.Go]);
|
||||
expect(fl('cfg/visitors/csharp-harvest.ts')).toEqual([SupportedLanguages.CSharp]);
|
||||
expect(fl('cfg/visitors/typescript-harvest.ts')).toEqual([SupportedLanguages.TypeScript]);
|
||||
expect(fl('cfg/visitors/c-cpp-harvest.ts')).toEqual([
|
||||
SupportedLanguages.C,
|
||||
SupportedLanguages.CPlusPlus,
|
||||
]);
|
||||
// a harvester pins exactly its visitor's grammar set, not the weak ALL_LANGS
|
||||
expect(fl('cfg/visitors/go-harvest.ts')).toEqual(fl('cfg/visitors/go.ts'));
|
||||
});
|
||||
it('leaves the language-agnostic harvesters valid-if-any (ALL_LANGS)', () => {
|
||||
const all = fl('cfg/visitors/call-site-harvest.ts');
|
||||
const scopeTree = fl('cfg/visitors/scope-tree-harvest.ts');
|
||||
// both name no grammar → fall through to the full gated set, which is far
|
||||
// larger than any single-/dual-language harvester mapping
|
||||
expect(all.length).toBeGreaterThan(2);
|
||||
expect(scopeTree).toEqual(all);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mode 4 — registry resolution layer (TypeChecker-gated)', () => {
|
||||
it('scans the resolution layer and tags literals by language dir', () => {
|
||||
const { nodeTypes } = __test.collectResolutionLayerLiterals();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue