fix(pascal): attribute a free routine's calls to it, not the file (#795)
A Pascal/Delphi procedure or function defined ONLY in the implementation section (no interface declaration, not a class method) had no node of its own, so extractPascalDefProc's caller lookup fell through to the nodeStack top — the file node. Every call in such a routine's body was lumped under the unit: callers returned the file, and impact couldn't attribute the call to the routine. (Methods were fine — they get a node from their class declaration.) Fix: when extractPascalDefProc finds no existing node for a FREE routine (a name with no `.`), create a function node for it and attribute the body's calls to it. Interface-declared free routines already have a node (found via the methodIndex), so there's no duplicate; methods keep their existing class-declaration node. PascalCoin A/B: +511 / -145 — the +511 are calls now correctly attributed to their actual routine (`allocate_new_datablock -> TDisposables::GetMem`), replacing -145 file-level aggregates; +248 new function nodes for the implementation-only routines. New synthetic test asserts a free routine's call attributes to it alongside a method caller. EXTRACTION_VERSION 17->18. Full suite green. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5342f7a93e
commit
dac00e7d44
@@ -3352,5 +3352,30 @@ end.
|
||||
expect(isCalled('TFoo::GetValue')).toBe(false);
|
||||
expect(isCalled('TFoo::SetValue')).toBe(false);
|
||||
});
|
||||
|
||||
it('attributes an implementation-only free procedure\'s calls to the procedure, not the file', async () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tempDir, 'main.pas'),
|
||||
`unit Main;
|
||||
interface
|
||||
type
|
||||
TTgt = class
|
||||
procedure Hit;
|
||||
end;
|
||||
TFoo = class
|
||||
procedure DoStuff;
|
||||
end;
|
||||
implementation
|
||||
procedure TTgt.Hit; begin end;
|
||||
procedure TFoo.DoStuff; var t: TTgt; begin t.Hit; end;
|
||||
procedure Helper; var t: TTgt; begin t.Hit; end;
|
||||
`
|
||||
);
|
||||
cg = await CodeGraph.init(tempDir, { index: true });
|
||||
// `Helper` is implementation-only (no interface decl, not a method), but its
|
||||
// body's call must attribute to `Helper`, not the file/module — alongside the
|
||||
// method `DoStuff`.
|
||||
expect(callerNamesOf('TTgt::Hit')).toEqual(['DoStuff', 'Helper']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user