mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-17 05:07:37 +08:00
889b6a3526
VB.NET's extractor keeps a call's last name only, so `Me.Panel.Controls.Add(x)` and `New System.Drawing.Size(1, 2)` arrived as bare `Add` / `Size` and exact / fuzzy matching took any class's member (even an enum case). The receiver is now read from the line: a member candidate needs `Me` / `MyBase` / `MyClass`, its own type or module as the last receiver segment, or a `(Of T)` type argument (`GetService(Of Notifier).Notify()`). Genuinely bare names are unchanged. A/B (edges removed / added): SCrawler -3452/+6, remoteapptool -143/+0, CompactGUI -31/+5, ViVeTool-GUI -1, TaskbarX 0. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
/**
|
|
* VB.NET's extractor keeps only the last name of a member access, so
|
|
* `Me.Panel.Controls.Add(x)` and `New System.Drawing.Size(1, 2)` reach the
|
|
* resolver as bare `Add` / `Size`. A member reached that way must match what
|
|
* the line writes before the dot: `Me` / `MyBase` / `MyClass`, the member's
|
|
* own type or module (`Logger.Log(…)`), or a service locator's type argument
|
|
* (`GetService(Of Notifier).Notify()`). SCrawler's designer code sent
|
|
* `New System.Drawing.Size(…)` to a nested enum's `Size` case 713 times and
|
|
* `Controls.Add(…)` to a collection class's `Add` 547 times.
|
|
*/
|
|
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
|
|
import * as fs from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
import { CodeGraph } from '../src';
|
|
|
|
let root = '';
|
|
let cg: CodeGraph;
|
|
|
|
beforeAll(async () => {
|
|
root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-vb-member-'));
|
|
const files: Record<string, string> = {
|
|
'Editors/UsersInfoForm.vb': `Namespace Editors
|
|
Friend Class UsersInfoForm
|
|
Private Enum EComparers
|
|
Name
|
|
Size
|
|
End Enum
|
|
End Class
|
|
End Namespace
|
|
`,
|
|
'Collections/DataColorCollection.vb': `Friend Class DataColorCollection
|
|
Friend Sub Add(ByVal Item As Object)
|
|
End Sub
|
|
End Class
|
|
`,
|
|
'Services/Notifier.vb': `Public Class Notifier
|
|
Public Sub Notify(ByVal Text As String)
|
|
End Sub
|
|
End Class
|
|
`,
|
|
'Logger.vb': `Public Module Logger
|
|
Public Sub Log(ByVal Text As String)
|
|
End Sub
|
|
End Module
|
|
`,
|
|
'MainForm.vb': `Public Class MainForm
|
|
Private Sub InitializeComponent()
|
|
Me.Panel.Controls.Add(Me.Button1)
|
|
Me.Panel.Size = New System.Drawing.Size(184, 25)
|
|
Logger.Log("ready")
|
|
Application.GetService(Of Notifier).Notify("ready")
|
|
Me.Refresh()
|
|
End Sub
|
|
|
|
Private Sub Refresh()
|
|
End Sub
|
|
End Class
|
|
`,
|
|
};
|
|
for (const [rel, content] of Object.entries(files)) {
|
|
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
|
|
fs.writeFileSync(path.join(root, rel), content);
|
|
}
|
|
cg = await CodeGraph.init(root, { index: true });
|
|
});
|
|
|
|
afterAll(() => {
|
|
cg?.close();
|
|
if (root) fs.rmSync(root, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('VB.NET member access', () => {
|
|
it('reaches a member only through what the line names', () => {
|
|
const ids = cg.getNodesInFile('MainForm.vb').map((n) => n.id);
|
|
const targets = cg
|
|
.getOutgoingEdgesFrom(ids)
|
|
.filter((e) => e.kind === 'calls')
|
|
.map((e) => cg.getNode(e.target)!.qualifiedName)
|
|
.sort();
|
|
expect(targets).not.toContain('Editors::UsersInfoForm::EComparers::Size');
|
|
expect(targets).not.toContain('DataColorCollection::Add');
|
|
expect(targets).toContain('Logger::Log');
|
|
expect(targets).toContain('Notifier::Notify');
|
|
expect(targets).toContain('MainForm::Refresh');
|
|
});
|
|
});
|