@optave/codegraph 3.1.2 → 3.1.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/README.md +19 -21
- package/package.json +10 -7
- package/src/analysis/context.js +408 -0
- package/src/analysis/dependencies.js +341 -0
- package/src/analysis/exports.js +130 -0
- package/src/analysis/impact.js +463 -0
- package/src/analysis/module-map.js +322 -0
- package/src/analysis/roles.js +45 -0
- package/src/analysis/symbol-lookup.js +232 -0
- package/src/ast-analysis/shared.js +5 -4
- package/src/batch.js +2 -1
- package/src/builder/context.js +85 -0
- package/src/builder/helpers.js +218 -0
- package/src/builder/incremental.js +178 -0
- package/src/builder/pipeline.js +130 -0
- package/src/builder/stages/build-edges.js +297 -0
- package/src/builder/stages/build-structure.js +113 -0
- package/src/builder/stages/collect-files.js +44 -0
- package/src/builder/stages/detect-changes.js +413 -0
- package/src/builder/stages/finalize.js +139 -0
- package/src/builder/stages/insert-nodes.js +195 -0
- package/src/builder/stages/parse-files.js +28 -0
- package/src/builder/stages/resolve-imports.js +143 -0
- package/src/builder/stages/run-analyses.js +44 -0
- package/src/builder.js +10 -1472
- package/src/cfg.js +1 -2
- package/src/cli/commands/ast.js +26 -0
- package/src/cli/commands/audit.js +46 -0
- package/src/cli/commands/batch.js +68 -0
- package/src/cli/commands/branch-compare.js +21 -0
- package/src/cli/commands/build.js +26 -0
- package/src/cli/commands/cfg.js +30 -0
- package/src/cli/commands/check.js +79 -0
- package/src/cli/commands/children.js +31 -0
- package/src/cli/commands/co-change.js +65 -0
- package/src/cli/commands/communities.js +23 -0
- package/src/cli/commands/complexity.js +45 -0
- package/src/cli/commands/context.js +34 -0
- package/src/cli/commands/cycles.js +28 -0
- package/src/cli/commands/dataflow.js +32 -0
- package/src/cli/commands/deps.js +16 -0
- package/src/cli/commands/diff-impact.js +30 -0
- package/src/cli/commands/embed.js +30 -0
- package/src/cli/commands/export.js +75 -0
- package/src/cli/commands/exports.js +18 -0
- package/src/cli/commands/flow.js +36 -0
- package/src/cli/commands/fn-impact.js +30 -0
- package/src/cli/commands/impact.js +16 -0
- package/src/cli/commands/info.js +76 -0
- package/src/cli/commands/map.js +19 -0
- package/src/cli/commands/mcp.js +18 -0
- package/src/cli/commands/models.js +19 -0
- package/src/cli/commands/owners.js +25 -0
- package/src/cli/commands/path.js +36 -0
- package/src/cli/commands/plot.js +80 -0
- package/src/cli/commands/query.js +49 -0
- package/src/cli/commands/registry.js +100 -0
- package/src/cli/commands/roles.js +34 -0
- package/src/cli/commands/search.js +42 -0
- package/src/cli/commands/sequence.js +32 -0
- package/src/cli/commands/snapshot.js +61 -0
- package/src/cli/commands/stats.js +15 -0
- package/src/cli/commands/structure.js +32 -0
- package/src/cli/commands/triage.js +78 -0
- package/src/cli/commands/watch.js +12 -0
- package/src/cli/commands/where.js +24 -0
- package/src/cli/index.js +118 -0
- package/src/cli/shared/options.js +39 -0
- package/src/cli/shared/output.js +1 -0
- package/src/cli.js +11 -1514
- package/src/commands/check.js +5 -5
- package/src/commands/manifesto.js +3 -3
- package/src/commands/structure.js +1 -1
- package/src/communities.js +15 -87
- package/src/complexity.js +1 -1
- package/src/cycles.js +30 -85
- package/src/dataflow.js +1 -2
- package/src/db/connection.js +4 -4
- package/src/db/migrations.js +41 -0
- package/src/db/query-builder.js +6 -5
- package/src/db/repository/base.js +201 -0
- package/src/db/repository/cached-stmt.js +19 -0
- package/src/db/repository/cfg.js +27 -38
- package/src/db/repository/cochange.js +16 -3
- package/src/db/repository/complexity.js +11 -6
- package/src/db/repository/dataflow.js +6 -1
- package/src/db/repository/edges.js +120 -98
- package/src/db/repository/embeddings.js +14 -3
- package/src/db/repository/graph-read.js +32 -9
- package/src/db/repository/in-memory-repository.js +584 -0
- package/src/db/repository/index.js +6 -1
- package/src/db/repository/nodes.js +110 -40
- package/src/db/repository/sqlite-repository.js +219 -0
- package/src/db.js +5 -0
- package/src/embeddings/generator.js +163 -0
- package/src/embeddings/index.js +13 -0
- package/src/embeddings/models.js +218 -0
- package/src/embeddings/search/cli-formatter.js +151 -0
- package/src/embeddings/search/filters.js +46 -0
- package/src/embeddings/search/hybrid.js +121 -0
- package/src/embeddings/search/keyword.js +68 -0
- package/src/embeddings/search/prepare.js +66 -0
- package/src/embeddings/search/semantic.js +145 -0
- package/src/embeddings/stores/fts5.js +27 -0
- package/src/embeddings/stores/sqlite-blob.js +24 -0
- package/src/embeddings/strategies/source.js +14 -0
- package/src/embeddings/strategies/structured.js +43 -0
- package/src/embeddings/strategies/text-utils.js +43 -0
- package/src/errors.js +78 -0
- package/src/export.js +217 -520
- package/src/extractors/csharp.js +10 -2
- package/src/extractors/go.js +3 -1
- package/src/extractors/helpers.js +71 -0
- package/src/extractors/java.js +9 -2
- package/src/extractors/javascript.js +38 -1
- package/src/extractors/php.js +3 -1
- package/src/extractors/python.js +14 -3
- package/src/extractors/rust.js +3 -1
- package/src/graph/algorithms/bfs.js +49 -0
- package/src/graph/algorithms/centrality.js +16 -0
- package/src/graph/algorithms/index.js +5 -0
- package/src/graph/algorithms/louvain.js +26 -0
- package/src/graph/algorithms/shortest-path.js +41 -0
- package/src/graph/algorithms/tarjan.js +49 -0
- package/src/graph/builders/dependency.js +91 -0
- package/src/graph/builders/index.js +3 -0
- package/src/graph/builders/structure.js +40 -0
- package/src/graph/builders/temporal.js +33 -0
- package/src/graph/classifiers/index.js +2 -0
- package/src/graph/classifiers/risk.js +85 -0
- package/src/graph/classifiers/roles.js +64 -0
- package/src/graph/index.js +13 -0
- package/src/graph/model.js +230 -0
- package/src/index.js +33 -204
- package/src/infrastructure/result-formatter.js +2 -21
- package/src/mcp/index.js +2 -0
- package/src/mcp/middleware.js +26 -0
- package/src/mcp/server.js +128 -0
- package/src/mcp/tool-registry.js +801 -0
- package/src/mcp/tools/ast-query.js +14 -0
- package/src/mcp/tools/audit.js +21 -0
- package/src/mcp/tools/batch-query.js +11 -0
- package/src/mcp/tools/branch-compare.js +10 -0
- package/src/mcp/tools/cfg.js +21 -0
- package/src/mcp/tools/check.js +43 -0
- package/src/mcp/tools/co-changes.js +20 -0
- package/src/mcp/tools/code-owners.js +12 -0
- package/src/mcp/tools/communities.js +15 -0
- package/src/mcp/tools/complexity.js +18 -0
- package/src/mcp/tools/context.js +17 -0
- package/src/mcp/tools/dataflow.js +26 -0
- package/src/mcp/tools/diff-impact.js +24 -0
- package/src/mcp/tools/execution-flow.js +26 -0
- package/src/mcp/tools/export-graph.js +57 -0
- package/src/mcp/tools/file-deps.js +12 -0
- package/src/mcp/tools/file-exports.js +13 -0
- package/src/mcp/tools/find-cycles.js +15 -0
- package/src/mcp/tools/fn-impact.js +15 -0
- package/src/mcp/tools/impact-analysis.js +12 -0
- package/src/mcp/tools/index.js +71 -0
- package/src/mcp/tools/list-functions.js +14 -0
- package/src/mcp/tools/list-repos.js +11 -0
- package/src/mcp/tools/module-map.js +6 -0
- package/src/mcp/tools/node-roles.js +14 -0
- package/src/mcp/tools/path.js +12 -0
- package/src/mcp/tools/query.js +30 -0
- package/src/mcp/tools/semantic-search.js +65 -0
- package/src/mcp/tools/sequence.js +17 -0
- package/src/mcp/tools/structure.js +15 -0
- package/src/mcp/tools/symbol-children.js +14 -0
- package/src/mcp/tools/triage.js +35 -0
- package/src/mcp/tools/where.js +13 -0
- package/src/mcp.js +2 -1470
- package/src/native.js +34 -10
- package/src/parser.js +53 -2
- package/src/presentation/colors.js +44 -0
- package/src/presentation/export.js +444 -0
- package/src/presentation/result-formatter.js +21 -0
- package/src/presentation/sequence-renderer.js +43 -0
- package/src/presentation/table.js +47 -0
- package/src/presentation/viewer.js +634 -0
- package/src/queries.js +35 -2276
- package/src/resolve.js +1 -1
- package/src/sequence.js +2 -38
- package/src/shared/file-utils.js +153 -0
- package/src/shared/generators.js +125 -0
- package/src/shared/hierarchy.js +27 -0
- package/src/shared/normalize.js +59 -0
- package/src/snapshot.js +6 -5
- package/src/structure.js +15 -40
- package/src/triage.js +20 -72
- package/src/viewer.js +35 -656
- package/src/watcher.js +8 -148
- package/src/embedder.js +0 -1097
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import { cachedStmt } from './cached-stmt.js';
|
|
2
|
+
|
|
3
|
+
// ─── Prepared-statement caches (one per db instance) ────────────────────
|
|
4
|
+
const _findCalleesStmt = new WeakMap();
|
|
5
|
+
const _findCallersStmt = new WeakMap();
|
|
6
|
+
const _findDistinctCallersStmt = new WeakMap();
|
|
7
|
+
const _findAllOutgoingStmt = new WeakMap();
|
|
8
|
+
const _findAllIncomingStmt = new WeakMap();
|
|
9
|
+
const _findCalleeNamesStmt = new WeakMap();
|
|
10
|
+
const _findCallerNamesStmt = new WeakMap();
|
|
11
|
+
const _findImportTargetsStmt = new WeakMap();
|
|
12
|
+
const _findImportSourcesStmt = new WeakMap();
|
|
13
|
+
const _findImportDependentsStmt = new WeakMap();
|
|
14
|
+
const _findCrossFileCallTargetsStmt = new WeakMap();
|
|
15
|
+
const _countCrossFileCallersStmt = new WeakMap();
|
|
16
|
+
const _getClassAncestorsStmt = new WeakMap();
|
|
17
|
+
const _findIntraFileCallEdgesStmt = new WeakMap();
|
|
18
|
+
|
|
1
19
|
// ─── Call-edge queries ──────────────────────────────────────────────────
|
|
2
20
|
|
|
3
21
|
/**
|
|
@@ -8,13 +26,13 @@
|
|
|
8
26
|
* @returns {{ id: number, name: string, kind: string, file: string, line: number, end_line: number|null }[]}
|
|
9
27
|
*/
|
|
10
28
|
export function findCallees(db, nodeId) {
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
29
|
+
return cachedStmt(
|
|
30
|
+
_findCalleesStmt,
|
|
31
|
+
db,
|
|
32
|
+
`SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line, n.end_line
|
|
33
|
+
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
34
|
+
WHERE e.source_id = ? AND e.kind = 'calls'`,
|
|
35
|
+
).all(nodeId);
|
|
18
36
|
}
|
|
19
37
|
|
|
20
38
|
/**
|
|
@@ -24,13 +42,13 @@ export function findCallees(db, nodeId) {
|
|
|
24
42
|
* @returns {{ id: number, name: string, kind: string, file: string, line: number }[]}
|
|
25
43
|
*/
|
|
26
44
|
export function findCallers(db, nodeId) {
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
return cachedStmt(
|
|
46
|
+
_findCallersStmt,
|
|
47
|
+
db,
|
|
48
|
+
`SELECT n.id, n.name, n.kind, n.file, n.line
|
|
49
|
+
FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
50
|
+
WHERE e.target_id = ? AND e.kind = 'calls'`,
|
|
51
|
+
).all(nodeId);
|
|
34
52
|
}
|
|
35
53
|
|
|
36
54
|
/**
|
|
@@ -40,13 +58,13 @@ export function findCallers(db, nodeId) {
|
|
|
40
58
|
* @returns {{ id: number, name: string, kind: string, file: string, line: number }[]}
|
|
41
59
|
*/
|
|
42
60
|
export function findDistinctCallers(db, nodeId) {
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
return cachedStmt(
|
|
62
|
+
_findDistinctCallersStmt,
|
|
63
|
+
db,
|
|
64
|
+
`SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line
|
|
65
|
+
FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
66
|
+
WHERE e.target_id = ? AND e.kind = 'calls'`,
|
|
67
|
+
).all(nodeId);
|
|
50
68
|
}
|
|
51
69
|
|
|
52
70
|
// ─── All-edge queries (no kind filter) ─────────────────────────────────
|
|
@@ -58,13 +76,13 @@ export function findDistinctCallers(db, nodeId) {
|
|
|
58
76
|
* @returns {{ name: string, kind: string, file: string, line: number, edge_kind: string }[]}
|
|
59
77
|
*/
|
|
60
78
|
export function findAllOutgoingEdges(db, nodeId) {
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
return cachedStmt(
|
|
80
|
+
_findAllOutgoingStmt,
|
|
81
|
+
db,
|
|
82
|
+
`SELECT n.name, n.kind, n.file, n.line, e.kind AS edge_kind
|
|
83
|
+
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
84
|
+
WHERE e.source_id = ?`,
|
|
85
|
+
).all(nodeId);
|
|
68
86
|
}
|
|
69
87
|
|
|
70
88
|
/**
|
|
@@ -74,13 +92,13 @@ export function findAllOutgoingEdges(db, nodeId) {
|
|
|
74
92
|
* @returns {{ name: string, kind: string, file: string, line: number, edge_kind: string }[]}
|
|
75
93
|
*/
|
|
76
94
|
export function findAllIncomingEdges(db, nodeId) {
|
|
77
|
-
return
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
return cachedStmt(
|
|
96
|
+
_findAllIncomingStmt,
|
|
97
|
+
db,
|
|
98
|
+
`SELECT n.name, n.kind, n.file, n.line, e.kind AS edge_kind
|
|
99
|
+
FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
100
|
+
WHERE e.target_id = ?`,
|
|
101
|
+
).all(nodeId);
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
// ─── Name-only callee/caller lookups (for embedder) ────────────────────
|
|
@@ -92,13 +110,14 @@ export function findAllIncomingEdges(db, nodeId) {
|
|
|
92
110
|
* @returns {string[]}
|
|
93
111
|
*/
|
|
94
112
|
export function findCalleeNames(db, nodeId) {
|
|
95
|
-
return
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
return cachedStmt(
|
|
114
|
+
_findCalleeNamesStmt,
|
|
115
|
+
db,
|
|
116
|
+
`SELECT DISTINCT n.name
|
|
117
|
+
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
118
|
+
WHERE e.source_id = ? AND e.kind = 'calls'
|
|
119
|
+
ORDER BY n.name`,
|
|
120
|
+
)
|
|
102
121
|
.all(nodeId)
|
|
103
122
|
.map((r) => r.name);
|
|
104
123
|
}
|
|
@@ -110,13 +129,14 @@ export function findCalleeNames(db, nodeId) {
|
|
|
110
129
|
* @returns {string[]}
|
|
111
130
|
*/
|
|
112
131
|
export function findCallerNames(db, nodeId) {
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
return cachedStmt(
|
|
133
|
+
_findCallerNamesStmt,
|
|
134
|
+
db,
|
|
135
|
+
`SELECT DISTINCT n.name
|
|
136
|
+
FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
137
|
+
WHERE e.target_id = ? AND e.kind = 'calls'
|
|
138
|
+
ORDER BY n.name`,
|
|
139
|
+
)
|
|
120
140
|
.all(nodeId)
|
|
121
141
|
.map((r) => r.name);
|
|
122
142
|
}
|
|
@@ -130,13 +150,13 @@ export function findCallerNames(db, nodeId) {
|
|
|
130
150
|
* @returns {{ file: string, edge_kind: string }[]}
|
|
131
151
|
*/
|
|
132
152
|
export function findImportTargets(db, nodeId) {
|
|
133
|
-
return
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
return cachedStmt(
|
|
154
|
+
_findImportTargetsStmt,
|
|
155
|
+
db,
|
|
156
|
+
`SELECT n.file, e.kind AS edge_kind
|
|
157
|
+
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
158
|
+
WHERE e.source_id = ? AND e.kind IN ('imports', 'imports-type')`,
|
|
159
|
+
).all(nodeId);
|
|
140
160
|
}
|
|
141
161
|
|
|
142
162
|
/**
|
|
@@ -146,13 +166,13 @@ export function findImportTargets(db, nodeId) {
|
|
|
146
166
|
* @returns {{ file: string, edge_kind: string }[]}
|
|
147
167
|
*/
|
|
148
168
|
export function findImportSources(db, nodeId) {
|
|
149
|
-
return
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
169
|
+
return cachedStmt(
|
|
170
|
+
_findImportSourcesStmt,
|
|
171
|
+
db,
|
|
172
|
+
`SELECT n.file, e.kind AS edge_kind
|
|
173
|
+
FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
174
|
+
WHERE e.target_id = ? AND e.kind IN ('imports', 'imports-type')`,
|
|
175
|
+
).all(nodeId);
|
|
156
176
|
}
|
|
157
177
|
|
|
158
178
|
/**
|
|
@@ -163,12 +183,12 @@ export function findImportSources(db, nodeId) {
|
|
|
163
183
|
* @returns {object[]}
|
|
164
184
|
*/
|
|
165
185
|
export function findImportDependents(db, nodeId) {
|
|
166
|
-
return
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
186
|
+
return cachedStmt(
|
|
187
|
+
_findImportDependentsStmt,
|
|
188
|
+
db,
|
|
189
|
+
`SELECT n.* FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
190
|
+
WHERE e.target_id = ? AND e.kind IN ('imports', 'imports-type')`,
|
|
191
|
+
).all(nodeId);
|
|
172
192
|
}
|
|
173
193
|
|
|
174
194
|
// ─── Cross-file and hierarchy queries ──────────────────────────────────
|
|
@@ -182,13 +202,14 @@ export function findImportDependents(db, nodeId) {
|
|
|
182
202
|
*/
|
|
183
203
|
export function findCrossFileCallTargets(db, file) {
|
|
184
204
|
return new Set(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
205
|
+
cachedStmt(
|
|
206
|
+
_findCrossFileCallTargetsStmt,
|
|
207
|
+
db,
|
|
208
|
+
`SELECT DISTINCT e.target_id FROM edges e
|
|
209
|
+
JOIN nodes caller ON e.source_id = caller.id
|
|
210
|
+
JOIN nodes target ON e.target_id = target.id
|
|
211
|
+
WHERE target.file = ? AND caller.file != ? AND e.kind = 'calls'`,
|
|
212
|
+
)
|
|
192
213
|
.all(file, file)
|
|
193
214
|
.map((r) => r.target_id),
|
|
194
215
|
);
|
|
@@ -203,12 +224,12 @@ export function findCrossFileCallTargets(db, file) {
|
|
|
203
224
|
* @returns {number}
|
|
204
225
|
*/
|
|
205
226
|
export function countCrossFileCallers(db, nodeId, file) {
|
|
206
|
-
return
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
227
|
+
return cachedStmt(
|
|
228
|
+
_countCrossFileCallersStmt,
|
|
229
|
+
db,
|
|
230
|
+
`SELECT COUNT(*) AS cnt FROM edges e JOIN nodes n ON e.source_id = n.id
|
|
231
|
+
WHERE e.target_id = ? AND e.kind = 'calls' AND n.file != ?`,
|
|
232
|
+
).get(nodeId, file).cnt;
|
|
212
233
|
}
|
|
213
234
|
|
|
214
235
|
/**
|
|
@@ -220,14 +241,15 @@ export function countCrossFileCallers(db, nodeId, file) {
|
|
|
220
241
|
export function getClassHierarchy(db, classNodeId) {
|
|
221
242
|
const ancestors = new Set();
|
|
222
243
|
const queue = [classNodeId];
|
|
244
|
+
const stmt = cachedStmt(
|
|
245
|
+
_getClassAncestorsStmt,
|
|
246
|
+
db,
|
|
247
|
+
`SELECT n.id, n.name FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
248
|
+
WHERE e.source_id = ? AND e.kind = 'extends'`,
|
|
249
|
+
);
|
|
223
250
|
while (queue.length > 0) {
|
|
224
251
|
const current = queue.shift();
|
|
225
|
-
const parents =
|
|
226
|
-
.prepare(
|
|
227
|
-
`SELECT n.id, n.name FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
228
|
-
WHERE e.source_id = ? AND e.kind = 'extends'`,
|
|
229
|
-
)
|
|
230
|
-
.all(current);
|
|
252
|
+
const parents = stmt.all(current);
|
|
231
253
|
for (const p of parents) {
|
|
232
254
|
if (!ancestors.has(p.id)) {
|
|
233
255
|
ancestors.add(p.id);
|
|
@@ -246,14 +268,14 @@ export function getClassHierarchy(db, classNodeId) {
|
|
|
246
268
|
* @returns {{ caller_name: string, callee_name: string }[]}
|
|
247
269
|
*/
|
|
248
270
|
export function findIntraFileCallEdges(db, file) {
|
|
249
|
-
return
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
271
|
+
return cachedStmt(
|
|
272
|
+
_findIntraFileCallEdgesStmt,
|
|
273
|
+
db,
|
|
274
|
+
`SELECT caller.name AS caller_name, callee.name AS callee_name
|
|
275
|
+
FROM edges e
|
|
276
|
+
JOIN nodes caller ON e.source_id = caller.id
|
|
277
|
+
JOIN nodes callee ON e.target_id = callee.id
|
|
278
|
+
WHERE caller.file = ? AND callee.file = ? AND e.kind = 'calls'
|
|
279
|
+
ORDER BY caller.line`,
|
|
280
|
+
).all(file, file);
|
|
259
281
|
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { cachedStmt } from './cached-stmt.js';
|
|
2
|
+
|
|
3
|
+
// ─── Statement caches (one prepared statement per db instance) ────────────
|
|
4
|
+
const _hasEmbeddingsStmt = new WeakMap();
|
|
5
|
+
const _getEmbeddingCountStmt = new WeakMap();
|
|
6
|
+
const _getEmbeddingMetaStmt = new WeakMap();
|
|
7
|
+
|
|
1
8
|
/**
|
|
2
9
|
* Check whether the embeddings table has data.
|
|
3
10
|
* @param {object} db
|
|
@@ -5,7 +12,7 @@
|
|
|
5
12
|
*/
|
|
6
13
|
export function hasEmbeddings(db) {
|
|
7
14
|
try {
|
|
8
|
-
return !!db
|
|
15
|
+
return !!cachedStmt(_hasEmbeddingsStmt, db, 'SELECT 1 FROM embeddings LIMIT 1').get();
|
|
9
16
|
} catch {
|
|
10
17
|
return false;
|
|
11
18
|
}
|
|
@@ -18,7 +25,7 @@ export function hasEmbeddings(db) {
|
|
|
18
25
|
*/
|
|
19
26
|
export function getEmbeddingCount(db) {
|
|
20
27
|
try {
|
|
21
|
-
return db
|
|
28
|
+
return cachedStmt(_getEmbeddingCountStmt, db, 'SELECT COUNT(*) AS c FROM embeddings').get().c;
|
|
22
29
|
} catch {
|
|
23
30
|
return 0;
|
|
24
31
|
}
|
|
@@ -32,7 +39,11 @@ export function getEmbeddingCount(db) {
|
|
|
32
39
|
*/
|
|
33
40
|
export function getEmbeddingMeta(db, key) {
|
|
34
41
|
try {
|
|
35
|
-
const row =
|
|
42
|
+
const row = cachedStmt(
|
|
43
|
+
_getEmbeddingMetaStmt,
|
|
44
|
+
db,
|
|
45
|
+
'SELECT value FROM embedding_meta WHERE key = ?',
|
|
46
|
+
).get(key);
|
|
36
47
|
return row?.value;
|
|
37
48
|
} catch {
|
|
38
49
|
return undefined;
|
|
@@ -1,12 +1,25 @@
|
|
|
1
|
+
import { CORE_SYMBOL_KINDS } from '../../kinds.js';
|
|
2
|
+
import { cachedStmt } from './cached-stmt.js';
|
|
3
|
+
|
|
4
|
+
// ─── Statement caches (one prepared statement per db instance) ────────────
|
|
5
|
+
const _getCallableNodesStmt = new WeakMap();
|
|
6
|
+
const _getCallEdgesStmt = new WeakMap();
|
|
7
|
+
const _getFileNodesAllStmt = new WeakMap();
|
|
8
|
+
const _getImportEdgesStmt = new WeakMap();
|
|
9
|
+
|
|
10
|
+
const CALLABLE_KINDS_SQL = CORE_SYMBOL_KINDS.map((k) => `'${k}'`).join(',');
|
|
11
|
+
|
|
1
12
|
/**
|
|
2
|
-
* Get callable nodes (
|
|
13
|
+
* Get callable nodes (all core symbol kinds) for graph construction.
|
|
3
14
|
* @param {object} db
|
|
4
15
|
* @returns {{ id: number, name: string, kind: string, file: string }[]}
|
|
5
16
|
*/
|
|
6
17
|
export function getCallableNodes(db) {
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
return cachedStmt(
|
|
19
|
+
_getCallableNodesStmt,
|
|
20
|
+
db,
|
|
21
|
+
`SELECT id, name, kind, file FROM nodes WHERE kind IN (${CALLABLE_KINDS_SQL})`,
|
|
22
|
+
).all();
|
|
10
23
|
}
|
|
11
24
|
|
|
12
25
|
/**
|
|
@@ -15,7 +28,11 @@ export function getCallableNodes(db) {
|
|
|
15
28
|
* @returns {{ source_id: number, target_id: number }[]}
|
|
16
29
|
*/
|
|
17
30
|
export function getCallEdges(db) {
|
|
18
|
-
return
|
|
31
|
+
return cachedStmt(
|
|
32
|
+
_getCallEdgesStmt,
|
|
33
|
+
db,
|
|
34
|
+
"SELECT source_id, target_id FROM edges WHERE kind = 'calls'",
|
|
35
|
+
).all();
|
|
19
36
|
}
|
|
20
37
|
|
|
21
38
|
/**
|
|
@@ -24,7 +41,11 @@ export function getCallEdges(db) {
|
|
|
24
41
|
* @returns {{ id: number, name: string, file: string }[]}
|
|
25
42
|
*/
|
|
26
43
|
export function getFileNodesAll(db) {
|
|
27
|
-
return
|
|
44
|
+
return cachedStmt(
|
|
45
|
+
_getFileNodesAllStmt,
|
|
46
|
+
db,
|
|
47
|
+
"SELECT id, name, file FROM nodes WHERE kind = 'file'",
|
|
48
|
+
).all();
|
|
28
49
|
}
|
|
29
50
|
|
|
30
51
|
/**
|
|
@@ -33,7 +54,9 @@ export function getFileNodesAll(db) {
|
|
|
33
54
|
* @returns {{ source_id: number, target_id: number }[]}
|
|
34
55
|
*/
|
|
35
56
|
export function getImportEdges(db) {
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
57
|
+
return cachedStmt(
|
|
58
|
+
_getImportEdgesStmt,
|
|
59
|
+
db,
|
|
60
|
+
"SELECT source_id, target_id FROM edges WHERE kind IN ('imports','imports-type')",
|
|
61
|
+
).all();
|
|
39
62
|
}
|