scip-query 0.4.3 → 0.6.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/dist/chunk-2DSS2NGF.js +10 -0
- package/dist/chunk-2RLP74AO.js +2 -0
- package/dist/chunk-4QJ7LVW5.js +2 -0
- package/dist/chunk-4TYGGOLO.js +5 -0
- package/dist/chunk-5IADAU5B.js +7 -0
- package/dist/chunk-7754WFFV.js +18 -0
- package/dist/chunk-7VOF4ZG6.js +2 -0
- package/dist/chunk-7Z4COVMC.js +2 -0
- package/dist/chunk-AJ5PWKD4.js +2 -0
- package/dist/chunk-BDBRZPX3.js +7 -0
- package/dist/chunk-BE6EQIWY.js +2 -0
- package/dist/chunk-BQ3INTYT.js +8 -0
- package/dist/chunk-D7KLLMPB.js +2 -0
- package/dist/chunk-D7YBWSON.js +29 -0
- package/dist/chunk-DE5ZBHMK.js +39 -0
- package/dist/chunk-DHYIJHXZ.js +33 -0
- package/dist/chunk-EEF3YEHW.js +2 -0
- package/dist/chunk-F2LLHRRZ.js +2 -0
- package/dist/chunk-FCC3XJTI.js +2 -0
- package/dist/chunk-GNXRLK5G.js +2 -0
- package/dist/chunk-GXVB36TG.js +62 -0
- package/dist/chunk-HMKJTAZD.js +2 -0
- package/dist/chunk-IBGBI3VU.js +2 -0
- package/dist/chunk-IYFZS4PV.js +84 -0
- package/dist/chunk-JH3A7HTU.js +2 -0
- package/dist/chunk-JS2RNIC7.js +2 -0
- package/dist/chunk-K5FQFCSN.js +41 -0
- package/dist/chunk-K6GBKEQE.js +6 -0
- package/dist/chunk-KO7YJRWP.js +12 -0
- package/dist/chunk-KYT47WU2.js +4 -0
- package/dist/chunk-LORWXBOO.js +2 -0
- package/dist/chunk-LX4H4LLG.js +89 -0
- package/dist/chunk-N3Z2SJCR.js +2 -0
- package/dist/chunk-NTDA4A2D.js +25 -0
- package/dist/chunk-NXMYYHDO.js +24 -0
- package/dist/chunk-PZ6ESKRH.js +7 -0
- package/dist/chunk-QXE6EDY2.js +6 -0
- package/dist/chunk-RJ7SPBJ5.js +5 -0
- package/dist/chunk-RWE6FHG3.js +3 -0
- package/dist/chunk-SDX6MDBL.js +2 -0
- package/dist/chunk-SG35Y7J2.js +2 -0
- package/dist/chunk-STOGKRJH.js +4 -0
- package/dist/chunk-TINPMWJK.js +2 -0
- package/dist/chunk-UJB62HV3.js +2 -0
- package/dist/chunk-VEUMRDHW.js +2 -0
- package/dist/chunk-WCDXJGYT.js +65 -0
- package/dist/chunk-WTSTDJZ7.js +6 -0
- package/dist/chunk-XAZTIDST.js +2 -0
- package/dist/chunk-XVDASCN7.js +35 -0
- package/dist/chunk-Y7H6D2EV.js +2 -0
- package/dist/chunk-Y7LOQSWY.js +2 -0
- package/dist/chunk-YIPCV7M7.js +70 -0
- package/dist/chunk-ZSRXMNMK.js +5 -0
- package/dist/chunk-ZXKURFVB.js +56 -0
- package/dist/cli.js +509 -8938
- package/dist/{db-6F9R9e_t.d.ts → db-BSTtBG_H.d.ts} +146 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.js +13 -1616
- package/dist/postinstall.js +4 -100
- package/dist/queries/affected.d.ts +1 -1
- package/dist/queries/affected.js +1 -8
- package/dist/queries/bottlenecks.d.ts +1 -1
- package/dist/queries/bottlenecks.js +1 -8
- package/dist/queries/by-kind.d.ts +1 -4
- package/dist/queries/by-kind.js +1 -10
- package/dist/queries/call-graph.d.ts +1 -1
- package/dist/queries/call-graph.js +1 -8
- package/dist/queries/change-surface.d.ts +4 -1
- package/dist/queries/change-surface.js +1 -8
- package/dist/queries/code.d.ts +1 -1
- package/dist/queries/code.js +1 -8
- package/dist/queries/complexity-hotspots.d.ts +5 -3
- package/dist/queries/complexity-hotspots.js +1 -8
- package/dist/queries/complexity.d.ts +1 -1
- package/dist/queries/complexity.js +1 -8
- package/dist/queries/convergence.d.ts +1 -1
- package/dist/queries/convergence.js +1 -8
- package/dist/queries/coupling.d.ts +1 -1
- package/dist/queries/coupling.js +1 -10
- package/dist/queries/cycles.d.ts +1 -1
- package/dist/queries/cycles.js +1 -8
- package/dist/queries/dataflow.d.ts +1 -1
- package/dist/queries/dataflow.js +1 -8
- package/dist/queries/dead.d.ts +1 -1
- package/dist/queries/dead.js +1 -9
- package/dist/queries/deep-chains.d.ts +9 -1
- package/dist/queries/deep-chains.js +1 -8
- package/dist/queries/deps.d.ts +1 -1
- package/dist/queries/deps.js +1 -10
- package/dist/queries/diff-impact.d.ts +1 -1
- package/dist/queries/diff-impact.js +1 -7
- package/dist/queries/drift.d.ts +1 -1
- package/dist/queries/drift.js +1 -8
- package/dist/queries/extract-candidates.d.ts +1 -1
- package/dist/queries/extract-candidates.js +1 -8
- package/dist/queries/fan.d.ts +1 -1
- package/dist/queries/fan.js +1 -14
- package/dist/queries/files.d.ts +1 -1
- package/dist/queries/files.js +1 -6
- package/dist/queries/health.d.ts +1 -1
- package/dist/queries/health.js +1 -20
- package/dist/queries/hierarchy.d.ts +1 -1
- package/dist/queries/hierarchy.js +1 -8
- package/dist/queries/hotspots.d.ts +1 -1
- package/dist/queries/hotspots.js +1 -8
- package/dist/queries/imports.d.ts +1 -1
- package/dist/queries/imports.js +1 -12
- package/dist/queries/index.d.ts +1 -1
- package/dist/queries/index.js +1 -197
- package/dist/queries/isolated.d.ts +1 -1
- package/dist/queries/isolated.js +1 -9
- package/dist/queries/members.d.ts +4 -1
- package/dist/queries/members.js +1 -8
- package/dist/queries/methods.d.ts +1 -1
- package/dist/queries/methods.js +1 -8
- package/dist/queries/outline.d.ts +4 -1
- package/dist/queries/outline.js +1 -8
- package/dist/queries/passthrough-candidates.d.ts +1 -1
- package/dist/queries/passthrough-candidates.js +1 -8
- package/dist/queries/redundant-reexports.d.ts +1 -1
- package/dist/queries/redundant-reexports.js +1 -9
- package/dist/queries/refs.d.ts +1 -1
- package/dist/queries/refs.js +1 -8
- package/dist/queries/similar-chains.d.ts +1 -1
- package/dist/queries/similar-chains.js +1 -8
- package/dist/queries/similar-files.d.ts +1 -1
- package/dist/queries/similar-files.js +1 -8
- package/dist/queries/similar-signatures.d.ts +1 -1
- package/dist/queries/similar-signatures.js +1 -8
- package/dist/queries/similar.d.ts +1 -1
- package/dist/queries/similar.js +1 -10
- package/dist/queries/slice.d.ts +1 -1
- package/dist/queries/slice.js +1 -8
- package/dist/queries/stale-abstractions.d.ts +15 -5
- package/dist/queries/stale-abstractions.js +1 -8
- package/dist/queries/stats.d.ts +1 -1
- package/dist/queries/stats.js +1 -6
- package/dist/queries/surface.d.ts +1 -1
- package/dist/queries/surface.js +1 -8
- package/dist/queries/symbols.d.ts +1 -1
- package/dist/queries/symbols.js +1 -9
- package/dist/queries/system.d.ts +6 -2
- package/dist/queries/system.js +1 -9
- package/dist/queries/trace.d.ts +1 -1
- package/dist/queries/trace.js +1 -9
- package/dist/queries/wrapper-candidates.d.ts +1 -1
- package/dist/queries/wrapper-candidates.js +1 -8
- package/dist/reindex-worker.js +7 -672
- package/package.json +20 -2
- package/dist/chunk-334PCFO3.js +0 -221
- package/dist/chunk-46ZTW4AI.js +0 -61
- package/dist/chunk-4TYLS5XX.js +0 -10
- package/dist/chunk-4YN3PE57.js +0 -124
- package/dist/chunk-5YB6UXQ3.js +0 -101
- package/dist/chunk-6PVHJ332.js +0 -44
- package/dist/chunk-74RFWB5T.js +0 -24
- package/dist/chunk-7KGTWDAX.js +0 -87
- package/dist/chunk-7OGXSMLY.js +0 -105
- package/dist/chunk-AEBM56CO.js +0 -69
- package/dist/chunk-B747RITP.js +0 -38
- package/dist/chunk-B7LDMCUS.js +0 -110
- package/dist/chunk-C2VSV54P.js +0 -110
- package/dist/chunk-DIYEUFVP.js +0 -81
- package/dist/chunk-E74RY6AQ.js +0 -93
- package/dist/chunk-FIMTTUGE.js +0 -165
- package/dist/chunk-FMAYH7GS.js +0 -2542
- package/dist/chunk-FO2CBB7U.js +0 -23
- package/dist/chunk-HESWGDIV.js +0 -162
- package/dist/chunk-HL2LXSBW.js +0 -34
- package/dist/chunk-HW76DVE4.js +0 -216
- package/dist/chunk-IC5NTO47.js +0 -53
- package/dist/chunk-J34HAAEQ.js +0 -59
- package/dist/chunk-JSXGC2EH.js +0 -151
- package/dist/chunk-LQXBFCP2.js +0 -87
- package/dist/chunk-NML6M5AS.js +0 -37
- package/dist/chunk-NNFP4ZRF.js +0 -72
- package/dist/chunk-NWXTQGUE.js +0 -49
- package/dist/chunk-NYZ6INK3.js +0 -95
- package/dist/chunk-OMVF3BHY.js +0 -84
- package/dist/chunk-P3VCDYMJ.js +0 -269
- package/dist/chunk-PGQXIAJF.js +0 -79
- package/dist/chunk-PKDFXASW.js +0 -76
- package/dist/chunk-PSK5BPFE.js +0 -82
- package/dist/chunk-QZ4FRB65.js +0 -341
- package/dist/chunk-R2QBMQQN.js +0 -185
- package/dist/chunk-T3ALCNCP.js +0 -113
- package/dist/chunk-T6UVM534.js +0 -213
- package/dist/chunk-U74VYTLX.js +0 -46
- package/dist/chunk-UIRCHPOU.js +0 -34
- package/dist/chunk-UNS6ZQVX.js +0 -71
- package/dist/chunk-VJMTX3OR.js +0 -115
- package/dist/chunk-XJSPWHNT.js +0 -64
- package/dist/chunk-XMZAC2VU.js +0 -84
- package/dist/chunk-Y7FKURZG.js +0 -130
- package/dist/chunk-YMSJCSRG.js +0 -213
- package/dist/chunk-YQIWS5V6.js +0 -172
- package/dist/chunk-ZPEI7DRJ.js +0 -66
- package/dist/queries/clean-signature.d.ts +0 -9
- package/dist/queries/clean-signature.js +0 -7
package/dist/chunk-PGQXIAJF.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getAllDefinitions,
|
|
3
|
-
getCalleeRowsForSymbol,
|
|
4
|
-
getCallerRowsForSymbol
|
|
5
|
-
} from "./chunk-FMAYH7GS.js";
|
|
6
|
-
import {
|
|
7
|
-
shortenSymbol
|
|
8
|
-
} from "./chunk-YMSJCSRG.js";
|
|
9
|
-
|
|
10
|
-
// src/queries/bottlenecks.ts
|
|
11
|
-
function bottlenecks(db, opts = {}) {
|
|
12
|
-
const { limit = 20, scope, minFanIn = 2, minFanOut = 2 } = opts;
|
|
13
|
-
const scopeFilter = scope ? `AND def_d.relative_path LIKE '%${scope}%'` : "";
|
|
14
|
-
const rows = db.all(
|
|
15
|
-
`SELECT * FROM (
|
|
16
|
-
SELECT
|
|
17
|
-
gs.symbol,
|
|
18
|
-
def_d.relative_path AS defined_in,
|
|
19
|
-
(SELECT COUNT(DISTINCT ref_c.document_id)
|
|
20
|
-
FROM mentions ref_m
|
|
21
|
-
JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
|
|
22
|
-
WHERE ref_m.symbol_id = gs.id AND ref_m.role != 1
|
|
23
|
-
) AS fan_in,
|
|
24
|
-
(SELECT COUNT(DISTINCT ref_gs.id)
|
|
25
|
-
FROM mentions ref_m
|
|
26
|
-
JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
|
|
27
|
-
JOIN global_symbols ref_gs ON ref_m.symbol_id = ref_gs.id
|
|
28
|
-
JOIN defn_enclosing_ranges ref_der ON ref_gs.id = ref_der.symbol_id
|
|
29
|
-
WHERE ref_c.document_id = def_d.id
|
|
30
|
-
AND ref_m.role != 1
|
|
31
|
-
AND ref_der.document_id != def_d.id
|
|
32
|
-
) AS fan_out
|
|
33
|
-
FROM global_symbols gs
|
|
34
|
-
JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
35
|
-
JOIN documents def_d ON der.document_id = def_d.id
|
|
36
|
-
WHERE 1 = 1
|
|
37
|
-
${db.pathExclusionsFor("def_d")}
|
|
38
|
-
${db.symbolNoiseFor("gs")}
|
|
39
|
-
${scopeFilter}
|
|
40
|
-
) WHERE fan_in >= ? AND fan_out >= ?
|
|
41
|
-
ORDER BY (fan_in * fan_out) DESC
|
|
42
|
-
LIMIT ?`,
|
|
43
|
-
minFanIn,
|
|
44
|
-
minFanOut,
|
|
45
|
-
limit
|
|
46
|
-
);
|
|
47
|
-
const indexedResults = rows.filter((r) => !db.isIgnored(r.defined_in)).map((r) => ({
|
|
48
|
-
symbol: r.symbol,
|
|
49
|
-
shortName: shortenSymbol(r.symbol),
|
|
50
|
-
fanIn: r.fan_in,
|
|
51
|
-
fanOut: r.fan_out,
|
|
52
|
-
score: r.fan_in * r.fan_out,
|
|
53
|
-
definedIn: r.defined_in
|
|
54
|
-
}));
|
|
55
|
-
if (indexedResults.length > 0) {
|
|
56
|
-
return indexedResults;
|
|
57
|
-
}
|
|
58
|
-
return getAllDefinitions(db, { scope }).filter((definition) => !db.isIgnored(definition.relativePath)).map((definition) => {
|
|
59
|
-
const fanIn = new Set(
|
|
60
|
-
getCallerRowsForSymbol(db, definition, { limit: 500 }).map((row) => row.file)
|
|
61
|
-
).size;
|
|
62
|
-
const fanOut = new Set(
|
|
63
|
-
getCalleeRowsForSymbol(db, definition, { limit: 500 }).filter((row) => row.file !== definition.relativePath).map((row) => `${row.symbol}|${row.file}`)
|
|
64
|
-
).size;
|
|
65
|
-
return {
|
|
66
|
-
symbol: definition.symbol,
|
|
67
|
-
shortName: shortenSymbol(definition.symbol),
|
|
68
|
-
fanIn,
|
|
69
|
-
fanOut,
|
|
70
|
-
score: fanIn * fanOut,
|
|
71
|
-
definedIn: definition.relativePath
|
|
72
|
-
};
|
|
73
|
-
}).filter((row) => row.fanIn >= minFanIn && row.fanOut >= minFanOut).sort((left, right) => right.score - left.score || right.fanIn - left.fanIn).slice(0, limit);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export {
|
|
77
|
-
bottlenecks
|
|
78
|
-
};
|
|
79
|
-
//# sourceMappingURL=chunk-PGQXIAJF.js.map
|
package/dist/chunk-PKDFXASW.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
findFirstSymbolMatch,
|
|
3
|
-
getCalleeRowsForSymbol
|
|
4
|
-
} from "./chunk-FMAYH7GS.js";
|
|
5
|
-
import {
|
|
6
|
-
shortenSymbol
|
|
7
|
-
} from "./chunk-YMSJCSRG.js";
|
|
8
|
-
|
|
9
|
-
// src/queries/convergence.ts
|
|
10
|
-
function convergence(db, symbolPatternA, symbolPatternB) {
|
|
11
|
-
const matchA = findFirstSymbolMatch(db, symbolPatternA);
|
|
12
|
-
const matchB = findFirstSymbolMatch(db, symbolPatternB);
|
|
13
|
-
if (!matchA || !matchB) return null;
|
|
14
|
-
const calleesA = new Set(
|
|
15
|
-
getCalleeRowsForSymbol(db, matchA).map((r) => r.symbol)
|
|
16
|
-
);
|
|
17
|
-
const calleesB = new Set(
|
|
18
|
-
getCalleeRowsForSymbol(db, matchB).map((r) => r.symbol)
|
|
19
|
-
);
|
|
20
|
-
const shared = [];
|
|
21
|
-
for (const c of calleesA) {
|
|
22
|
-
if (calleesB.has(c)) shared.push(c);
|
|
23
|
-
}
|
|
24
|
-
const uniqueA = [];
|
|
25
|
-
for (const c of calleesA) {
|
|
26
|
-
if (!calleesB.has(c)) uniqueA.push(c);
|
|
27
|
-
}
|
|
28
|
-
const uniqueB = [];
|
|
29
|
-
for (const c of calleesB) {
|
|
30
|
-
if (!calleesA.has(c)) uniqueB.push(c);
|
|
31
|
-
}
|
|
32
|
-
const union = /* @__PURE__ */ new Set([...calleesA, ...calleesB]);
|
|
33
|
-
const similarity = union.size > 0 ? shared.length / union.size : 0;
|
|
34
|
-
let strategy;
|
|
35
|
-
if (union.size === 0) {
|
|
36
|
-
strategy = "Neither function calls other tracked symbols. There is no callee-pattern evidence for consolidation; inspect the source bodies directly.";
|
|
37
|
-
} else if (shared.length === 0) {
|
|
38
|
-
strategy = "These functions do not share any callees. They are not a callee-based consolidation candidate.";
|
|
39
|
-
} else if (uniqueA.length === 0 && uniqueB.length === 0) {
|
|
40
|
-
strategy = "These functions have identical tracked callee sets. They are a strong structural match, but identical callees do not prove interchangeable semantics; inspect signatures, control flow, and return values before consolidating.";
|
|
41
|
-
} else if (uniqueA.length === 0) {
|
|
42
|
-
strategy = `A's tracked callees are a subset of B's. B may subsume part of A's structure, but verify signatures, guards, and non-call logic before replacing A with B.`;
|
|
43
|
-
} else if (uniqueB.length === 0) {
|
|
44
|
-
strategy = `B's tracked callees are a subset of A's. A may subsume part of B's structure, but verify signatures, guards, and non-call logic before replacing B with A.`;
|
|
45
|
-
} else if (uniqueA.length <= 2 && uniqueB.length <= 2) {
|
|
46
|
-
strategy = `Create a shared function with the ${shared.length} common callees. Pass the ${uniqueA.length + uniqueB.length} divergent callees as parameters or strategy callbacks.`;
|
|
47
|
-
} else {
|
|
48
|
-
strategy = `Extract the ${shared.length} shared callees into a common helper. Each function calls the helper plus its own unique logic (${uniqueA.length} callees in A, ${uniqueB.length} in B).`;
|
|
49
|
-
}
|
|
50
|
-
const locA = matchA.endLine - matchA.startLine + 1;
|
|
51
|
-
const locB = matchB.endLine - matchB.startLine + 1;
|
|
52
|
-
return {
|
|
53
|
-
symbolA: {
|
|
54
|
-
symbol: matchA.symbol,
|
|
55
|
-
shortName: shortenSymbol(matchA.symbol),
|
|
56
|
-
file: matchA.relativePath,
|
|
57
|
-
loc: locA
|
|
58
|
-
},
|
|
59
|
-
symbolB: {
|
|
60
|
-
symbol: matchB.symbol,
|
|
61
|
-
shortName: shortenSymbol(matchB.symbol),
|
|
62
|
-
file: matchB.relativePath,
|
|
63
|
-
loc: locB
|
|
64
|
-
},
|
|
65
|
-
similarity,
|
|
66
|
-
sharedCallees: shared.map(shortenSymbol),
|
|
67
|
-
uniqueToA: uniqueA.map(shortenSymbol),
|
|
68
|
-
uniqueToB: uniqueB.map(shortenSymbol),
|
|
69
|
-
consolidationStrategy: strategy
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export {
|
|
74
|
-
convergence
|
|
75
|
-
};
|
|
76
|
-
//# sourceMappingURL=chunk-PKDFXASW.js.map
|
package/dist/chunk-PSK5BPFE.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
cleanSignature
|
|
3
|
-
} from "./chunk-4TYLS5XX.js";
|
|
4
|
-
import {
|
|
5
|
-
resolveIndexedPaths
|
|
6
|
-
} from "./chunk-FMAYH7GS.js";
|
|
7
|
-
import {
|
|
8
|
-
shortenSymbol
|
|
9
|
-
} from "./chunk-YMSJCSRG.js";
|
|
10
|
-
|
|
11
|
-
// src/queries/system.ts
|
|
12
|
-
function system(db, modulePattern) {
|
|
13
|
-
const matchedPaths = resolveIndexedPaths(db, modulePattern);
|
|
14
|
-
if (matchedPaths.length === 0) {
|
|
15
|
-
return { files: [], symbols: [], dependsOn: [], dependedOnBy: [] };
|
|
16
|
-
}
|
|
17
|
-
const placeholders = matchedPaths.map(() => "?").join(", ");
|
|
18
|
-
const fileRows = db.all(
|
|
19
|
-
`SELECT relative_path FROM documents
|
|
20
|
-
WHERE relative_path IN (${placeholders})
|
|
21
|
-
ORDER BY relative_path`,
|
|
22
|
-
...matchedPaths
|
|
23
|
-
);
|
|
24
|
-
const files = fileRows.map((r) => r.relative_path).filter((p) => !db.isIgnored(p));
|
|
25
|
-
const symbolRows = db.all(
|
|
26
|
-
`SELECT der.start_line, der.end_line, gs.symbol,
|
|
27
|
-
REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig
|
|
28
|
-
FROM defn_enclosing_ranges der
|
|
29
|
-
JOIN global_symbols gs ON der.symbol_id = gs.id
|
|
30
|
-
JOIN documents d ON der.document_id = d.id
|
|
31
|
-
WHERE d.relative_path IN (${placeholders})
|
|
32
|
-
AND ${db.localSymbolPredicate}
|
|
33
|
-
${db.symbolNoise}
|
|
34
|
-
AND gs.documentation IS NOT NULL
|
|
35
|
-
ORDER BY d.relative_path, der.start_line`,
|
|
36
|
-
...matchedPaths
|
|
37
|
-
);
|
|
38
|
-
const symbols = symbolRows.map((r) => ({
|
|
39
|
-
startLine: r.start_line,
|
|
40
|
-
endLine: r.end_line,
|
|
41
|
-
symbol: r.symbol,
|
|
42
|
-
shortName: shortenSymbol(r.symbol),
|
|
43
|
-
signature: cleanSignature(r.sig)
|
|
44
|
-
}));
|
|
45
|
-
const depRows = db.all(
|
|
46
|
-
`SELECT DISTINCT d2.relative_path
|
|
47
|
-
FROM mentions m
|
|
48
|
-
JOIN chunks c ON m.chunk_id = c.id
|
|
49
|
-
JOIN documents d1 ON c.document_id = d1.id
|
|
50
|
-
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
51
|
-
JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
52
|
-
JOIN documents d2 ON der.document_id = d2.id
|
|
53
|
-
WHERE d1.relative_path IN (${placeholders})
|
|
54
|
-
AND d2.relative_path NOT IN (${placeholders})
|
|
55
|
-
AND ${db.localSymbolPredicate}
|
|
56
|
-
ORDER BY d2.relative_path`,
|
|
57
|
-
...matchedPaths,
|
|
58
|
-
...matchedPaths
|
|
59
|
-
);
|
|
60
|
-
const dependsOn = depRows.map((r) => r.relative_path).filter((p) => !db.isIgnored(p));
|
|
61
|
-
const rdepRows = db.all(
|
|
62
|
-
`SELECT DISTINCT d1.relative_path
|
|
63
|
-
FROM mentions m
|
|
64
|
-
JOIN chunks c ON m.chunk_id = c.id
|
|
65
|
-
JOIN documents d1 ON c.document_id = d1.id
|
|
66
|
-
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
67
|
-
JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
68
|
-
JOIN documents d2 ON der.document_id = d2.id
|
|
69
|
-
WHERE d2.relative_path IN (${placeholders})
|
|
70
|
-
AND d1.relative_path NOT IN (${placeholders})
|
|
71
|
-
ORDER BY d1.relative_path`,
|
|
72
|
-
...matchedPaths,
|
|
73
|
-
...matchedPaths
|
|
74
|
-
);
|
|
75
|
-
const dependedOnBy = rdepRows.map((r) => r.relative_path).filter((p) => !db.isIgnored(p));
|
|
76
|
-
return { files, symbols, dependsOn, dependedOnBy };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export {
|
|
80
|
-
system
|
|
81
|
-
};
|
|
82
|
-
//# sourceMappingURL=chunk-PSK5BPFE.js.map
|
package/dist/chunk-QZ4FRB65.js
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
findFirstSymbolMatch,
|
|
3
|
-
getAllDefinitions,
|
|
4
|
-
getCalleeRowsForSymbol,
|
|
5
|
-
getSourceText
|
|
6
|
-
} from "./chunk-FMAYH7GS.js";
|
|
7
|
-
import {
|
|
8
|
-
isFunctionLikeSymbol,
|
|
9
|
-
leafName,
|
|
10
|
-
shortenSymbol
|
|
11
|
-
} from "./chunk-YMSJCSRG.js";
|
|
12
|
-
|
|
13
|
-
// src/queries/similar.ts
|
|
14
|
-
function similar(db, symbolPattern, opts = {}) {
|
|
15
|
-
const { minSimilarity = 0.4, limit = 20 } = opts;
|
|
16
|
-
const target = findCallees(db, symbolPattern);
|
|
17
|
-
if (!target) return [];
|
|
18
|
-
if (!isFunctionLikeSymbol(target.symbol)) return [];
|
|
19
|
-
const candidates = getAllCalleeFingerprints(db, {
|
|
20
|
-
minCallees: 3,
|
|
21
|
-
excludeSymbol: target.symbol
|
|
22
|
-
});
|
|
23
|
-
const allFingerprints = [target, ...candidates];
|
|
24
|
-
const idfWeights = computeIdf(allFingerprints);
|
|
25
|
-
const results = [];
|
|
26
|
-
for (const candidate of candidates) {
|
|
27
|
-
if (candidate.callees.size < 3) continue;
|
|
28
|
-
const { similarity, significantShared } = weightedSimilarity(
|
|
29
|
-
target.callees,
|
|
30
|
-
candidate.callees,
|
|
31
|
-
idfWeights
|
|
32
|
-
);
|
|
33
|
-
if (similarity < minSimilarity) continue;
|
|
34
|
-
if (significantShared.length < 1) continue;
|
|
35
|
-
results.push({
|
|
36
|
-
symbolA: target.symbol,
|
|
37
|
-
shortNameA: shortenSymbol(target.symbol),
|
|
38
|
-
fileA: target.file,
|
|
39
|
-
symbolB: candidate.symbol,
|
|
40
|
-
shortNameB: shortenSymbol(candidate.symbol),
|
|
41
|
-
fileB: candidate.file,
|
|
42
|
-
similarity,
|
|
43
|
-
sharedCallees: significantShared.map(shortenSymbol),
|
|
44
|
-
uniqueToA: [...difference(target.callees, candidate.callees)].map(shortenSymbol),
|
|
45
|
-
uniqueToB: [...difference(candidate.callees, target.callees)].map(shortenSymbol)
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
results.sort((a, b) => b.similarity - a.similarity);
|
|
49
|
-
if (results.length > 0) {
|
|
50
|
-
return results.slice(0, limit);
|
|
51
|
-
}
|
|
52
|
-
return similarBySourceShape(db, symbolPattern, { minSimilarity, limit });
|
|
53
|
-
}
|
|
54
|
-
function similarAll(db, opts = {}) {
|
|
55
|
-
const { minSimilarity = 0.5, limit = 20, scope, minCallees = 4, crossFileOnly = false } = opts;
|
|
56
|
-
const all = getAllCalleeFingerprints(db, { minCallees, scope });
|
|
57
|
-
const idfWeights = computeIdf(all);
|
|
58
|
-
const results = [];
|
|
59
|
-
for (let i = 0; i < all.length; i++) {
|
|
60
|
-
for (let j = i + 1; j < all.length; j++) {
|
|
61
|
-
const a = all[i];
|
|
62
|
-
const b = all[j];
|
|
63
|
-
if (crossFileOnly && a.file === b.file) continue;
|
|
64
|
-
const { similarity, significantShared } = weightedSimilarity(
|
|
65
|
-
a.callees,
|
|
66
|
-
b.callees,
|
|
67
|
-
idfWeights
|
|
68
|
-
);
|
|
69
|
-
if (similarity < minSimilarity) continue;
|
|
70
|
-
const sharedCount = intersection(a.callees, b.callees).size;
|
|
71
|
-
if (significantShared.length < 2 && sharedCount < 4) continue;
|
|
72
|
-
const displayShared = significantShared.length > 0 ? significantShared : [...intersection(a.callees, b.callees)];
|
|
73
|
-
results.push({
|
|
74
|
-
symbolA: a.symbol,
|
|
75
|
-
shortNameA: shortenSymbol(a.symbol),
|
|
76
|
-
fileA: a.file,
|
|
77
|
-
symbolB: b.symbol,
|
|
78
|
-
shortNameB: shortenSymbol(b.symbol),
|
|
79
|
-
fileB: b.file,
|
|
80
|
-
similarity,
|
|
81
|
-
sharedCallees: displayShared.map(shortenSymbol),
|
|
82
|
-
uniqueToA: [...difference(a.callees, b.callees)].map(shortenSymbol),
|
|
83
|
-
uniqueToB: [...difference(b.callees, a.callees)].map(shortenSymbol)
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
if (results.length > limit * 5) break;
|
|
87
|
-
}
|
|
88
|
-
results.sort((a, b) => b.similarity - a.similarity);
|
|
89
|
-
return results.slice(0, limit);
|
|
90
|
-
}
|
|
91
|
-
function computeIdf(fingerprints) {
|
|
92
|
-
const n = fingerprints.length;
|
|
93
|
-
if (n === 0) return /* @__PURE__ */ new Map();
|
|
94
|
-
const docFreq = /* @__PURE__ */ new Map();
|
|
95
|
-
for (const fp of fingerprints) {
|
|
96
|
-
for (const callee of fp.callees) {
|
|
97
|
-
docFreq.set(callee, (docFreq.get(callee) ?? 0) + 1);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const idf = /* @__PURE__ */ new Map();
|
|
101
|
-
for (const [callee, df] of docFreq) {
|
|
102
|
-
idf.set(callee, Math.log(n / df));
|
|
103
|
-
}
|
|
104
|
-
return idf;
|
|
105
|
-
}
|
|
106
|
-
function weightedSimilarity(a, b, idf) {
|
|
107
|
-
const shared = intersection(a, b);
|
|
108
|
-
if (shared.size === 0) return { similarity: 0, significantShared: [], trivialShared: [] };
|
|
109
|
-
let dotProduct = 0;
|
|
110
|
-
let magA = 0;
|
|
111
|
-
let magB = 0;
|
|
112
|
-
const allCallees = /* @__PURE__ */ new Set([...a, ...b]);
|
|
113
|
-
for (const callee of allCallees) {
|
|
114
|
-
const weight = idf.get(callee) ?? 0;
|
|
115
|
-
const inA = a.has(callee) ? weight : 0;
|
|
116
|
-
const inB = b.has(callee) ? weight : 0;
|
|
117
|
-
dotProduct += inA * inB;
|
|
118
|
-
magA += inA * inA;
|
|
119
|
-
magB += inB * inB;
|
|
120
|
-
}
|
|
121
|
-
const magnitude = Math.sqrt(magA) * Math.sqrt(magB);
|
|
122
|
-
const similarity = magnitude > 0 ? dotProduct / magnitude : 0;
|
|
123
|
-
const medianIdf = getMedianIdf(idf);
|
|
124
|
-
const significantShared = [];
|
|
125
|
-
const trivialShared = [];
|
|
126
|
-
for (const callee of shared) {
|
|
127
|
-
const weight = idf.get(callee) ?? 0;
|
|
128
|
-
if (weight >= medianIdf) {
|
|
129
|
-
significantShared.push(callee);
|
|
130
|
-
} else {
|
|
131
|
-
trivialShared.push(callee);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
significantShared.sort((x, y) => (idf.get(y) ?? 0) - (idf.get(x) ?? 0));
|
|
135
|
-
return { similarity, significantShared, trivialShared };
|
|
136
|
-
}
|
|
137
|
-
function getMedianIdf(idf) {
|
|
138
|
-
const values = [...idf.values()].sort((a, b) => a - b);
|
|
139
|
-
if (values.length === 0) return 0;
|
|
140
|
-
const mid = Math.floor(values.length / 2);
|
|
141
|
-
return values.length % 2 === 0 ? (values[mid - 1] + values[mid]) / 2 : values[mid];
|
|
142
|
-
}
|
|
143
|
-
function findCallees(db, symbolPattern) {
|
|
144
|
-
const target = findFirstSymbolMatch(db, symbolPattern);
|
|
145
|
-
if (!target) return null;
|
|
146
|
-
const calleeRows = getCalleeRowsForSymbol(db, target);
|
|
147
|
-
return {
|
|
148
|
-
symbol: target.symbol,
|
|
149
|
-
file: target.relativePath,
|
|
150
|
-
callees: new Set(calleeRows.map((r) => r.symbol))
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
function getAllCalleeFingerprints(db, opts) {
|
|
154
|
-
const { minCallees, scope, excludeSymbol } = opts;
|
|
155
|
-
const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : "";
|
|
156
|
-
const excludeFilter = excludeSymbol ? `AND gs.symbol != '${excludeSymbol.replace(/'/g, "''")}'` : "";
|
|
157
|
-
const symbols = db.all(
|
|
158
|
-
`SELECT gs.id, gs.symbol, der.document_id, der.start_line, der.end_line, d.relative_path
|
|
159
|
-
FROM global_symbols gs
|
|
160
|
-
JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
161
|
-
JOIN documents d ON der.document_id = d.id
|
|
162
|
-
WHERE 1 = 1
|
|
163
|
-
${db.pathExclusionsFor("d")}
|
|
164
|
-
${db.symbolNoiseFor("gs")}
|
|
165
|
-
AND (der.end_line - der.start_line + 1) >= 5
|
|
166
|
-
${scopeFilter}
|
|
167
|
-
${excludeFilter}
|
|
168
|
-
ORDER BY d.relative_path`
|
|
169
|
-
);
|
|
170
|
-
const fingerprints = [];
|
|
171
|
-
for (const sym of symbols) {
|
|
172
|
-
if (db.isIgnored(sym.relative_path)) continue;
|
|
173
|
-
if (!isFunctionLikeSymbol(sym.symbol)) continue;
|
|
174
|
-
const calleeRows = getCalleeRowsForSymbol(db, {
|
|
175
|
-
documentId: sym.document_id,
|
|
176
|
-
startLine: sym.start_line,
|
|
177
|
-
endLine: sym.end_line,
|
|
178
|
-
symbolId: sym.id
|
|
179
|
-
});
|
|
180
|
-
const callees = new Set(calleeRows.map((r) => r.symbol));
|
|
181
|
-
if (callees.size >= minCallees) {
|
|
182
|
-
fingerprints.push({ symbol: sym.symbol, file: sym.relative_path, callees });
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return fingerprints;
|
|
186
|
-
}
|
|
187
|
-
function intersection(a, b) {
|
|
188
|
-
const result = /* @__PURE__ */ new Set();
|
|
189
|
-
for (const item of a) {
|
|
190
|
-
if (b.has(item)) result.add(item);
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
}
|
|
194
|
-
function difference(a, b) {
|
|
195
|
-
const result = /* @__PURE__ */ new Set();
|
|
196
|
-
for (const item of a) {
|
|
197
|
-
if (!b.has(item)) result.add(item);
|
|
198
|
-
}
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
201
|
-
function similarBySourceShape(db, symbolPattern, opts) {
|
|
202
|
-
const target = findSourceFingerprint(db, symbolPattern);
|
|
203
|
-
if (!target || target.tokens.size < 3) {
|
|
204
|
-
return [];
|
|
205
|
-
}
|
|
206
|
-
const minSimilarity = opts.minSimilarity >= 0.5 ? opts.minSimilarity : 0.3;
|
|
207
|
-
const results = [];
|
|
208
|
-
for (const candidate of getAllSourceFingerprints(db)) {
|
|
209
|
-
if (candidate.symbol === target.symbol || candidate.tokens.size < 3) continue;
|
|
210
|
-
const shared = intersection(target.tokens, candidate.tokens);
|
|
211
|
-
if (shared.size < 2) continue;
|
|
212
|
-
const union = /* @__PURE__ */ new Set([...target.tokens, ...candidate.tokens]);
|
|
213
|
-
const similarity = union.size > 0 ? shared.size / union.size : 0;
|
|
214
|
-
if (similarity < minSimilarity) continue;
|
|
215
|
-
results.push({
|
|
216
|
-
symbolA: target.symbol,
|
|
217
|
-
shortNameA: shortenSymbol(target.symbol),
|
|
218
|
-
fileA: target.file,
|
|
219
|
-
symbolB: candidate.symbol,
|
|
220
|
-
shortNameB: shortenSymbol(candidate.symbol),
|
|
221
|
-
fileB: candidate.file,
|
|
222
|
-
similarity,
|
|
223
|
-
sharedCallees: [...shared].sort(),
|
|
224
|
-
uniqueToA: [...difference(target.tokens, candidate.tokens)].sort(),
|
|
225
|
-
uniqueToB: [...difference(candidate.tokens, target.tokens)].sort()
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
results.sort((a, b) => b.similarity - a.similarity || a.shortNameB.localeCompare(b.shortNameB));
|
|
229
|
-
return results.slice(0, opts.limit);
|
|
230
|
-
}
|
|
231
|
-
function findSourceFingerprint(db, symbolPattern) {
|
|
232
|
-
const match = findFirstSymbolMatch(db, symbolPattern);
|
|
233
|
-
if (!match || !isFunctionLikeSymbol(match.symbol)) {
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
const snippet = definitionSnippet(db, match.relativePath, match.startLine, match.endLine, leafName(match.symbol));
|
|
237
|
-
const tokens = sourceTokens(snippet, leafName(match.symbol));
|
|
238
|
-
if (tokens.size === 0) {
|
|
239
|
-
return null;
|
|
240
|
-
}
|
|
241
|
-
return {
|
|
242
|
-
symbol: match.symbol,
|
|
243
|
-
file: match.relativePath,
|
|
244
|
-
tokens
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
function getAllSourceFingerprints(db) {
|
|
248
|
-
return getAllDefinitions(db).filter((definition) => definition.isFunctionLike).map((definition) => ({
|
|
249
|
-
symbol: definition.symbol,
|
|
250
|
-
file: definition.relativePath,
|
|
251
|
-
tokens: sourceTokens(
|
|
252
|
-
definitionSnippet(db, definition.relativePath, definition.startLine, definition.endLine, definition.leaf),
|
|
253
|
-
definition.leaf
|
|
254
|
-
)
|
|
255
|
-
})).filter((fingerprint) => fingerprint.tokens.size > 0);
|
|
256
|
-
}
|
|
257
|
-
function definitionSnippet(db, relativePath, startLine, endLine, leaf) {
|
|
258
|
-
const source = getSourceText(db, relativePath);
|
|
259
|
-
if (!source) {
|
|
260
|
-
return "";
|
|
261
|
-
}
|
|
262
|
-
const lines = source.split("\n");
|
|
263
|
-
if (endLine >= startLine && endLine - startLine <= 12) {
|
|
264
|
-
return lines.slice(startLine, endLine + 1).join("\n");
|
|
265
|
-
}
|
|
266
|
-
const markerPatterns = [
|
|
267
|
-
new RegExp(`\\bdef\\s+${escapeRegex(leaf)}\\b`),
|
|
268
|
-
new RegExp(`\\bfun\\s+${escapeRegex(leaf)}\\b`),
|
|
269
|
-
new RegExp(`\\bfn\\s+${escapeRegex(leaf)}\\b`),
|
|
270
|
-
new RegExp(`\\bfunction\\s+${escapeRegex(leaf)}\\b`),
|
|
271
|
-
new RegExp(`\\b${escapeRegex(leaf)}\\s*\\(`)
|
|
272
|
-
];
|
|
273
|
-
const definitionStart = lines.findIndex((line) => markerPatterns.some((pattern) => pattern.test(line)));
|
|
274
|
-
if (definitionStart >= 0) {
|
|
275
|
-
let definitionEnd = definitionStart;
|
|
276
|
-
for (let index = definitionStart + 1; index < lines.length && index <= definitionStart + 8; index++) {
|
|
277
|
-
const line = lines[index] ?? "";
|
|
278
|
-
if (index > definitionStart && looksLikeDefinitionBoundary(line)) {
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
definitionEnd = index;
|
|
282
|
-
if (line.trim() === "" && index > definitionStart + 1) {
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return lines.slice(definitionStart, definitionEnd + 1).join("\n");
|
|
287
|
-
}
|
|
288
|
-
return lines.slice(startLine, Math.min(lines.length, startLine + 8)).join("\n");
|
|
289
|
-
}
|
|
290
|
-
function sourceTokens(snippet, leaf) {
|
|
291
|
-
if (!snippet) {
|
|
292
|
-
return /* @__PURE__ */ new Set();
|
|
293
|
-
}
|
|
294
|
-
const stopWords = /* @__PURE__ */ new Set([
|
|
295
|
-
"public",
|
|
296
|
-
"private",
|
|
297
|
-
"protected",
|
|
298
|
-
"final",
|
|
299
|
-
"static",
|
|
300
|
-
"class",
|
|
301
|
-
"def",
|
|
302
|
-
"fun",
|
|
303
|
-
"fn",
|
|
304
|
-
"function",
|
|
305
|
-
"return",
|
|
306
|
-
"string",
|
|
307
|
-
"bool",
|
|
308
|
-
"boolean",
|
|
309
|
-
"void",
|
|
310
|
-
"unit",
|
|
311
|
-
"self",
|
|
312
|
-
"this",
|
|
313
|
-
"new",
|
|
314
|
-
"const",
|
|
315
|
-
"let",
|
|
316
|
-
"var",
|
|
317
|
-
"end",
|
|
318
|
-
"pub"
|
|
319
|
-
]);
|
|
320
|
-
const normalizedLeafParts = splitIdentifier(leaf);
|
|
321
|
-
const normalized = snippet.replace(/["'`]/g, " ").replace(/\b\d+\b/g, " NUM ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[^A-Za-z0-9_]+/g, " ").replace(/_/g, " ").toLowerCase();
|
|
322
|
-
const tokens = normalized.split(/\s+/).map((token) => token.trim()).filter((token) => token.length > 1).filter((token) => !stopWords.has(token)).filter((token) => !normalizedLeafParts.has(token));
|
|
323
|
-
return new Set(tokens);
|
|
324
|
-
}
|
|
325
|
-
function splitIdentifier(value) {
|
|
326
|
-
return new Set(
|
|
327
|
-
value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^A-Za-z0-9_]+|_/).map((part) => part.toLowerCase()).filter((part) => part.length > 1)
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
function looksLikeDefinitionBoundary(line) {
|
|
331
|
-
return /^\s*(?:def|fun|fn|function|class|trait|module|object|enum|interface|public|private|protected)\b/.test(line);
|
|
332
|
-
}
|
|
333
|
-
function escapeRegex(value) {
|
|
334
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export {
|
|
338
|
-
similar,
|
|
339
|
-
similarAll
|
|
340
|
-
};
|
|
341
|
-
//# sourceMappingURL=chunk-QZ4FRB65.js.map
|