@opensip-cli/graph-go 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/branch-coverage-2.test.d.ts +21 -0
- package/dist/__tests__/branch-coverage-2.test.d.ts.map +1 -0
- package/dist/__tests__/branch-coverage-2.test.js +187 -0
- package/dist/__tests__/branch-coverage-2.test.js.map +1 -0
- package/dist/__tests__/branch-coverage.test.d.ts +17 -0
- package/dist/__tests__/branch-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/branch-coverage.test.js +136 -0
- package/dist/__tests__/branch-coverage.test.js.map +1 -0
- package/dist/__tests__/cache-key.test.d.ts +5 -0
- package/dist/__tests__/cache-key.test.d.ts.map +1 -0
- package/dist/__tests__/cache-key.test.js +45 -0
- package/dist/__tests__/cache-key.test.js.map +1 -0
- package/dist/__tests__/depends-on-emission.test.d.ts +13 -0
- package/dist/__tests__/depends-on-emission.test.d.ts.map +1 -0
- package/dist/__tests__/depends-on-emission.test.js +215 -0
- package/dist/__tests__/depends-on-emission.test.js.map +1 -0
- package/dist/__tests__/discover.test.d.ts +5 -0
- package/dist/__tests__/discover.test.d.ts.map +1 -0
- package/dist/__tests__/discover.test.js +59 -0
- package/dist/__tests__/discover.test.js.map +1 -0
- package/dist/__tests__/parse.test.d.ts +5 -0
- package/dist/__tests__/parse.test.d.ts.map +1 -0
- package/dist/__tests__/parse.test.js +59 -0
- package/dist/__tests__/parse.test.js.map +1 -0
- package/dist/__tests__/resolve.test.d.ts +18 -0
- package/dist/__tests__/resolve.test.d.ts.map +1 -0
- package/dist/__tests__/resolve.test.js +205 -0
- package/dist/__tests__/resolve.test.js.map +1 -0
- package/dist/__tests__/walk.test.d.ts +10 -0
- package/dist/__tests__/walk.test.d.ts.map +1 -0
- package/dist/__tests__/walk.test.js +163 -0
- package/dist/__tests__/walk.test.js.map +1 -0
- package/dist/body-digest.d.ts +20 -0
- package/dist/body-digest.d.ts.map +1 -0
- package/dist/body-digest.js +139 -0
- package/dist/body-digest.js.map +1 -0
- package/dist/cache-key.d.ts +17 -0
- package/dist/cache-key.d.ts.map +1 -0
- package/dist/cache-key.js +18 -0
- package/dist/cache-key.js.map +1 -0
- package/dist/discover.d.ts +24 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +33 -0
- package/dist/discover.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +17 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +14 -0
- package/dist/parse.js.map +1 -0
- package/dist/resolve.d.ts +32 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +294 -0
- package/dist/resolve.js.map +1 -0
- package/dist/rule-hints.d.ts +16 -0
- package/dist/rule-hints.d.ts.map +1 -0
- package/dist/rule-hints.js +62 -0
- package/dist/rule-hints.js.map +1 -0
- package/dist/walk-metadata.d.ts +22 -0
- package/dist/walk-metadata.d.ts.map +1 -0
- package/dist/walk-metadata.js +96 -0
- package/dist/walk-metadata.js.map +1 -0
- package/dist/walk.d.ts +47 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +278 -0
- package/dist/walk.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branch-coverage tests for graph-go/resolve.ts.
|
|
3
|
+
*
|
|
4
|
+
* Drives the full Go adapter (discover + parse + walk + resolve)
|
|
5
|
+
* over fixtures exercising:
|
|
6
|
+
* - `call_expression` with identifier callee (`foo()`)
|
|
7
|
+
* - selector_expression callees (`obj.Method()`, `pkg.Func()`,
|
|
8
|
+
* `Type{}.method()`)
|
|
9
|
+
* - Confidence ladder: 0 → unknown/low; 1 → static/medium;
|
|
10
|
+
* N → method-dispatch/low
|
|
11
|
+
* - Unrecognized callee shapes (index expression, type assertion
|
|
12
|
+
* call) → unresolved
|
|
13
|
+
* - `defer` and `go` statements → discarded=true
|
|
14
|
+
* - Closure creation edges → static/high
|
|
15
|
+
* - I-4: catalog is not mutated
|
|
16
|
+
*/
|
|
17
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
21
|
+
import { goGraphAdapter } from '../index.js';
|
|
22
|
+
function pipeline(dir) {
|
|
23
|
+
const discovery = goGraphAdapter.discoverFiles({ cwd: dir });
|
|
24
|
+
const parsed = goGraphAdapter.parseProject({
|
|
25
|
+
projectDirAbs: discovery.projectDirAbs,
|
|
26
|
+
files: discovery.files,
|
|
27
|
+
compilerOptions: discovery.compilerOptions,
|
|
28
|
+
resolutionMode: 'exact',
|
|
29
|
+
});
|
|
30
|
+
const walk = goGraphAdapter.walkProject({
|
|
31
|
+
project: parsed.project,
|
|
32
|
+
projectDirAbs: discovery.projectDirAbs,
|
|
33
|
+
files: discovery.files,
|
|
34
|
+
});
|
|
35
|
+
const catalog = {
|
|
36
|
+
version: '3.0',
|
|
37
|
+
tool: 'graph',
|
|
38
|
+
language: goGraphAdapter.id,
|
|
39
|
+
builtAt: '2026-05-27T00:00:00.000Z',
|
|
40
|
+
cacheKey: goGraphAdapter.cacheKey({
|
|
41
|
+
projectDirAbs: discovery.projectDirAbs,
|
|
42
|
+
configPathAbs: discovery.configPathAbs,
|
|
43
|
+
compilerOptions: discovery.compilerOptions,
|
|
44
|
+
resolutionMode: 'exact',
|
|
45
|
+
}),
|
|
46
|
+
functions: walk.occurrences,
|
|
47
|
+
};
|
|
48
|
+
const resolved = goGraphAdapter.resolveCallSites({
|
|
49
|
+
project: parsed.project,
|
|
50
|
+
catalog,
|
|
51
|
+
callSites: walk.callSites,
|
|
52
|
+
projectDirAbs: discovery.projectDirAbs,
|
|
53
|
+
resolutionMode: 'exact',
|
|
54
|
+
});
|
|
55
|
+
return { project: parsed.project, walk, catalog, resolved };
|
|
56
|
+
}
|
|
57
|
+
function allEdges(resolved) {
|
|
58
|
+
const out = [];
|
|
59
|
+
for (const edges of resolved.edgesByOwner.values())
|
|
60
|
+
out.push(...edges);
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
describe('graph-go resolve.ts', () => {
|
|
64
|
+
let dir;
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
dir = mkdtempSync(join(tmpdir(), 'graph-go-resolve-'));
|
|
67
|
+
});
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
rmSync(dir, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
it('resolves single-match identifier call as static/medium', () => {
|
|
72
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { callee() }\nfunc callee() {}\n`, 'utf8');
|
|
73
|
+
const { resolved } = pipeline(dir);
|
|
74
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('callee('));
|
|
75
|
+
expect(edge).toBeDefined();
|
|
76
|
+
expect(edge?.resolution).toBe('static');
|
|
77
|
+
expect(edge?.confidence).toBe('medium');
|
|
78
|
+
expect(edge?.to.length).toBe(1);
|
|
79
|
+
expect(resolved.stats.resolvedMedium).toBeGreaterThan(0);
|
|
80
|
+
});
|
|
81
|
+
it('resolves multi-match identifier call as method-dispatch/low', () => {
|
|
82
|
+
// Two functions with the same simple name (one method, one free
|
|
83
|
+
// function) — name-based resolution sees two matches.
|
|
84
|
+
writeFileSync(join(dir, 'main.go'), `package main\ntype Foo struct{}\nfunc (f Foo) work() {}\nfunc work() {}\nfunc caller(f Foo) { f.work(); work() }\n`, 'utf8');
|
|
85
|
+
const { resolved } = pipeline(dir);
|
|
86
|
+
const edges = allEdges(resolved).filter((e) => e.text.includes('work('));
|
|
87
|
+
expect(edges.length).toBeGreaterThan(0);
|
|
88
|
+
for (const e of edges) {
|
|
89
|
+
expect(e.resolution).toBe('method-dispatch');
|
|
90
|
+
expect(e.confidence).toBe('low');
|
|
91
|
+
expect(e.to.length).toBe(2);
|
|
92
|
+
}
|
|
93
|
+
expect(resolved.stats.resolvedLow).toBeGreaterThan(0);
|
|
94
|
+
});
|
|
95
|
+
it('reports unknown/low when no catalog entry matches', () => {
|
|
96
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { unknownFunc() }\n`, 'utf8');
|
|
97
|
+
const { resolved } = pipeline(dir);
|
|
98
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('unknownFunc('));
|
|
99
|
+
expect(edge).toBeDefined();
|
|
100
|
+
expect(edge?.resolution).toBe('unknown');
|
|
101
|
+
expect(edge?.confidence).toBe('low');
|
|
102
|
+
expect(edge?.to).toEqual([]);
|
|
103
|
+
expect(resolved.stats.unresolved).toBeGreaterThan(0);
|
|
104
|
+
});
|
|
105
|
+
it('resolves selector_expression callees by trailing field name', () => {
|
|
106
|
+
writeFileSync(join(dir, 'main.go'), `package main\ntype Foo struct{}\nfunc (f Foo) bar() {}\nfunc caller(f Foo) { f.bar() }\n`, 'utf8');
|
|
107
|
+
const { resolved } = pipeline(dir);
|
|
108
|
+
const edge = allEdges(resolved).find((e) => e.text === 'f.bar()');
|
|
109
|
+
expect(edge).toBeDefined();
|
|
110
|
+
expect(edge?.resolution).toBe('static');
|
|
111
|
+
expect(edge?.to.length).toBe(1);
|
|
112
|
+
});
|
|
113
|
+
it('treats pkg.Func selector calls the same way (field name lookup)', () => {
|
|
114
|
+
// We can't tell `pkg.Func` from `obj.Method` without type info, so
|
|
115
|
+
// the resolver looks up by the trailing identifier. Here `Println`
|
|
116
|
+
// has no catalog match → unknown.
|
|
117
|
+
writeFileSync(join(dir, 'main.go'), `package main\nimport "fmt"\nfunc caller() { fmt.Println("hi") }\n`, 'utf8');
|
|
118
|
+
const { resolved } = pipeline(dir);
|
|
119
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('fmt.Println'));
|
|
120
|
+
expect(edge).toBeDefined();
|
|
121
|
+
expect(edge?.resolution).toBe('unknown');
|
|
122
|
+
expect(edge?.to).toEqual([]);
|
|
123
|
+
});
|
|
124
|
+
it('returns null target when callee is a non-id/non-selector shape (e.g., index expression)', () => {
|
|
125
|
+
// `funcs["foo"]()` — call_expression.function is an index_expression,
|
|
126
|
+
// which the resolver does not recognize → unknown/low.
|
|
127
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller(funcs map[string]func()) { funcs["foo"]() }\n`, 'utf8');
|
|
128
|
+
const { resolved } = pipeline(dir);
|
|
129
|
+
const edges = allEdges(resolved).filter((e) => e.text.includes('funcs['));
|
|
130
|
+
expect(edges.length).toBeGreaterThan(0);
|
|
131
|
+
for (const e of edges) {
|
|
132
|
+
expect(e.resolution).toBe('unknown');
|
|
133
|
+
expect(e.to).toEqual([]);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
it('marks defer call as discarded=true', () => {
|
|
137
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { defer cleanup() }\nfunc cleanup() {}\n`, 'utf8');
|
|
138
|
+
const { resolved } = pipeline(dir);
|
|
139
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('cleanup('));
|
|
140
|
+
expect(edge).toBeDefined();
|
|
141
|
+
expect(edge?.discarded).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
it('marks go statement call as discarded=true', () => {
|
|
144
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { go worker() }\nfunc worker() {}\n`, 'utf8');
|
|
145
|
+
const { resolved } = pipeline(dir);
|
|
146
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('worker('));
|
|
147
|
+
expect(edge).toBeDefined();
|
|
148
|
+
expect(edge?.discarded).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
it('marks plain expression-statement call as discarded=true', () => {
|
|
151
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { side() }\nfunc side() {}\n`, 'utf8');
|
|
152
|
+
const { resolved } = pipeline(dir);
|
|
153
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('side('));
|
|
154
|
+
expect(edge?.discarded).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
it('marks call in assignment context as discarded=false', () => {
|
|
157
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { x := compute(); _ = x }\nfunc compute() int { return 1 }\n`, 'utf8');
|
|
158
|
+
const { resolved } = pipeline(dir);
|
|
159
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('compute('));
|
|
160
|
+
expect(edge).toBeDefined();
|
|
161
|
+
expect(edge?.discarded).toBe(false);
|
|
162
|
+
});
|
|
163
|
+
it('treats parenthesized_expression transparently when checking discard', () => {
|
|
164
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc caller() { (compute()) }\nfunc compute() int { return 1 }\n`, 'utf8');
|
|
165
|
+
const { resolved } = pipeline(dir);
|
|
166
|
+
const edge = allEdges(resolved).find((e) => e.text.startsWith('compute('));
|
|
167
|
+
expect(edge).toBeDefined();
|
|
168
|
+
expect(edge?.discarded).toBe(true);
|
|
169
|
+
});
|
|
170
|
+
it('emits a creation edge (static/high) for func_literal closures', () => {
|
|
171
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc maker() func(int) int {\n inc := func(n int) int { return n + 1 }\n return inc\n}\n`, 'utf8');
|
|
172
|
+
const { resolved } = pipeline(dir);
|
|
173
|
+
const creation = allEdges(resolved).find((e) => e.resolution === 'static' && e.confidence === 'high');
|
|
174
|
+
expect(creation).toBeDefined();
|
|
175
|
+
expect(resolved.stats.resolvedHigh).toBeGreaterThan(0);
|
|
176
|
+
});
|
|
177
|
+
it('I-4 — resolveCallSites does not mutate the input catalog', () => {
|
|
178
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc a() { b() }\nfunc b() {}\n`, 'utf8');
|
|
179
|
+
const { catalog, walk, project } = pipeline(dir);
|
|
180
|
+
const before = JSON.stringify(catalog);
|
|
181
|
+
goGraphAdapter.resolveCallSites({
|
|
182
|
+
project,
|
|
183
|
+
catalog,
|
|
184
|
+
callSites: walk.callSites,
|
|
185
|
+
projectDirAbs: dir,
|
|
186
|
+
resolutionMode: 'exact',
|
|
187
|
+
});
|
|
188
|
+
expect(JSON.stringify(catalog)).toBe(before);
|
|
189
|
+
});
|
|
190
|
+
it('skips synthetic <module-init> entries from the byName index', () => {
|
|
191
|
+
writeFileSync(join(dir, 'a.go'), `package main\nfunc m() {}\n`, 'utf8');
|
|
192
|
+
writeFileSync(join(dir, 'b.go'), `package main\nfunc m2() {}\n`, 'utf8');
|
|
193
|
+
const { resolved } = pipeline(dir);
|
|
194
|
+
const edges = allEdges(resolved);
|
|
195
|
+
// No call edge should reference the module-init synthetic name.
|
|
196
|
+
expect(edges.every((e) => !e.text.includes('<module-init>'))).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
it('emits empty edge map when there are no call sites', () => {
|
|
199
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc Empty() {}\n`, 'utf8');
|
|
200
|
+
const { resolved } = pipeline(dir);
|
|
201
|
+
expect(resolved.stats.totalCallSites).toBe(0);
|
|
202
|
+
expect(resolved.edgesByOwner.size).toBe(0);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=resolve.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.test.js","sourceRoot":"","sources":["../../src/__tests__/resolve.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branch-coverage tests for graph-go/walk.ts.
|
|
3
|
+
*
|
|
4
|
+
* Drives the full Go adapter (discover + parse + walk) over fixtures
|
|
5
|
+
* exercising: line comments, block comments, interpreted strings,
|
|
6
|
+
* raw strings, function declarations, method declarations (pointer
|
|
7
|
+
* and value receivers), and func_literal (closure) emission.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=walk.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/walk.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branch-coverage tests for graph-go/walk.ts.
|
|
3
|
+
*
|
|
4
|
+
* Drives the full Go adapter (discover + parse + walk) over fixtures
|
|
5
|
+
* exercising: line comments, block comments, interpreted strings,
|
|
6
|
+
* raw strings, function declarations, method declarations (pointer
|
|
7
|
+
* and value receivers), and func_literal (closure) emission.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { tmpdir } from 'node:os';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
13
|
+
import { goGraphAdapter } from '../index.js';
|
|
14
|
+
function run(dir) {
|
|
15
|
+
const discovery = goGraphAdapter.discoverFiles({ cwd: dir });
|
|
16
|
+
const parsed = goGraphAdapter.parseProject({
|
|
17
|
+
projectDirAbs: discovery.projectDirAbs,
|
|
18
|
+
files: discovery.files,
|
|
19
|
+
compilerOptions: discovery.compilerOptions,
|
|
20
|
+
resolutionMode: 'exact',
|
|
21
|
+
});
|
|
22
|
+
return goGraphAdapter.walkProject({
|
|
23
|
+
project: parsed.project,
|
|
24
|
+
projectDirAbs: discovery.projectDirAbs,
|
|
25
|
+
files: discovery.files,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
describe('graph-go walk.ts', () => {
|
|
29
|
+
let dir;
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
dir = mkdtempSync(join(tmpdir(), 'graph-go-walk-'));
|
|
32
|
+
});
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
rmSync(dir, { recursive: true, force: true });
|
|
35
|
+
});
|
|
36
|
+
it('emits function-declaration for top-level funcs', () => {
|
|
37
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc topLevel() int { return 1 }\n`, 'utf8');
|
|
38
|
+
const walk = run(dir);
|
|
39
|
+
expect(Object.keys(walk.occurrences)).toContain('topLevel');
|
|
40
|
+
const occs = walk.occurrences.topLevel;
|
|
41
|
+
expect(occs?.[0]?.kind).toBe('function-declaration');
|
|
42
|
+
expect(occs?.[0]?.enclosingClass).toBeNull();
|
|
43
|
+
});
|
|
44
|
+
it('emits method with enclosingClass set to receiver type (value receiver)', () => {
|
|
45
|
+
writeFileSync(join(dir, 'main.go'), `package main\ntype Foo struct{}\nfunc (f Foo) bar() int { return 1 }\n`, 'utf8');
|
|
46
|
+
const walk = run(dir);
|
|
47
|
+
const bar = walk.occurrences.bar;
|
|
48
|
+
expect(bar?.[0]?.kind).toBe('method');
|
|
49
|
+
expect(bar?.[0]?.enclosingClass).toBe('Foo');
|
|
50
|
+
});
|
|
51
|
+
it('emits method with enclosingClass set for pointer receiver (*Foo → Foo)', () => {
|
|
52
|
+
writeFileSync(join(dir, 'main.go'), `package main\ntype Foo struct{}\nfunc (f *Foo) baz() int { return 2 }\n`, 'utf8');
|
|
53
|
+
const walk = run(dir);
|
|
54
|
+
const baz = walk.occurrences.baz;
|
|
55
|
+
expect(baz?.[0]?.kind).toBe('method');
|
|
56
|
+
expect(baz?.[0]?.enclosingClass).toBe('Foo');
|
|
57
|
+
});
|
|
58
|
+
it('emits arrow occurrence for func_literal (closures)', () => {
|
|
59
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc maker() func(int) int {\n inc := func(n int) int { return n + 1 }\n return inc\n}\n`, 'utf8');
|
|
60
|
+
const walk = run(dir);
|
|
61
|
+
const arrowNames = Object.keys(walk.occurrences).filter((n) => n.startsWith('<arrow:'));
|
|
62
|
+
expect(arrowNames.length).toBe(1);
|
|
63
|
+
// Closure creation should produce a 'creation' call-site so
|
|
64
|
+
// reachability flows from `maker` into the closure body.
|
|
65
|
+
const creations = walk.callSites.filter((c) => c.kind === 'creation');
|
|
66
|
+
expect(creations.length).toBeGreaterThan(0);
|
|
67
|
+
});
|
|
68
|
+
it('classifies visibility from leading-character case (Go convention)', () => {
|
|
69
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc Exported() {}\nfunc unexported() {}\n`, 'utf8');
|
|
70
|
+
const walk = run(dir);
|
|
71
|
+
expect(walk.occurrences.Exported?.[0]?.visibility).toBe('exported');
|
|
72
|
+
expect(walk.occurrences.unexported?.[0]?.visibility).toBe('module-local');
|
|
73
|
+
});
|
|
74
|
+
it('flags _test.go files as inTestFile', () => {
|
|
75
|
+
writeFileSync(join(dir, 'thing_test.go'), `package main\nfunc TestSomething() {}\n`, 'utf8');
|
|
76
|
+
const walk = run(dir);
|
|
77
|
+
expect(walk.occurrences.TestSomething?.[0]?.inTestFile).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
it('preserves string and raw-string literals when stripping comments', () => {
|
|
80
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc withStrings() string {\n _ = "a /* fake comment */ inside"\n r := \`another // not a comment\`\n _ = r\n return "ok"\n}\n`, 'utf8');
|
|
81
|
+
const walk = run(dir);
|
|
82
|
+
expect(Object.keys(walk.occurrences)).toContain('withStrings');
|
|
83
|
+
});
|
|
84
|
+
it('handles block comments without nesting (Go does not nest)', () => {
|
|
85
|
+
writeFileSync(join(dir, 'main.go'), `package main\n/* outer comment */\nfunc afterComment() int { return 1 }\n`, 'utf8');
|
|
86
|
+
const walk = run(dir);
|
|
87
|
+
expect(Object.keys(walk.occurrences)).toContain('afterComment');
|
|
88
|
+
});
|
|
89
|
+
it('records call_expression as call-site records', () => {
|
|
90
|
+
mkdirSync(join(dir, 'src'), { recursive: true });
|
|
91
|
+
writeFileSync(join(dir, 'src/main.go'), `package main\nfunc caller() { callee() }\nfunc callee() {}\n`, 'utf8');
|
|
92
|
+
const walk = run(dir);
|
|
93
|
+
const calls = walk.callSites.filter((c) => c.kind === 'call');
|
|
94
|
+
expect(calls.length).toBeGreaterThanOrEqual(1);
|
|
95
|
+
});
|
|
96
|
+
it('preserves escape sequences inside interpreted string literals', () => {
|
|
97
|
+
// `"\\\""` — an escaped quote. The interpreted-string scanner has
|
|
98
|
+
// an escape branch (`\\` + next char).
|
|
99
|
+
writeFileSync(join(dir, 'main.go'), String.raw `package main` + '\nfunc esc() string { return ' + String.raw `"a\"b"` + ' }\n', 'utf8');
|
|
100
|
+
const walk = run(dir);
|
|
101
|
+
expect(walk.occurrences.esc).toBeDefined();
|
|
102
|
+
});
|
|
103
|
+
it('preserves rune literals — simple and escaped', () => {
|
|
104
|
+
// `'a'` exercises the unescape path; `'\\n'` exercises the escape
|
|
105
|
+
// branch in consumeRuneLiteral.
|
|
106
|
+
writeFileSync(join(dir, 'main.go'), "package main\nfunc a() rune { return 'a' }\nfunc b() rune { return '\\n' }\n", 'utf8');
|
|
107
|
+
const walk = run(dir);
|
|
108
|
+
expect(walk.occurrences.a).toBeDefined();
|
|
109
|
+
expect(walk.occurrences.b).toBeDefined();
|
|
110
|
+
});
|
|
111
|
+
it('classifies *_generated.go files as definedInGenerated', () => {
|
|
112
|
+
writeFileSync(join(dir, 'foo_generated.go'), `package main\nfunc Gen() {}\n`, 'utf8');
|
|
113
|
+
const walk = run(dir);
|
|
114
|
+
expect(walk.occurrences.Gen?.[0]?.definedInGenerated).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
it('classifies *.gen.go files as definedInGenerated', () => {
|
|
117
|
+
writeFileSync(join(dir, 'queries.gen.go'), `package main\nfunc GenQ() {}\n`, 'utf8');
|
|
118
|
+
const walk = run(dir);
|
|
119
|
+
expect(walk.occurrences.GenQ?.[0]?.definedInGenerated).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it('classifies .pb.go files as definedInGenerated', () => {
|
|
122
|
+
writeFileSync(join(dir, 'proto.pb.go'), `package main\nfunc ProtoFunc() {}\n`, 'utf8');
|
|
123
|
+
const walk = run(dir);
|
|
124
|
+
expect(walk.occurrences.ProtoFunc?.[0]?.definedInGenerated).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
it('emits a synthetic <module-init> per file', () => {
|
|
127
|
+
writeFileSync(join(dir, 'main.go'), `package main\nimport "fmt"\nvar greeting = "hi"\nfunc m() { fmt.Println(greeting) }\n`, 'utf8');
|
|
128
|
+
const walk = run(dir);
|
|
129
|
+
const moduleInits = Object.keys(walk.occurrences).filter((n) => n.startsWith('<module-init:'));
|
|
130
|
+
expect(moduleInits.length).toBe(1);
|
|
131
|
+
const occ = walk.occurrences[moduleInits[0]]?.[0];
|
|
132
|
+
expect(occ?.kind).toBe('module-init');
|
|
133
|
+
expect(occ?.visibility).toBe('module-local');
|
|
134
|
+
});
|
|
135
|
+
it('emits multi-name parameter declaration (`func f(a, b int)`)', () => {
|
|
136
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc add(a, b int) int { return a + b }\n`, 'utf8');
|
|
137
|
+
const walk = run(dir);
|
|
138
|
+
const params = walk.occurrences.add?.[0]?.params;
|
|
139
|
+
expect(params?.map((p) => p.name)).toEqual(['a', 'b']);
|
|
140
|
+
});
|
|
141
|
+
it('emits variadic parameter as rest=true', () => {
|
|
142
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc sum(xs ...int) int { return 0 }\n`, 'utf8');
|
|
143
|
+
const walk = run(dir);
|
|
144
|
+
const params = walk.occurrences.sum?.[0]?.params;
|
|
145
|
+
expect(params?.[0]?.rest).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
it('strips // line comments and /* */ block comments inside function bodies', () => {
|
|
148
|
+
// Body contains both `//` line and `/* */` block comments to
|
|
149
|
+
// exercise stripGoComments' line+block branches during body
|
|
150
|
+
// normalization.
|
|
151
|
+
writeFileSync(join(dir, 'main.go'), `package main\nfunc withComments() int {\n // explanation\n /* block */\n return 1\n}\n`, 'utf8');
|
|
152
|
+
const walk = run(dir);
|
|
153
|
+
expect(walk.occurrences.withComments).toBeDefined();
|
|
154
|
+
});
|
|
155
|
+
it('handles generic receiver types (Foo[T])', () => {
|
|
156
|
+
writeFileSync(join(dir, 'main.go'), `package main\ntype Box[T any] struct { v T }\nfunc (b Box[T]) Get() T { return b.v }\n`, 'utf8');
|
|
157
|
+
const walk = run(dir);
|
|
158
|
+
const get = walk.occurrences.Get?.[0];
|
|
159
|
+
expect(get?.kind).toBe('method');
|
|
160
|
+
expect(get?.enclosingClass).toBe('Box');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=walk.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.test.js","sourceRoot":"","sources":["../../src/__tests__/walk.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,SAAS,GAAG,CAAC,GAAW;IACtB,MAAM,SAAS,GAAG,cAAc,CAAC,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC;QACzC,aAAa,EAAE,SAAS,CAAC,aAAa;QACtC,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,eAAe,EAAE,SAAS,CAAC,eAAe;QAC1C,cAAc,EAAE,OAAO;KACxB,CAAC,CAAC;IACH,OAAO,cAAc,CAAC,WAAW,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,SAAS,CAAC,aAAa;QACtC,KAAK,EAAE,SAAS,CAAC,KAAK;KACvB,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,GAAW,CAAC;IAEhB,UAAU,CAAC,GAAG,EAAE;QACd,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,kDAAkD,EAAE,MAAM,CAAC,CAAC;QAChG,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;QACvC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,wEAAwE,EACxE,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;QACjC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,yEAAyE,EACzE,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;QACjC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,8GAA8G,EAC9G,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QACxF,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,4DAA4D;QAC5D,yDAAyD;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACtE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,0DAA0D,EAC1D,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,yCAAyC,EAAE,MAAM,CAAC,CAAC;QAC7F,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,0JAA0J,EAC1J,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,2EAA2E,EAC3E,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EACxB,8DAA8D,EAC9D,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,kEAAkE;QAClE,uCAAuC;QACvC,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,MAAM,CAAC,GAAG,CAAA,cAAc,GAAG,+BAA+B,GAAG,MAAM,CAAC,GAAG,CAAA,QAAQ,GAAG,MAAM,EACxF,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,kEAAkE;QAClE,gCAAgC;QAChC,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,8EAA8E,EAC9E,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,+BAA+B,EAAE,MAAM,CAAC,CAAC;QACtF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,gCAAgC,EAAE,MAAM,CAAC,CAAC;QACrF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,qCAAqC,EAAE,MAAM,CAAC,CAAC;QACvF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,uFAAuF,EACvF,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;QAC/F,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,yDAAyD,EACzD,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QACjD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,sDAAsD,EACtD,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QACjD,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,6DAA6D;QAC7D,4DAA4D;QAC5D,iBAAiB;QACjB,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,iGAAiG,EACjG,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EACpB,wFAAwF,EACxF,MAAM,CACP,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Body normalization + SHA-256 digest for Go.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `walk.ts` to keep that module focused on AST traversal
|
|
5
|
+
* and occurrence construction. The body-digest defines the catalog's
|
|
6
|
+
* `bodyHash` contract: walk produces it; resolve consumes it. Splitting
|
|
7
|
+
* is safe because no other code under graph-go reaches into these
|
|
8
|
+
* helpers — they are pure functions over source text.
|
|
9
|
+
*
|
|
10
|
+
* Normalization (consistent across language adapters):
|
|
11
|
+
*
|
|
12
|
+
* 1. Strip line + block comments (preserving string + rune literals
|
|
13
|
+
* so quoted comment-like text survives).
|
|
14
|
+
* 2. Collapse runs of whitespace to a single space, trim.
|
|
15
|
+
* 3. SHA-256.
|
|
16
|
+
*/
|
|
17
|
+
import { type BodyDigest } from '@opensip-cli/graph';
|
|
18
|
+
export declare function digestGoBody(text: string): BodyDigest;
|
|
19
|
+
export declare const digestSyntheticBody: typeof digestGoBody;
|
|
20
|
+
//# sourceMappingURL=body-digest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-digest.d.ts","sourceRoot":"","sources":["../src/body-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAiC,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGpF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAErD;AAID,eAAO,MAAM,mBAAmB,qBAAe,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Body normalization + SHA-256 digest for Go.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `walk.ts` to keep that module focused on AST traversal
|
|
5
|
+
* and occurrence construction. The body-digest defines the catalog's
|
|
6
|
+
* `bodyHash` contract: walk produces it; resolve consumes it. Splitting
|
|
7
|
+
* is safe because no other code under graph-go reaches into these
|
|
8
|
+
* helpers — they are pure functions over source text.
|
|
9
|
+
*
|
|
10
|
+
* Normalization (consistent across language adapters):
|
|
11
|
+
*
|
|
12
|
+
* 1. Strip line + block comments (preserving string + rune literals
|
|
13
|
+
* so quoted comment-like text survives).
|
|
14
|
+
* 2. Collapse runs of whitespace to a single space, trim.
|
|
15
|
+
* 3. SHA-256.
|
|
16
|
+
*/
|
|
17
|
+
import { hashBody, normalizeWhitespace } from '@opensip-cli/graph';
|
|
18
|
+
import { skipBlockComment, skipToEndOfLine } from '@opensip-cli/graph-adapter-common';
|
|
19
|
+
export function digestGoBody(text) {
|
|
20
|
+
return hashBody(normalizeWhitespace(stripGoComments(text)));
|
|
21
|
+
}
|
|
22
|
+
// Synthetic bodies (module-init) use the same normalization as real
|
|
23
|
+
// bodies; alias for self-documenting call sites.
|
|
24
|
+
export const digestSyntheticBody = digestGoBody;
|
|
25
|
+
/**
|
|
26
|
+
* Strip Go line comments (// to end of line) and block comments
|
|
27
|
+
* (slash-star ... star-slash). Go does NOT support nested block
|
|
28
|
+
* comments. Preserve string literals (both interpreted `"…"` and raw
|
|
29
|
+
* backtick `…`); preserve rune literals.
|
|
30
|
+
*/
|
|
31
|
+
function stripGoComments(text) {
|
|
32
|
+
let out = '';
|
|
33
|
+
let i = 0;
|
|
34
|
+
while (i < text.length) {
|
|
35
|
+
const next2 = text.slice(i, i + 2);
|
|
36
|
+
if (next2 === '//') {
|
|
37
|
+
i = skipToEndOfLine(text, i);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (next2 === '/*') {
|
|
41
|
+
i = skipBlockComment(text, i + 2);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const c = text[i];
|
|
45
|
+
if (c === '"') {
|
|
46
|
+
const block = consumeInterpretedString(text, i);
|
|
47
|
+
out += block.text;
|
|
48
|
+
i = block.index;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (c === '`') {
|
|
52
|
+
const block = consumeRawString(text, i);
|
|
53
|
+
out += block.text;
|
|
54
|
+
i = block.index;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (c === "'") {
|
|
58
|
+
const block = consumeRuneLiteral(text, i);
|
|
59
|
+
out += block.text;
|
|
60
|
+
i = block.index;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
out += c;
|
|
64
|
+
i++;
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function consumeInterpretedString(text, start) {
|
|
69
|
+
let i = start + 1;
|
|
70
|
+
let buf = '"';
|
|
71
|
+
while (i < text.length) {
|
|
72
|
+
if (text[i] === '\\' && i + 1 < text.length) {
|
|
73
|
+
buf += text.slice(i, i + 2);
|
|
74
|
+
i += 2;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (text[i] === '"') {
|
|
78
|
+
buf += '"';
|
|
79
|
+
i++;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
/* v8 ignore next */
|
|
83
|
+
if (text[i] === '\n')
|
|
84
|
+
break;
|
|
85
|
+
buf += text[i];
|
|
86
|
+
i++;
|
|
87
|
+
}
|
|
88
|
+
return { text: buf, index: i };
|
|
89
|
+
}
|
|
90
|
+
function consumeRawString(text, start) {
|
|
91
|
+
// Raw strings span across newlines and have no escape sequences.
|
|
92
|
+
let i = start + 1;
|
|
93
|
+
let buf = '`';
|
|
94
|
+
while (i < text.length) {
|
|
95
|
+
if (text[i] === '`') {
|
|
96
|
+
buf += '`';
|
|
97
|
+
i++;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
buf += text[i];
|
|
101
|
+
i++;
|
|
102
|
+
}
|
|
103
|
+
return { text: buf, index: i };
|
|
104
|
+
}
|
|
105
|
+
function consumeRuneLiteral(text, start) {
|
|
106
|
+
// A rune literal is a `'`, then either a single char or an escape
|
|
107
|
+
// sequence (`\n`, `A`, `\xff`), then a closing `'`. Walk to the
|
|
108
|
+
// next unescaped `'` within a small window.
|
|
109
|
+
let i = start + 1;
|
|
110
|
+
let buf = "'";
|
|
111
|
+
let escape = false;
|
|
112
|
+
while (i < text.length) {
|
|
113
|
+
const c = text[i];
|
|
114
|
+
if (escape) {
|
|
115
|
+
buf += c;
|
|
116
|
+
escape = false;
|
|
117
|
+
i++;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (c === '\\') {
|
|
121
|
+
buf += c;
|
|
122
|
+
escape = true;
|
|
123
|
+
i++;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (c === "'") {
|
|
127
|
+
buf += c;
|
|
128
|
+
i++;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
/* v8 ignore next */
|
|
132
|
+
if (c === '\n')
|
|
133
|
+
break;
|
|
134
|
+
buf += c;
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
return { text: buf, index: i };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=body-digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-digest.js","sourceRoot":"","sources":["../src/body-digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go cacheKey implementation.
|
|
3
|
+
*
|
|
4
|
+
* Produces `go-${goSumHash || goModHash || 'no-config'}`.
|
|
5
|
+
*
|
|
6
|
+
* Prefers go.sum over go.mod when both are present — go.sum holds the
|
|
7
|
+
* resolved dependency tree (with hashes), so changing a dep version
|
|
8
|
+
* reliably flips the key. go.mod (the manifest) is the fallback when
|
|
9
|
+
* go.sum isn't checked in (rare; Go conventionally commits it). The
|
|
10
|
+
* precedence is encoded in `discover.ts`'s config-candidate list; this
|
|
11
|
+
* module just fingerprints whichever anchor discover picked.
|
|
12
|
+
*
|
|
13
|
+
* Per contract invariant I-6: pure function of `(config content)`.
|
|
14
|
+
* Per I-8: emits `go-`, distinct from `rs-` and `py-`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const cacheKey: (input: import("@opensip-cli/graph").CacheKeyInput) => string;
|
|
17
|
+
//# sourceMappingURL=cache-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-key.d.ts","sourceRoot":"","sources":["../src/cache-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,eAAO,MAAM,QAAQ,+DAAuC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go cacheKey implementation.
|
|
3
|
+
*
|
|
4
|
+
* Produces `go-${goSumHash || goModHash || 'no-config'}`.
|
|
5
|
+
*
|
|
6
|
+
* Prefers go.sum over go.mod when both are present — go.sum holds the
|
|
7
|
+
* resolved dependency tree (with hashes), so changing a dep version
|
|
8
|
+
* reliably flips the key. go.mod (the manifest) is the fallback when
|
|
9
|
+
* go.sum isn't checked in (rare; Go conventionally commits it). The
|
|
10
|
+
* precedence is encoded in `discover.ts`'s config-candidate list; this
|
|
11
|
+
* module just fingerprints whichever anchor discover picked.
|
|
12
|
+
*
|
|
13
|
+
* Per contract invariant I-6: pure function of `(config content)`.
|
|
14
|
+
* Per I-8: emits `go-`, distinct from `rs-` and `py-`.
|
|
15
|
+
*/
|
|
16
|
+
import { makeConfigCacheKey } from '@opensip-cli/graph-adapter-common';
|
|
17
|
+
export const cacheKey = makeConfigCacheKey({ prefix: 'go' });
|
|
18
|
+
//# sourceMappingURL=cache-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-key.js","sourceRoot":"","sources":["../src/cache-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,CAAC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC"}
|