@vibgrate/cli 2026.728.3 → 2026.728.4
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/dist/baseline-QD4HVNVJ.js +8 -0
- package/dist/{baseline-PPZJBYAJ.js.map → baseline-QD4HVNVJ.js.map} +1 -1
- package/dist/{chunk-A2IYFNCQ.js → chunk-2ZHWF7C6.js} +227 -19
- package/dist/chunk-2ZHWF7C6.js.map +1 -0
- package/dist/{chunk-UZJS7GMK.js → chunk-3LSG7Z4I.js} +10 -6
- package/dist/chunk-3LSG7Z4I.js.map +1 -0
- package/dist/{chunk-R2QNFXE5.js → chunk-DBOT2ELH.js} +3 -3
- package/dist/{chunk-R2QNFXE5.js.map → chunk-DBOT2ELH.js.map} +1 -1
- package/dist/{chunk-6UK6QPTR.js → chunk-EETK7S43.js} +137 -34
- package/dist/chunk-EETK7S43.js.map +1 -0
- package/dist/{chunk-JRAGO6OB.js → chunk-EVWW3BPM.js} +4 -4
- package/dist/{chunk-JRAGO6OB.js.map → chunk-EVWW3BPM.js.map} +1 -1
- package/dist/chunk-G4HTI4ZM.js +1537 -0
- package/dist/chunk-G4HTI4ZM.js.map +1 -0
- package/dist/{chunk-VYGEOOLY.js → chunk-HY2RVURA.js} +3 -3
- package/dist/{chunk-VYGEOOLY.js.map → chunk-HY2RVURA.js.map} +1 -1
- package/dist/chunk-IPICO2RV.js +789 -0
- package/dist/chunk-IPICO2RV.js.map +1 -0
- package/dist/{chunk-6GRLZ4Z2.js → chunk-LYDH2PHN.js} +8 -8
- package/dist/{chunk-6GRLZ4Z2.js.map → chunk-LYDH2PHN.js.map} +1 -1
- package/dist/{chunk-6UQMXIAG.js → chunk-OWSFZQOP.js} +62 -12
- package/dist/chunk-OWSFZQOP.js.map +1 -0
- package/dist/{chunk-WH2N22S3.js → chunk-PRGCCW7D.js} +4 -4
- package/dist/{chunk-WH2N22S3.js.map → chunk-PRGCCW7D.js.map} +1 -1
- package/dist/{chunk-3BIRGSRS.js → chunk-RCBMY7CR.js} +11 -11
- package/dist/{chunk-3BIRGSRS.js.map → chunk-RCBMY7CR.js.map} +1 -1
- package/dist/{chunk-OSD546W7.js → chunk-REIGWTTH.js} +5 -3
- package/dist/chunk-REIGWTTH.js.map +1 -0
- package/dist/{chunk-B3YUO3NW.js → chunk-RYNAK4LK.js} +3 -3
- package/dist/{chunk-B3YUO3NW.js.map → chunk-RYNAK4LK.js.map} +1 -1
- package/dist/{chunk-YF43FOPP.js → chunk-RZEXHDCF.js} +33 -14
- package/dist/chunk-RZEXHDCF.js.map +1 -0
- package/dist/chunk-SA4BMEU6.js +2184 -0
- package/dist/chunk-SA4BMEU6.js.map +1 -0
- package/dist/{chunk-HK3AWUXH.js → chunk-TCJTQGAO.js} +3 -3
- package/dist/{chunk-HK3AWUXH.js.map → chunk-TCJTQGAO.js.map} +1 -1
- package/dist/{chunk-ZBTY6VV4.js → chunk-US2DAKCM.js} +15 -5
- package/dist/chunk-US2DAKCM.js.map +1 -0
- package/dist/{chunk-ON25BX6T.js → chunk-UTNNGKKX.js} +3 -3
- package/dist/{chunk-ON25BX6T.js.map → chunk-UTNNGKKX.js.map} +1 -1
- package/dist/chunk-WDJNUC6V.js +3059 -0
- package/dist/chunk-WDJNUC6V.js.map +1 -0
- package/dist/{chunk-SZSNPXSW.js → chunk-WHJMS7XC.js} +3 -3
- package/dist/{chunk-SZSNPXSW.js.map → chunk-WHJMS7XC.js.map} +1 -1
- package/dist/chunk-Z6ZWNWWR.js +30 -0
- package/dist/{chunk-DGUM43GV.js.map → chunk-Z6ZWNWWR.js.map} +1 -1
- package/dist/{chunk-VI4ITXHQ.js → chunk-ZU7VD4QL.js} +7 -6
- package/dist/chunk-ZU7VD4QL.js.map +1 -0
- package/dist/cli.js +158 -71
- package/dist/cli.js.map +1 -1
- package/dist/{execution-env-ZU45JZ4G.js → execution-env-4MS5AYAN.js} +3 -3
- package/dist/{execution-env-ZU45JZ4G.js.map → execution-env-4MS5AYAN.js.map} +1 -1
- package/dist/{federation-SZWZIFZ7.js → federation-MDQPO3PW.js} +3 -3
- package/dist/{federation-SZWZIFZ7.js.map → federation-MDQPO3PW.js.map} +1 -1
- package/dist/{fs-O5IQYXHO.js → fs-4G5A65KS.js} +3 -3
- package/dist/fs-4G5A65KS.js.map +1 -0
- package/dist/{fs-B5HZ2MIU.js → fs-6JKZNQ3U.js} +3 -3
- package/dist/fs-6JKZNQ3U.js.map +1 -0
- package/dist/{git-ref-XDXB6JP5.js → git-ref-RSRAN4OH.js} +3 -3
- package/dist/{git-ref-XDXB6JP5.js.map → git-ref-RSRAN4OH.js.map} +1 -1
- package/dist/{graph-backend-UTOL3SHE.js → graph-backend-GBL33GMW.js} +5 -5
- package/dist/{graph-backend-UTOL3SHE.js.map → graph-backend-GBL33GMW.js.map} +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +12 -10
- package/dist/index.js.map +1 -1
- package/dist/{interactive-OCWQ326U.js → interactive-32LSIBRG.js} +45 -24
- package/dist/interactive-32LSIBRG.js.map +1 -0
- package/dist/{llm-host-XYBT4267.js → llm-host-5RE34322.js} +3 -3
- package/dist/{llm-host-XYBT4267.js.map → llm-host-5RE34322.js.map} +1 -1
- package/dist/load-SEFJA3M5.js +8 -0
- package/dist/{load-QPOWQD7C.js.map → load-SEFJA3M5.js.map} +1 -1
- package/dist/local-runtime-2ED33KK6.js +6 -0
- package/dist/{local-runtime-5O2NN3GA.js.map → local-runtime-2ED33KK6.js.map} +1 -1
- package/dist/mcp-tools-KAJS34TN.js +4 -0
- package/dist/{mcp-tools-I7JK3S2M.js.map → mcp-tools-KAJS34TN.js.map} +1 -1
- package/dist/{model-execution-profile-TFBKCNJG.js → model-execution-profile-ELWF3Z6H.js} +3 -3
- package/dist/{model-execution-profile-TFBKCNJG.js.map → model-execution-profile-ELWF3Z6H.js.map} +1 -1
- package/dist/model-manager-GJ2YSTSK.js +10 -0
- package/dist/{model-manager-LB54VSV7.js.map → model-manager-GJ2YSTSK.js.map} +1 -1
- package/dist/{model-orchestrator-4M5FG6MN.js → model-orchestrator-LHYPJBFH.js} +3 -3
- package/dist/{model-orchestrator-4M5FG6MN.js.map → model-orchestrator-LHYPJBFH.js.map} +1 -1
- package/dist/parse-worker.js +2 -2
- package/dist/{paths-2RAH3GME.js → paths-62AKTFSR.js} +3 -3
- package/dist/{paths-2RAH3GME.js.map → paths-62AKTFSR.js.map} +1 -1
- package/dist/{resolve-gguf-4AFRN4CP.js → resolve-gguf-SDIYGGI6.js} +3 -3
- package/dist/{resolve-gguf-4AFRN4CP.js.map → resolve-gguf-SDIYGGI6.js.map} +1 -1
- package/dist/{runtime-session-EJQZXANB.js → runtime-session-4IACVDSY.js} +7 -7
- package/dist/{runtime-session-EJQZXANB.js.map → runtime-session-4IACVDSY.js.map} +1 -1
- package/dist/session-2JT4AUZT.js +13 -0
- package/dist/{session-ZJGENHKX.js.map → session-2JT4AUZT.js.map} +1 -1
- package/dist/session-store-O4XPXKOV.js +4 -0
- package/dist/{session-store-WFBX7HXL.js.map → session-store-O4XPXKOV.js.map} +1 -1
- package/dist/{sql-extract-JELDZA6W.js → sql-extract-6UJOLJDL.js} +3 -3
- package/dist/{sql-extract-JELDZA6W.js.map → sql-extract-6UJOLJDL.js.map} +1 -1
- package/dist/stream-json-Y45JBNYP.js +112 -0
- package/dist/stream-json-Y45JBNYP.js.map +1 -0
- package/dist/ui-K7D3BCHD.js +5 -0
- package/dist/ui-K7D3BCHD.js.map +1 -0
- package/dist/vg-mcp-bridge-E4SJFL7Q.js +75 -0
- package/dist/vg-mcp-bridge-E4SJFL7Q.js.map +1 -0
- package/dist/{vgd-3MHSB4KA.js → vgd-KDQFS33M.js} +6 -6
- package/dist/vgd-KDQFS33M.js.map +1 -0
- package/package.json +1 -1
- package/dist/baseline-PPZJBYAJ.js +0 -8
- package/dist/chunk-57QU36P6.js +0 -5645
- package/dist/chunk-57QU36P6.js.map +0 -1
- package/dist/chunk-6AXHLQBV.js +0 -1892
- package/dist/chunk-6AXHLQBV.js.map +0 -1
- package/dist/chunk-6UK6QPTR.js.map +0 -1
- package/dist/chunk-6UQMXIAG.js.map +0 -1
- package/dist/chunk-A2IYFNCQ.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -10
- package/dist/chunk-OSD546W7.js.map +0 -1
- package/dist/chunk-UZJS7GMK.js.map +0 -1
- package/dist/chunk-VI4ITXHQ.js.map +0 -1
- package/dist/chunk-YF43FOPP.js.map +0 -1
- package/dist/chunk-ZBTY6VV4.js.map +0 -1
- package/dist/fs-B5HZ2MIU.js.map +0 -1
- package/dist/fs-O5IQYXHO.js.map +0 -1
- package/dist/interactive-OCWQ326U.js.map +0 -1
- package/dist/load-QPOWQD7C.js +0 -8
- package/dist/local-runtime-5O2NN3GA.js +0 -5
- package/dist/mcp-tools-I7JK3S2M.js +0 -4
- package/dist/model-manager-LB54VSV7.js +0 -10
- package/dist/session-ZJGENHKX.js +0 -13
- package/dist/session-store-WFBX7HXL.js +0 -4
- package/dist/stream-json-Z5KC2DM3.js +0 -78
- package/dist/stream-json-Z5KC2DM3.js.map +0 -1
- package/dist/ui-Q6DJ3GCU.js +0 -5
- package/dist/ui-Q6DJ3GCU.js.map +0 -1
- package/dist/vgd-3MHSB4KA.js.map +0 -1
|
@@ -0,0 +1,789 @@
|
|
|
1
|
+
import { shortId, canonicalize } from './chunk-JFGYT6BI.js';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
var JS_TS_EXT = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".vue", ".svelte", ".astro"];
|
|
6
|
+
var OTHER_EXT = [
|
|
7
|
+
".py",
|
|
8
|
+
".pyi",
|
|
9
|
+
".go",
|
|
10
|
+
".rs",
|
|
11
|
+
".rb",
|
|
12
|
+
".java",
|
|
13
|
+
".cs",
|
|
14
|
+
".php",
|
|
15
|
+
".kt",
|
|
16
|
+
".kts",
|
|
17
|
+
".swift",
|
|
18
|
+
".scala",
|
|
19
|
+
".sc",
|
|
20
|
+
".dart",
|
|
21
|
+
".lua",
|
|
22
|
+
".ex",
|
|
23
|
+
".exs",
|
|
24
|
+
".sh",
|
|
25
|
+
".bash",
|
|
26
|
+
".zig",
|
|
27
|
+
".c",
|
|
28
|
+
".cpp",
|
|
29
|
+
".cc",
|
|
30
|
+
".cxx",
|
|
31
|
+
".hpp",
|
|
32
|
+
".hh",
|
|
33
|
+
".hxx",
|
|
34
|
+
".h",
|
|
35
|
+
".m",
|
|
36
|
+
".mm",
|
|
37
|
+
".ml",
|
|
38
|
+
".mli",
|
|
39
|
+
".res",
|
|
40
|
+
".sol"
|
|
41
|
+
];
|
|
42
|
+
var EXT_GROUPS = {
|
|
43
|
+
".py": [".py", ".pyi"],
|
|
44
|
+
".pyi": [".py", ".pyi"],
|
|
45
|
+
".java": [".java"],
|
|
46
|
+
".cs": [".cs"],
|
|
47
|
+
".go": [".go"],
|
|
48
|
+
".rs": [".rs"],
|
|
49
|
+
".rb": [".rb"]
|
|
50
|
+
};
|
|
51
|
+
for (const e of JS_TS_EXT) EXT_GROUPS[e] = JS_TS_EXT;
|
|
52
|
+
var CPP_EXT = [".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h"];
|
|
53
|
+
Object.assign(EXT_GROUPS, {
|
|
54
|
+
".php": [".php"],
|
|
55
|
+
".kt": [".kt", ".kts"],
|
|
56
|
+
".kts": [".kt", ".kts"],
|
|
57
|
+
".swift": [".swift"],
|
|
58
|
+
".scala": [".scala", ".sc"],
|
|
59
|
+
".sc": [".scala", ".sc"],
|
|
60
|
+
".dart": [".dart"],
|
|
61
|
+
".lua": [".lua"],
|
|
62
|
+
".ex": [".ex", ".exs"],
|
|
63
|
+
".exs": [".ex", ".exs"],
|
|
64
|
+
".sh": [".sh", ".bash"],
|
|
65
|
+
".bash": [".sh", ".bash"],
|
|
66
|
+
".zig": [".zig"],
|
|
67
|
+
".c": [".c", ".h"],
|
|
68
|
+
".cpp": CPP_EXT,
|
|
69
|
+
".cc": CPP_EXT,
|
|
70
|
+
".cxx": CPP_EXT,
|
|
71
|
+
".hpp": CPP_EXT,
|
|
72
|
+
".hh": CPP_EXT,
|
|
73
|
+
".hxx": CPP_EXT,
|
|
74
|
+
".h": [...CPP_EXT, ".c"],
|
|
75
|
+
// ObjC #imports headers; ObjC++ additionally reaches C++ headers.
|
|
76
|
+
".m": [".h", ".m", ".mm"],
|
|
77
|
+
".mm": [".h", ".m", ".mm", ...CPP_EXT],
|
|
78
|
+
".ml": [".ml", ".mli"],
|
|
79
|
+
".mli": [".ml", ".mli"],
|
|
80
|
+
".res": [".res"],
|
|
81
|
+
".sol": [".sol"],
|
|
82
|
+
// Template containers: ERB fragments are Ruby; HTML/EJS script is JS.
|
|
83
|
+
".erb": [".rb", ".erb"],
|
|
84
|
+
".html": JS_TS_EXT,
|
|
85
|
+
".htm": JS_TS_EXT,
|
|
86
|
+
".ejs": JS_TS_EXT
|
|
87
|
+
});
|
|
88
|
+
function buildModuleResolver(root, relSet) {
|
|
89
|
+
const probe = makeProbe(relSet);
|
|
90
|
+
const suffixIndex = buildSuffixIndex(relSet);
|
|
91
|
+
const tsPaths = loadTsconfigPaths(root);
|
|
92
|
+
const workspaces = loadWorkspacePackages(root);
|
|
93
|
+
function resolveAlias(source) {
|
|
94
|
+
if (!tsPaths) return null;
|
|
95
|
+
for (const [pattern, targets] of tsPaths.paths) {
|
|
96
|
+
const m = matchPattern(pattern, source);
|
|
97
|
+
if (m === null) continue;
|
|
98
|
+
for (const target of targets) {
|
|
99
|
+
const sub = target.replace("*", m);
|
|
100
|
+
const rel = posixJoin(tsPaths.baseUrlRel, sub);
|
|
101
|
+
const hit = probe(rel);
|
|
102
|
+
if (hit) return hit;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
function resolveWorkspace(source) {
|
|
108
|
+
if (!workspaces.size) return null;
|
|
109
|
+
let best = null;
|
|
110
|
+
for (const [name, dirRel] of workspaces) {
|
|
111
|
+
if (source === name || source.startsWith(`${name}/`)) {
|
|
112
|
+
const rest = source === name ? "" : source.slice(name.length + 1);
|
|
113
|
+
if (!best || name.length > best.dirRel.length) best = { dirRel, rest };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!best) return null;
|
|
117
|
+
const base = best.rest ? posixJoin(best.dirRel, best.rest) : best.dirRel;
|
|
118
|
+
return probe(base) ?? probe(posixJoin(base, "src/index")) ?? probe(posixJoin(base, "index"));
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
resolve(fromRel, source) {
|
|
122
|
+
if (source.includes("\\")) source = source.split("\\").join(".");
|
|
123
|
+
if (source.startsWith("./") || source.startsWith("../")) {
|
|
124
|
+
return probe(posixJoin(path.posix.dirname(fromRel), source));
|
|
125
|
+
}
|
|
126
|
+
if (/\.[A-Za-z0-9]+$/.test(source) && !source.startsWith("<")) {
|
|
127
|
+
const hit = probe(posixJoin(path.posix.dirname(fromRel), source));
|
|
128
|
+
if (hit) return hit;
|
|
129
|
+
}
|
|
130
|
+
if (source.startsWith(".")) {
|
|
131
|
+
return resolvePyRelative(probe, fromRel, source);
|
|
132
|
+
}
|
|
133
|
+
return resolveAlias(source) ?? resolveWorkspace(source) ?? resolveSuffix(suffixIndex, fromRel, source) ?? resolveDotted(probe, source);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function buildSuffixIndex(relSet) {
|
|
138
|
+
const byLast = /* @__PURE__ */ new Map();
|
|
139
|
+
for (const rel of relSet) {
|
|
140
|
+
const dot = rel.lastIndexOf(".");
|
|
141
|
+
if (dot < 0) continue;
|
|
142
|
+
const ext = rel.slice(dot);
|
|
143
|
+
if (!EXT_GROUPS[ext]) continue;
|
|
144
|
+
let key = rel.slice(0, dot);
|
|
145
|
+
const base = key.slice(key.lastIndexOf("/") + 1);
|
|
146
|
+
if (base === "__init__" || base === "index") {
|
|
147
|
+
key = key.slice(0, Math.max(0, key.length - base.length - 1));
|
|
148
|
+
}
|
|
149
|
+
if (!key) continue;
|
|
150
|
+
const last = key.slice(key.lastIndexOf("/") + 1);
|
|
151
|
+
const list = byLast.get(last);
|
|
152
|
+
if (list) list.push({ rel, key, ext });
|
|
153
|
+
else byLast.set(last, [{ rel, key, ext }]);
|
|
154
|
+
}
|
|
155
|
+
return byLast;
|
|
156
|
+
}
|
|
157
|
+
function resolveSuffix(index, fromRel, source) {
|
|
158
|
+
if (!/^[A-Za-z_][\w.]*$/.test(source) || !source.includes(".")) return null;
|
|
159
|
+
const fromDot = fromRel.lastIndexOf(".");
|
|
160
|
+
const fromExt = fromDot >= 0 ? fromRel.slice(fromDot) : "";
|
|
161
|
+
const allowed = EXT_GROUPS[fromExt];
|
|
162
|
+
if (!allowed) return null;
|
|
163
|
+
const q = source.replace(/\./g, "/");
|
|
164
|
+
const last = q.slice(q.lastIndexOf("/") + 1);
|
|
165
|
+
const cands = index.get(last);
|
|
166
|
+
if (!cands) return null;
|
|
167
|
+
const matches = cands.filter(
|
|
168
|
+
(c) => allowed.includes(c.ext) && (c.key === q || c.key.endsWith("/" + q))
|
|
169
|
+
);
|
|
170
|
+
if (matches.length === 0) return null;
|
|
171
|
+
if (matches.length === 1) return matches[0].rel;
|
|
172
|
+
return pickClosest(matches, fromRel).rel;
|
|
173
|
+
}
|
|
174
|
+
function pickClosest(matches, fromRel) {
|
|
175
|
+
const fromSegs = fromRel.split("/");
|
|
176
|
+
const score = (rel) => {
|
|
177
|
+
const segs = rel.split("/");
|
|
178
|
+
let i = 0;
|
|
179
|
+
while (i < segs.length && i < fromSegs.length && segs[i] === fromSegs[i]) i++;
|
|
180
|
+
return i;
|
|
181
|
+
};
|
|
182
|
+
return [...matches].sort((a, b) => {
|
|
183
|
+
const d = score(b.rel) - score(a.rel);
|
|
184
|
+
if (d) return d;
|
|
185
|
+
if (a.rel.length !== b.rel.length) return a.rel.length - b.rel.length;
|
|
186
|
+
return a.rel < b.rel ? -1 : 1;
|
|
187
|
+
})[0];
|
|
188
|
+
}
|
|
189
|
+
function resolveDotted(probe, source) {
|
|
190
|
+
if (!/^[A-Za-z_][\w.]*$/.test(source) || !source.includes(".")) return null;
|
|
191
|
+
const slashed = source.replace(/\./g, "/");
|
|
192
|
+
return probe(slashed) ?? probe(posixJoin("src", slashed));
|
|
193
|
+
}
|
|
194
|
+
function resolvePyRelative(probe, fromRel, source) {
|
|
195
|
+
let dots = 0;
|
|
196
|
+
while (source[dots] === ".") dots++;
|
|
197
|
+
const rest = source.slice(dots);
|
|
198
|
+
let dir = path.posix.dirname(fromRel);
|
|
199
|
+
for (let i = 1; i < dots; i++) dir = path.posix.dirname(dir);
|
|
200
|
+
const sub = rest.replace(/\./g, "/");
|
|
201
|
+
return probe(sub ? posixJoin(dir, sub) : dir);
|
|
202
|
+
}
|
|
203
|
+
function relativeResolver(relSet) {
|
|
204
|
+
const probe = makeProbe(relSet);
|
|
205
|
+
return {
|
|
206
|
+
resolve(fromRel, source) {
|
|
207
|
+
if (source.startsWith(".")) return probe(posixJoin(path.posix.dirname(fromRel), source));
|
|
208
|
+
return resolveDotted(probe, source);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function makeProbe(relSet) {
|
|
213
|
+
return (base) => {
|
|
214
|
+
const norm = normalizeRel(base);
|
|
215
|
+
if (!norm) return null;
|
|
216
|
+
if (relSet.has(norm)) return norm;
|
|
217
|
+
for (const ext of JS_TS_EXT) if (relSet.has(norm + ext)) return norm + ext;
|
|
218
|
+
for (const ext of JS_TS_EXT) if (relSet.has(`${norm}/index${ext}`)) return `${norm}/index${ext}`;
|
|
219
|
+
for (const ext of OTHER_EXT) if (relSet.has(norm + ext)) return norm + ext;
|
|
220
|
+
if (relSet.has(`${norm}/__init__.py`)) return `${norm}/__init__.py`;
|
|
221
|
+
return null;
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function normalizeRel(p) {
|
|
225
|
+
const norm = path.posix.normalize(p);
|
|
226
|
+
const stripped = norm.startsWith("./") ? norm.slice(2) : norm;
|
|
227
|
+
return stripped.startsWith("..") ? "" : stripped;
|
|
228
|
+
}
|
|
229
|
+
function posixJoin(a, b) {
|
|
230
|
+
return path.posix.normalize(path.posix.join(a, b));
|
|
231
|
+
}
|
|
232
|
+
function matchPattern(pattern, source) {
|
|
233
|
+
const star = pattern.indexOf("*");
|
|
234
|
+
if (star === -1) return source === pattern ? "" : null;
|
|
235
|
+
const prefix = pattern.slice(0, star);
|
|
236
|
+
const suffix = pattern.slice(star + 1);
|
|
237
|
+
if (!source.startsWith(prefix) || !source.endsWith(suffix)) return null;
|
|
238
|
+
if (source.length < prefix.length + suffix.length) return null;
|
|
239
|
+
return source.slice(prefix.length, source.length - suffix.length);
|
|
240
|
+
}
|
|
241
|
+
function loadTsconfigPaths(root) {
|
|
242
|
+
for (const name of ["tsconfig.base.json", "tsconfig.json"]) {
|
|
243
|
+
const file = path.join(root, name);
|
|
244
|
+
if (fs.existsSync(file)) {
|
|
245
|
+
const merged = readTsconfigChain(root, file, /* @__PURE__ */ new Set());
|
|
246
|
+
if (merged && merged.paths.length) return merged;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
function readTsconfigChain(root, file, seen) {
|
|
252
|
+
if (seen.has(file) || seen.size > 6) return null;
|
|
253
|
+
seen.add(file);
|
|
254
|
+
let cfg;
|
|
255
|
+
try {
|
|
256
|
+
cfg = parseJsonc(fs.readFileSync(file, "utf8"));
|
|
257
|
+
} catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
const dir = path.dirname(file);
|
|
261
|
+
let base = { baseUrlRel: "", paths: [] };
|
|
262
|
+
if (cfg.extends && cfg.extends.startsWith(".")) {
|
|
263
|
+
const extPath = path.resolve(dir, cfg.extends.endsWith(".json") ? cfg.extends : `${cfg.extends}.json`);
|
|
264
|
+
if (fs.existsSync(extPath)) {
|
|
265
|
+
const inherited = readTsconfigChain(root, extPath, seen);
|
|
266
|
+
if (inherited) base = inherited;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const co = cfg.compilerOptions ?? {};
|
|
270
|
+
const baseUrlRel = co.baseUrl !== void 0 ? path.relative(root, path.resolve(dir, co.baseUrl)).split(path.sep).join("/") : base.baseUrlRel;
|
|
271
|
+
const paths = [...base.paths];
|
|
272
|
+
if (co.paths) for (const [k, v] of Object.entries(co.paths)) paths.push([k, v]);
|
|
273
|
+
return { baseUrlRel, paths };
|
|
274
|
+
}
|
|
275
|
+
function loadWorkspacePackages(root) {
|
|
276
|
+
const map = /* @__PURE__ */ new Map();
|
|
277
|
+
const globs = [];
|
|
278
|
+
const rootPkg = path.join(root, "package.json");
|
|
279
|
+
if (fs.existsSync(rootPkg)) {
|
|
280
|
+
try {
|
|
281
|
+
const pkg = JSON.parse(fs.readFileSync(rootPkg, "utf8"));
|
|
282
|
+
const ws = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages;
|
|
283
|
+
if (ws) globs.push(...ws);
|
|
284
|
+
} catch {
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const pnpmWs = path.join(root, "pnpm-workspace.yaml");
|
|
288
|
+
if (fs.existsSync(pnpmWs)) {
|
|
289
|
+
for (const line of fs.readFileSync(pnpmWs, "utf8").split("\n")) {
|
|
290
|
+
const m = /^\s*-\s*['"]?([^'"\n]+)['"]?\s*$/.exec(line);
|
|
291
|
+
if (m) globs.push(m[1].trim());
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
for (const dir of expandWorkspaceGlobs(root, globs)) {
|
|
295
|
+
const pj = path.join(dir, "package.json");
|
|
296
|
+
try {
|
|
297
|
+
const name = JSON.parse(fs.readFileSync(pj, "utf8")).name;
|
|
298
|
+
if (name) map.set(name, path.relative(root, dir).split(path.sep).join("/"));
|
|
299
|
+
} catch {
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return map;
|
|
303
|
+
}
|
|
304
|
+
function expandWorkspaceGlobs(root, globs) {
|
|
305
|
+
const out = /* @__PURE__ */ new Set();
|
|
306
|
+
for (const glob of globs) {
|
|
307
|
+
const clean = glob.replace(/\/\*\*$/, "").replace(/\/\*$/, "");
|
|
308
|
+
const baseDir = path.join(root, clean);
|
|
309
|
+
const recurse = glob.endsWith("**");
|
|
310
|
+
if (glob === clean) {
|
|
311
|
+
if (fs.existsSync(path.join(baseDir, "package.json"))) out.add(baseDir);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
collectPackageDirs(baseDir, recurse ? 4 : 1, out);
|
|
315
|
+
}
|
|
316
|
+
return [...out];
|
|
317
|
+
}
|
|
318
|
+
function collectPackageDirs(dir, depth, out) {
|
|
319
|
+
if (depth < 0) return;
|
|
320
|
+
let entries;
|
|
321
|
+
try {
|
|
322
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
323
|
+
} catch {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
for (const e of entries) {
|
|
327
|
+
if (!e.isDirectory() || e.name === "node_modules" || e.name.startsWith(".")) continue;
|
|
328
|
+
const child = path.join(dir, e.name);
|
|
329
|
+
if (fs.existsSync(path.join(child, "package.json"))) out.add(child);
|
|
330
|
+
else collectPackageDirs(child, depth - 1, out);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function parseJsonc(text) {
|
|
334
|
+
return JSON.parse(stripJsonc(text));
|
|
335
|
+
}
|
|
336
|
+
function stripJsonc(text) {
|
|
337
|
+
let out = "";
|
|
338
|
+
let inStr = false;
|
|
339
|
+
let strCh = "";
|
|
340
|
+
for (let i = 0; i < text.length; i++) {
|
|
341
|
+
const ch = text[i];
|
|
342
|
+
const next = text[i + 1];
|
|
343
|
+
if (inStr) {
|
|
344
|
+
out += ch;
|
|
345
|
+
if (ch === "\\") {
|
|
346
|
+
out += next ?? "";
|
|
347
|
+
i++;
|
|
348
|
+
} else if (ch === strCh) {
|
|
349
|
+
inStr = false;
|
|
350
|
+
}
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (ch === '"' || ch === "'") {
|
|
354
|
+
inStr = true;
|
|
355
|
+
strCh = ch;
|
|
356
|
+
out += ch;
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
if (ch === "/" && next === "/") {
|
|
360
|
+
while (i < text.length && text[i] !== "\n") i++;
|
|
361
|
+
out += "\n";
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (ch === "/" && next === "*") {
|
|
365
|
+
i += 2;
|
|
366
|
+
while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) i++;
|
|
367
|
+
i++;
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
out += ch;
|
|
371
|
+
}
|
|
372
|
+
return out.replace(/,(\s*[}\]])/g, "$1");
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/engine/ids.ts
|
|
376
|
+
function nodeId(parts) {
|
|
377
|
+
return shortId(
|
|
378
|
+
canonicalize({
|
|
379
|
+
t: "node",
|
|
380
|
+
kind: parts.kind,
|
|
381
|
+
qn: parts.qualifiedName,
|
|
382
|
+
file: parts.file,
|
|
383
|
+
sig: parts.signature ?? ""
|
|
384
|
+
})
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
function edgeId(kind, src, dst) {
|
|
388
|
+
return shortId(canonicalize({ t: "edge", kind, src, dst }));
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/engine/tests.ts
|
|
392
|
+
function isTestFile(rel) {
|
|
393
|
+
const lower = rel.toLowerCase();
|
|
394
|
+
const base = rel.split("/").pop() ?? rel;
|
|
395
|
+
const lbase = base.toLowerCase();
|
|
396
|
+
if (/(^|\/)(__tests__|__test__)\//.test(lower)) return true;
|
|
397
|
+
if (/(^|\/)(tests?|spec|specs)\//.test(lower)) return true;
|
|
398
|
+
if (/(^|\/)src\/test\//.test(lower)) return true;
|
|
399
|
+
if (/\.(test|spec)\.[cm]?[jt]sx?$/.test(lbase)) return true;
|
|
400
|
+
if (/^test_.*\.py$/.test(lbase) || /_test\.py$/.test(lbase)) return true;
|
|
401
|
+
if (/_test\.go$/.test(lbase)) return true;
|
|
402
|
+
if (/[A-Za-z0-9](Test|Tests|IT)\.java$/.test(base)) return true;
|
|
403
|
+
if (/_spec\.rb$/.test(lbase) || /_test\.rb$/.test(lbase)) return true;
|
|
404
|
+
if (/[A-Za-z0-9](Test|Tests)\.cs$/.test(base)) return true;
|
|
405
|
+
if (/[A-Za-z0-9](Test|Tests)\.swift$/.test(base)) return true;
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
function applyStaticTestLinkage(nodes, edges) {
|
|
409
|
+
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
410
|
+
const testFiles = /* @__PURE__ */ new Set();
|
|
411
|
+
for (const n of nodes) if (n.kind === "file" && isTestFile(n.file)) testFiles.add(n.file);
|
|
412
|
+
const fileNodeIdByRel = /* @__PURE__ */ new Map();
|
|
413
|
+
for (const n of nodes) if (n.kind === "file") fileNodeIdByRel.set(n.file, n.id);
|
|
414
|
+
const covered = /* @__PURE__ */ new Set();
|
|
415
|
+
const newEdges = /* @__PURE__ */ new Map();
|
|
416
|
+
for (const e of edges) {
|
|
417
|
+
if (e.kind !== "call") continue;
|
|
418
|
+
const src = byId.get(e.src);
|
|
419
|
+
const dst = byId.get(e.dst);
|
|
420
|
+
if (!src || !dst) continue;
|
|
421
|
+
if (testFiles.has(src.file) && !testFiles.has(dst.file) && dst.kind !== "external") {
|
|
422
|
+
const testFileId = fileNodeIdByRel.get(src.file);
|
|
423
|
+
if (!testFileId) continue;
|
|
424
|
+
const id = edgeId("test", testFileId, dst.id);
|
|
425
|
+
if (!newEdges.has(id)) {
|
|
426
|
+
newEdges.set(id, {
|
|
427
|
+
id,
|
|
428
|
+
kind: "test",
|
|
429
|
+
src: testFileId,
|
|
430
|
+
dst: dst.id,
|
|
431
|
+
resolution: e.resolution,
|
|
432
|
+
confidence: e.confidence
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
covered.add(dst.id);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const outNodes = nodes.map((n) => ({ ...n, tested: testedFlag(n, covered.has(n.id), testFiles) }));
|
|
439
|
+
const outEdges = [...edges, ...newEdges.values()].sort(
|
|
440
|
+
(a, b) => a.kind.localeCompare(b.kind) || a.src.localeCompare(b.src) || a.dst.localeCompare(b.dst)
|
|
441
|
+
);
|
|
442
|
+
return {
|
|
443
|
+
nodes: outNodes,
|
|
444
|
+
edges: outEdges,
|
|
445
|
+
testFiles: [...testFiles].sort(),
|
|
446
|
+
testEdgeCount: newEdges.size
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function testedFlag(node, covered, testFiles) {
|
|
450
|
+
if (node.kind === "external" || node.kind === "file" || node.kind === "package" || node.kind === "module") {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
if (testFiles.has(node.file)) return null;
|
|
454
|
+
if (node.kind === "function" || node.kind === "method") return covered;
|
|
455
|
+
return covered ? true : node.tested ?? null;
|
|
456
|
+
}
|
|
457
|
+
function resolve2(parses, resolver) {
|
|
458
|
+
const baseNodes = /* @__PURE__ */ new Map();
|
|
459
|
+
const relSet = new Set(parses.map((p) => p.rel));
|
|
460
|
+
const mod = resolver ?? relativeResolver(relSet);
|
|
461
|
+
const defsByName = /* @__PURE__ */ new Map();
|
|
462
|
+
const defsByFile = /* @__PURE__ */ new Map();
|
|
463
|
+
const fileNodeIdByRel = /* @__PURE__ */ new Map();
|
|
464
|
+
for (const p of parses) {
|
|
465
|
+
const fileId = nodeId({ kind: "file", qualifiedName: p.rel, file: p.rel });
|
|
466
|
+
fileNodeIdByRel.set(p.rel, fileId);
|
|
467
|
+
addNode(baseNodes, {
|
|
468
|
+
id: fileId,
|
|
469
|
+
kind: "file",
|
|
470
|
+
name: path.posix.basename(p.rel),
|
|
471
|
+
qualifiedName: p.rel,
|
|
472
|
+
file: p.rel,
|
|
473
|
+
span: { start: 1, end: 1 },
|
|
474
|
+
lang: p.lang
|
|
475
|
+
});
|
|
476
|
+
for (const d of p.defs) {
|
|
477
|
+
const id = nodeId({
|
|
478
|
+
kind: d.kind,
|
|
479
|
+
qualifiedName: d.qualifiedName,
|
|
480
|
+
file: p.rel,
|
|
481
|
+
signature: d.signature
|
|
482
|
+
});
|
|
483
|
+
addNode(baseNodes, {
|
|
484
|
+
id,
|
|
485
|
+
kind: d.kind,
|
|
486
|
+
name: d.name,
|
|
487
|
+
qualifiedName: d.qualifiedName,
|
|
488
|
+
file: p.rel,
|
|
489
|
+
span: { start: d.startLine, end: d.endLine },
|
|
490
|
+
lang: p.lang,
|
|
491
|
+
signature: d.signature,
|
|
492
|
+
doc: d.doc
|
|
493
|
+
});
|
|
494
|
+
const ref = {
|
|
495
|
+
id,
|
|
496
|
+
name: d.name,
|
|
497
|
+
qualifiedName: d.qualifiedName,
|
|
498
|
+
rel: p.rel,
|
|
499
|
+
lang: p.lang,
|
|
500
|
+
kind: d.kind,
|
|
501
|
+
startByte: d.startByte,
|
|
502
|
+
endByte: d.endByte
|
|
503
|
+
};
|
|
504
|
+
push(defsByName, d.name, ref);
|
|
505
|
+
push(defsByFile, p.rel, ref);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
const filesByNamespace = /* @__PURE__ */ new Map();
|
|
509
|
+
for (const p of parses) for (const ns of p.namespaces ?? []) addToSet(filesByNamespace, ns, p.rel);
|
|
510
|
+
const relsByLang = /* @__PURE__ */ new Map();
|
|
511
|
+
for (const p of parses) push(relsByLang, p.lang, p.rel);
|
|
512
|
+
const nsReachableByRel = /* @__PURE__ */ new Map();
|
|
513
|
+
const moduleReachableByRel = /* @__PURE__ */ new Map();
|
|
514
|
+
for (const p of parses) {
|
|
515
|
+
if (MODULE_SCOPED_LANGS.has(p.lang)) {
|
|
516
|
+
const mod2 = /* @__PURE__ */ new Set();
|
|
517
|
+
for (const rel of relsByLang.get(p.lang) ?? []) if (rel !== p.rel) mod2.add(rel);
|
|
518
|
+
moduleReachableByRel.set(p.rel, mod2);
|
|
519
|
+
}
|
|
520
|
+
const reach = /* @__PURE__ */ new Set();
|
|
521
|
+
const namespaces = new Set(p.namespaces ?? []);
|
|
522
|
+
for (const imp of p.imports) {
|
|
523
|
+
namespaces.add(imp.source);
|
|
524
|
+
if (IMPORT_NAMES_A_TYPE.has(p.lang)) {
|
|
525
|
+
const sep2 = Math.max(imp.source.lastIndexOf("."), imp.source.lastIndexOf("\\"));
|
|
526
|
+
if (sep2 > 0) namespaces.add(imp.source.slice(0, sep2));
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
for (const ns of namespaces) for (const rel of filesByNamespace.get(ns) ?? []) if (rel !== p.rel) reach.add(rel);
|
|
530
|
+
nsReachableByRel.set(p.rel, reach);
|
|
531
|
+
}
|
|
532
|
+
const superTypesByType = /* @__PURE__ */ new Map();
|
|
533
|
+
for (const p of parses) {
|
|
534
|
+
const localDefs = defsByFile.get(p.rel) ?? [];
|
|
535
|
+
for (const h of p.heritage) {
|
|
536
|
+
const encl = enclosingDefRef(localDefs, h.byte);
|
|
537
|
+
if (encl && (encl.kind === "class" || encl.kind === "interface")) addToSet(superTypesByType, encl.name, h.superName);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const edges = new EdgeSet();
|
|
541
|
+
const unresolved = /* @__PURE__ */ new Map();
|
|
542
|
+
const stats = {
|
|
543
|
+
callsResolved: 0,
|
|
544
|
+
callsUnresolved: 0,
|
|
545
|
+
importsResolvedToFile: 0,
|
|
546
|
+
importsExternal: 0,
|
|
547
|
+
resolvers: ["heuristic"]
|
|
548
|
+
};
|
|
549
|
+
for (const p of parses) {
|
|
550
|
+
const fileId = fileNodeIdByRel.get(p.rel);
|
|
551
|
+
const localByQn = /* @__PURE__ */ new Map();
|
|
552
|
+
for (const ref of defsByFile.get(p.rel) ?? []) localByQn.set(ref.qualifiedName, ref.id);
|
|
553
|
+
for (const d of p.defs) {
|
|
554
|
+
const id = localByQn.get(d.qualifiedName);
|
|
555
|
+
const parentQn = parentQualifiedName(d.qualifiedName);
|
|
556
|
+
const parentId = parentQn ? localByQn.get(parentQn) : void 0;
|
|
557
|
+
edges.add("contains", parentId ?? fileId, id, "heuristic", 1);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
const importedFilesByRel = /* @__PURE__ */ new Map();
|
|
561
|
+
for (const p of parses) {
|
|
562
|
+
const fileId = fileNodeIdByRel.get(p.rel);
|
|
563
|
+
const importedRels = /* @__PURE__ */ new Set();
|
|
564
|
+
for (const imp of p.imports) {
|
|
565
|
+
const targetRel = mod.resolve(p.rel, imp.source);
|
|
566
|
+
if (targetRel && targetRel !== p.rel) {
|
|
567
|
+
importedRels.add(targetRel);
|
|
568
|
+
edges.add("import", fileId, fileNodeIdByRel.get(targetRel), "heuristic", 0.9);
|
|
569
|
+
stats.importsResolvedToFile++;
|
|
570
|
+
} else {
|
|
571
|
+
const extId = ensureExternalNode(baseNodes, imp.source);
|
|
572
|
+
edges.add("import", fileId, extId, "heuristic", 1);
|
|
573
|
+
stats.importsExternal++;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
importedFilesByRel.set(p.rel, importedRels);
|
|
577
|
+
}
|
|
578
|
+
for (const p of parses) {
|
|
579
|
+
const fileId = fileNodeIdByRel.get(p.rel);
|
|
580
|
+
const localDefs = defsByFile.get(p.rel) ?? [];
|
|
581
|
+
const imported = importedFilesByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
582
|
+
const testCaller = isTestFile(p.rel);
|
|
583
|
+
const nsReach = nsReachableByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
584
|
+
const modReach = moduleReachableByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
585
|
+
for (const call of p.calls) {
|
|
586
|
+
const srcId = enclosingDefId(localDefs, call.byte) ?? fileId;
|
|
587
|
+
const resolved = resolveCall(call, p.rel, p.lang, imported, defsByName, srcId, testCaller, nsReach, superTypesByType, modReach);
|
|
588
|
+
if (resolved) {
|
|
589
|
+
edges.add("call", srcId, resolved.id, "heuristic", resolved.confidence);
|
|
590
|
+
stats.callsResolved++;
|
|
591
|
+
} else {
|
|
592
|
+
stats.callsUnresolved++;
|
|
593
|
+
bumpUnresolved(unresolved, srcId, call.callee, "call", p.rel);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
for (const p of parses) {
|
|
598
|
+
const fileId = fileNodeIdByRel.get(p.rel);
|
|
599
|
+
const localDefs = defsByFile.get(p.rel) ?? [];
|
|
600
|
+
const imported = importedFilesByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
601
|
+
const testCaller = isTestFile(p.rel);
|
|
602
|
+
const nsReach = nsReachableByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
603
|
+
const modReach = moduleReachableByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
604
|
+
for (const ref of p.typeRefs) {
|
|
605
|
+
const srcId = enclosingDefId(localDefs, ref.byte) ?? fileId;
|
|
606
|
+
const target = resolveType(ref.name, p.rel, p.lang, imported, defsByName, testCaller, nsReach, modReach);
|
|
607
|
+
if (target) edges.add("references", srcId, target.id, "heuristic", 0.7);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
for (const p of parses) {
|
|
611
|
+
const localDefs = defsByFile.get(p.rel) ?? [];
|
|
612
|
+
const imported = importedFilesByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
613
|
+
const testCaller = isTestFile(p.rel);
|
|
614
|
+
for (const h of p.heritage) {
|
|
615
|
+
const srcId = enclosingDefId(localDefs, h.byte);
|
|
616
|
+
if (!srcId) continue;
|
|
617
|
+
const nsReach = nsReachableByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
618
|
+
const modReach = moduleReachableByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
|
|
619
|
+
const target = resolveType(h.superName, p.rel, p.lang, imported, defsByName, testCaller, nsReach, modReach);
|
|
620
|
+
if (target) edges.add(h.kind, srcId, target.id, "heuristic", 0.85);
|
|
621
|
+
else bumpUnresolved(unresolved, srcId, h.superName, h.kind, p.rel);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
const nodes = [...baseNodes.values()].map((n) => ({
|
|
625
|
+
...n,
|
|
626
|
+
importance: 0,
|
|
627
|
+
centrality: { degree: 0, pagerank: 0, betweenness: 0, eigenvector: 0 },
|
|
628
|
+
area: 0,
|
|
629
|
+
isHub: false,
|
|
630
|
+
tested: null
|
|
631
|
+
}));
|
|
632
|
+
const unresolvedList = [...unresolved.values()].sort(
|
|
633
|
+
(a, b) => a.from.localeCompare(b.from) || a.kind.localeCompare(b.kind) || a.name.localeCompare(b.name)
|
|
634
|
+
);
|
|
635
|
+
return { nodes, edges: edges.toArray(), unresolved: unresolvedList, stats };
|
|
636
|
+
}
|
|
637
|
+
function bumpUnresolved(map, from, name, kind, fromRel) {
|
|
638
|
+
const key = `${from}${kind}${name}`;
|
|
639
|
+
const existing = map.get(key);
|
|
640
|
+
if (existing) existing.count++;
|
|
641
|
+
else map.set(key, { from, name, kind, count: 1, fromRel });
|
|
642
|
+
}
|
|
643
|
+
function addNode(map, n) {
|
|
644
|
+
if (!map.has(n.id)) map.set(n.id, n);
|
|
645
|
+
}
|
|
646
|
+
function ensureExternalNode(map, source) {
|
|
647
|
+
const id = nodeId({ kind: "external", qualifiedName: source, file: "" });
|
|
648
|
+
if (!map.has(id)) {
|
|
649
|
+
map.set(id, {
|
|
650
|
+
id,
|
|
651
|
+
kind: "external",
|
|
652
|
+
name: source,
|
|
653
|
+
qualifiedName: source,
|
|
654
|
+
file: "",
|
|
655
|
+
span: { start: 1, end: 1 },
|
|
656
|
+
lang: "external"
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
return id;
|
|
660
|
+
}
|
|
661
|
+
function push(map, key, value) {
|
|
662
|
+
const list = map.get(key);
|
|
663
|
+
if (list) list.push(value);
|
|
664
|
+
else map.set(key, [value]);
|
|
665
|
+
}
|
|
666
|
+
function parentQualifiedName(qn) {
|
|
667
|
+
const idx = qn.lastIndexOf(".");
|
|
668
|
+
return idx > 0 ? qn.slice(0, idx) : null;
|
|
669
|
+
}
|
|
670
|
+
function enclosingDefRef(defs, byte) {
|
|
671
|
+
let best;
|
|
672
|
+
for (const d of defs) {
|
|
673
|
+
if (d.startByte <= byte && d.endByte >= byte) {
|
|
674
|
+
if (!best || d.endByte - d.startByte < best.endByte - best.startByte) best = d;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return best;
|
|
678
|
+
}
|
|
679
|
+
function enclosingDefId(defs, byte) {
|
|
680
|
+
return enclosingDefRef(defs, byte)?.id;
|
|
681
|
+
}
|
|
682
|
+
function addToSet(map, key, value) {
|
|
683
|
+
const s = map.get(key);
|
|
684
|
+
if (s) s.add(value);
|
|
685
|
+
else map.set(key, /* @__PURE__ */ new Set([value]));
|
|
686
|
+
}
|
|
687
|
+
function parentTypeName(qualifiedName) {
|
|
688
|
+
const i = qualifiedName.lastIndexOf(".");
|
|
689
|
+
return i > 0 ? qualifiedName.slice(0, i) : null;
|
|
690
|
+
}
|
|
691
|
+
function disambiguateInterfaceImpl(pool, superTypesByType) {
|
|
692
|
+
const withParent = pool.map((c) => ({ c, parent: parentTypeName(c.qualifiedName) })).filter((x) => x.parent !== null);
|
|
693
|
+
if (withParent.length < 2) return null;
|
|
694
|
+
const parents = new Set(withParent.map((x) => x.parent));
|
|
695
|
+
const impls = withParent.filter(
|
|
696
|
+
(x) => [...parents].some((other) => other !== x.parent && superTypesByType.get(x.parent)?.has(other))
|
|
697
|
+
);
|
|
698
|
+
if (impls.length === 0) return null;
|
|
699
|
+
const interfaceParents = /* @__PURE__ */ new Set();
|
|
700
|
+
for (const impl of impls) for (const s of superTypesByType.get(impl.parent) ?? []) interfaceParents.add(s);
|
|
701
|
+
const interfaces = withParent.filter((x) => interfaceParents.has(x.parent));
|
|
702
|
+
const uniqueImplIds = new Set(impls.map((x) => x.c.id));
|
|
703
|
+
if (uniqueImplIds.size === 1) return impls[0].c;
|
|
704
|
+
const uniqueIfaceIds = new Set(interfaces.map((x) => x.c.id));
|
|
705
|
+
if (uniqueIfaceIds.size === 1) return interfaces[0].c;
|
|
706
|
+
return null;
|
|
707
|
+
}
|
|
708
|
+
var PACKAGE_SCOPED_LANGS = /* @__PURE__ */ new Set(["go", "java", "cs", "kotlin", "scala", "swift"]);
|
|
709
|
+
var IMPORT_NAMES_A_TYPE = /* @__PURE__ */ new Set(["java", "kotlin", "scala", "php"]);
|
|
710
|
+
var MODULE_SCOPED_LANGS = /* @__PURE__ */ new Set(["swift"]);
|
|
711
|
+
function dirOf(rel) {
|
|
712
|
+
const i = rel.lastIndexOf("/");
|
|
713
|
+
return i >= 0 ? rel.slice(0, i) : "";
|
|
714
|
+
}
|
|
715
|
+
function resolveCall(call, fromRel, fromLang, importedRels, defsByName, enclosingId, fromIsTestFile = false, nsReachableRels = /* @__PURE__ */ new Set(), superTypesByType = /* @__PURE__ */ new Map(), moduleReachableRels = /* @__PURE__ */ new Set()) {
|
|
716
|
+
const candidates = defsByName.get(call.callee);
|
|
717
|
+
if (!candidates || candidates.length === 0) return null;
|
|
718
|
+
const callable = candidates.filter((c) => c.kind === "function" || c.kind === "method");
|
|
719
|
+
const pool = callable.length ? callable : candidates;
|
|
720
|
+
let sameFile = pool.filter((c) => c.rel === fromRel);
|
|
721
|
+
if (call.qualified && enclosingId) sameFile = sameFile.filter((c) => c.id !== enclosingId);
|
|
722
|
+
if (sameFile.length === 1) return { id: sameFile[0].id, confidence: 0.85 };
|
|
723
|
+
if (sameFile.length > 1) {
|
|
724
|
+
const pick = [...sameFile].sort((a, b) => a.id.localeCompare(b.id))[0];
|
|
725
|
+
return { id: pick.id, confidence: 0.4 };
|
|
726
|
+
}
|
|
727
|
+
const dir = dirOf(fromRel);
|
|
728
|
+
const notSelf = (c) => !(call.qualified && enclosingId && c.id === enclosingId);
|
|
729
|
+
const strict = pool.filter(
|
|
730
|
+
(c) => notSelf(c) && (importedRels.has(c.rel) || PACKAGE_SCOPED_LANGS.has(fromLang) && c.lang === fromLang && dirOf(c.rel) === dir || nsReachableRels.has(c.rel))
|
|
731
|
+
);
|
|
732
|
+
if (strict.length === 1) return { id: strict[0].id, confidence: 0.75 };
|
|
733
|
+
const broad = pool.filter((c) => notSelf(c) && (moduleReachableRels.has(c.rel) || strict.includes(c)));
|
|
734
|
+
if (broad.length > 1) {
|
|
735
|
+
const dedup = disambiguateInterfaceImpl(broad, superTypesByType);
|
|
736
|
+
if (dedup) return { id: dedup.id, confidence: 0.6 };
|
|
737
|
+
}
|
|
738
|
+
if (strict.length > 1) return null;
|
|
739
|
+
if (fromLang === "swift" && fromIsTestFile && pool.length === 1) {
|
|
740
|
+
return { id: pool[0].id, confidence: 0.5 };
|
|
741
|
+
}
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
function resolveType(name, fromRel, fromLang, importedRels, defsByName, fromIsTestFile = false, nsReachableRels = /* @__PURE__ */ new Set(), moduleReachableRels = /* @__PURE__ */ new Set()) {
|
|
745
|
+
const candidates = (defsByName.get(name) ?? []).filter(
|
|
746
|
+
(c) => c.kind === "class" || c.kind === "interface"
|
|
747
|
+
);
|
|
748
|
+
if (candidates.length === 0) return null;
|
|
749
|
+
const sameFile = candidates.filter((c) => c.rel === fromRel);
|
|
750
|
+
if (sameFile.length === 1) return { id: sameFile[0].id };
|
|
751
|
+
const imported = candidates.filter((c) => importedRels.has(c.rel));
|
|
752
|
+
if (imported.length === 1) return { id: imported[0].id };
|
|
753
|
+
if (imported.length > 1) return null;
|
|
754
|
+
if (PACKAGE_SCOPED_LANGS.has(fromLang)) {
|
|
755
|
+
const dir = dirOf(fromRel);
|
|
756
|
+
const samePkg = candidates.filter((c) => c.lang === fromLang && dirOf(c.rel) === dir);
|
|
757
|
+
if (samePkg.length === 1) return { id: samePkg[0].id };
|
|
758
|
+
}
|
|
759
|
+
if (nsReachableRels.size || moduleReachableRels.size) {
|
|
760
|
+
const reach = candidates.filter((c) => nsReachableRels.has(c.rel) || moduleReachableRels.has(c.rel));
|
|
761
|
+
if (reach.length === 1) return { id: reach[0].id };
|
|
762
|
+
}
|
|
763
|
+
if (fromLang === "swift" && fromIsTestFile && candidates.length === 1) {
|
|
764
|
+
return { id: candidates[0].id };
|
|
765
|
+
}
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
var EdgeSet = class {
|
|
769
|
+
map = /* @__PURE__ */ new Map();
|
|
770
|
+
add(kind, src, dst, resolution, confidence) {
|
|
771
|
+
const id = edgeId(kind, src, dst);
|
|
772
|
+
const existing = this.map.get(id);
|
|
773
|
+
if (existing) {
|
|
774
|
+
existing.count = (existing.count ?? 1) + 1;
|
|
775
|
+
if (confidence > existing.confidence) existing.confidence = confidence;
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
this.map.set(id, { id, kind, src, dst, resolution, confidence, count: 1 });
|
|
779
|
+
}
|
|
780
|
+
toArray() {
|
|
781
|
+
return [...this.map.values()].sort(
|
|
782
|
+
(a, b) => a.kind.localeCompare(b.kind) || a.src.localeCompare(b.src) || a.dst.localeCompare(b.dst)
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
export { applyStaticTestLinkage, buildModuleResolver, edgeId, isTestFile, nodeId, parseJsonc, relativeResolver, resolve2 as resolve };
|
|
788
|
+
//# sourceMappingURL=chunk-IPICO2RV.js.map
|
|
789
|
+
//# sourceMappingURL=chunk-IPICO2RV.js.map
|