fix(resolution): recognize union instantiation

This commit is contained in:
ctype_lab
2026-08-06 17:11:26 +09:00
parent ba58365c6f
commit e922563e05
3 changed files with 53 additions and 2 deletions
+47
View File
@@ -1020,6 +1020,31 @@ def bootstrap():
expect(callsToUserService).toHaveLength(0);
});
it('promotes calls→instantiates when target resolves to a C++ union', async () => {
// `Packet()` value-initializes the union. The extractor emits a calls
// reference for that expression, so resolution must preserve the
// class-like promotion that unions received when they were structs.
fs.writeFileSync(
path.join(tempDir, 'packet.cpp'),
`union Packet { unsigned int raw; };
void initialize() { Packet(); }
`
);
cg = await CodeGraph.init(tempDir, { index: true });
cg.resolveReferences();
const packet = cg.getNodesByKind('union').find((n) => n.name === 'Packet');
const initialize = cg.getNodesByKind('function').find((n) => n.name === 'initialize');
expect(packet).toBeDefined();
expect(initialize).toBeDefined();
const outgoing = cg.getOutgoingEdges(initialize!.id);
expect(outgoing.some((e) => e.kind === 'instantiates' && e.target === packet!.id)).toBe(true);
expect(outgoing.some((e) => e.kind === 'calls' && e.target === packet!.id)).toBe(false);
});
it('records instantiates for C++ stack/brace construction, targeting the class (#1035)', async () => {
// `Calculator calc(0)` (direct-init) and `Widget w{1, 2}` (brace-init)
// carry the constructor args directly on the declarator — there's no
@@ -2169,6 +2194,28 @@ func main() {
expect(result?.targetNodeId).toBe('class:logger.ts:Logger:10');
});
it('prefers a union candidate over a function for `instantiates` refs', () => {
const fn: Node = {
id: 'func:packet.cpp:Packet:5', kind: 'function', name: 'Packet',
qualifiedName: 'packet.cpp::Packet', filePath: 'packet.cpp', language: 'cpp',
startLine: 5, endLine: 7, startColumn: 0, endColumn: 0, updatedAt: Date.now(),
};
const union: Node = {
id: 'union:packet.hpp:Packet:10', kind: 'union', name: 'Packet',
qualifiedName: 'packet.hpp::Packet', filePath: 'packet.hpp', language: 'cpp',
startLine: 10, endLine: 14, startColumn: 0, endColumn: 0, updatedAt: Date.now(),
};
const ref = {
fromNodeId: 'func:main.cpp:initialize:1',
referenceName: 'Packet',
referenceKind: 'instantiates' as const,
line: 5, column: 0, filePath: 'main.cpp', language: 'cpp' as const,
};
const result = matchReference(ref, baseContext([fn, union]));
expect(result?.targetNodeId).toBe('union:packet.hpp:Packet:10');
});
it('prefers a function candidate over a non-function for `decorates` refs', () => {
const variable: Node = {
id: 'var:config.ts:Inject:5', kind: 'variable', name: 'Inject',