@optave/codegraph 3.4.1 → 3.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/README.md +50 -28
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +119 -127
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/rules/javascript.d.ts.map +1 -1
- package/dist/ast-analysis/rules/javascript.js +1 -0
- package/dist/ast-analysis/rules/javascript.js.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js +116 -35
- package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.js +11 -13
- package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
- package/dist/db/better-sqlite3.d.ts +3 -0
- package/dist/db/better-sqlite3.d.ts.map +1 -0
- package/dist/db/better-sqlite3.js +19 -0
- package/dist/db/better-sqlite3.js.map +1 -0
- package/dist/db/connection.d.ts +25 -4
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +125 -23
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +40 -32
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/query-builder.d.ts +5 -5
- package/dist/db/query-builder.d.ts.map +1 -1
- package/dist/db/query-builder.js +20 -4
- package/dist/db/query-builder.js.map +1 -1
- package/dist/db/repository/index.d.ts +1 -0
- package/dist/db/repository/index.d.ts.map +1 -1
- package/dist/db/repository/index.js +1 -0
- package/dist/db/repository/index.js.map +1 -1
- package/dist/db/repository/native-repository.d.ts +58 -0
- package/dist/db/repository/native-repository.d.ts.map +1 -0
- package/dist/db/repository/native-repository.js +261 -0
- package/dist/db/repository/native-repository.js.map +1 -0
- package/dist/db/repository/nodes.d.ts +4 -4
- package/dist/db/repository/nodes.d.ts.map +1 -1
- package/dist/db/repository/nodes.js +6 -6
- package/dist/db/repository/nodes.js.map +1 -1
- package/dist/domain/analysis/context.d.ts.map +1 -1
- package/dist/domain/analysis/context.js +51 -66
- package/dist/domain/analysis/context.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +62 -70
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/diff-impact.d.ts +9 -7
- package/dist/domain/analysis/diff-impact.d.ts.map +1 -1
- package/dist/domain/analysis/exports.d.ts.map +1 -1
- package/dist/domain/analysis/exports.js +29 -33
- package/dist/domain/analysis/exports.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts +15 -17
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +35 -65
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +91 -6
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/query-helpers.d.ts +20 -0
- package/dist/domain/analysis/query-helpers.d.ts.map +1 -0
- package/dist/domain/analysis/query-helpers.js +27 -0
- package/dist/domain/analysis/query-helpers.js.map +1 -0
- package/dist/domain/graph/builder/context.d.ts +2 -1
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js +1 -0
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +15 -9
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +3 -2
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +95 -7
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +101 -57
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.js +33 -3
- package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.js +70 -6
- package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +36 -14
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +130 -88
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.js +124 -16
- package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +3 -2
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/resolve.d.ts +0 -4
- package/dist/domain/graph/resolve.d.ts.map +1 -1
- package/dist/domain/graph/resolve.js +32 -48
- package/dist/domain/graph/resolve.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +12 -12
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +1 -1
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +165 -101
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/search/cli-formatter.d.ts.map +1 -1
- package/dist/domain/search/search/cli-formatter.js +88 -83
- package/dist/domain/search/search/cli-formatter.js.map +1 -1
- package/dist/extractors/bash.d.ts +6 -0
- package/dist/extractors/bash.d.ts.map +1 -0
- package/dist/extractors/bash.js +91 -0
- package/dist/extractors/bash.js.map +1 -0
- package/dist/extractors/c.d.ts +6 -0
- package/dist/extractors/c.d.ts.map +1 -0
- package/dist/extractors/c.js +204 -0
- package/dist/extractors/c.js.map +1 -0
- package/dist/extractors/cpp.d.ts +6 -0
- package/dist/extractors/cpp.d.ts.map +1 -0
- package/dist/extractors/cpp.js +283 -0
- package/dist/extractors/cpp.js.map +1 -0
- package/dist/extractors/csharp.d.ts.map +1 -1
- package/dist/extractors/csharp.js +42 -54
- package/dist/extractors/csharp.js.map +1 -1
- package/dist/extractors/go.d.ts.map +1 -1
- package/dist/extractors/go.js +126 -130
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/hcl.js +6 -6
- package/dist/extractors/hcl.js.map +1 -1
- package/dist/extractors/helpers.d.ts +32 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +74 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/index.d.ts +6 -0
- package/dist/extractors/index.d.ts.map +1 -1
- package/dist/extractors/index.js +6 -0
- package/dist/extractors/index.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +32 -47
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +359 -330
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.d.ts +6 -0
- package/dist/extractors/kotlin.d.ts.map +1 -0
- package/dist/extractors/kotlin.js +275 -0
- package/dist/extractors/kotlin.js.map +1 -0
- package/dist/extractors/php.d.ts.map +1 -1
- package/dist/extractors/php.js +39 -44
- package/dist/extractors/php.js.map +1 -1
- package/dist/extractors/python.d.ts.map +1 -1
- package/dist/extractors/python.js +75 -93
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/ruby.js +6 -13
- package/dist/extractors/ruby.js.map +1 -1
- package/dist/extractors/rust.d.ts.map +1 -1
- package/dist/extractors/rust.js +58 -82
- package/dist/extractors/rust.js.map +1 -1
- package/dist/extractors/scala.d.ts +6 -0
- package/dist/extractors/scala.d.ts.map +1 -0
- package/dist/extractors/scala.js +269 -0
- package/dist/extractors/scala.js.map +1 -0
- package/dist/extractors/swift.d.ts +6 -0
- package/dist/extractors/swift.d.ts.map +1 -0
- package/dist/extractors/swift.js +275 -0
- package/dist/extractors/swift.js.map +1 -0
- package/dist/features/ast.d.ts +16 -1
- package/dist/features/ast.d.ts.map +1 -1
- package/dist/features/ast.js +45 -23
- package/dist/features/ast.js.map +1 -1
- package/dist/features/audit.d.ts.map +1 -1
- package/dist/features/audit.js +17 -21
- package/dist/features/audit.js.map +1 -1
- package/dist/features/branch-compare.d.ts.map +1 -1
- package/dist/features/branch-compare.js +50 -4
- package/dist/features/branch-compare.js.map +1 -1
- package/dist/features/cfg.d.ts +7 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +118 -62
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +79 -62
- package/dist/features/check.js.map +1 -1
- package/dist/features/complexity-query.d.ts.map +1 -1
- package/dist/features/complexity-query.js +142 -137
- package/dist/features/complexity-query.js.map +1 -1
- package/dist/features/complexity.d.ts +7 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +62 -1
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts +7 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +356 -188
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/graph-enrichment.d.ts.map +1 -1
- package/dist/features/graph-enrichment.js +117 -104
- package/dist/features/graph-enrichment.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +25 -4
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/snapshot.d.ts.map +1 -1
- package/dist/features/snapshot.js +2 -1
- package/dist/features/snapshot.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +29 -4
- package/dist/features/structure-query.js.map +1 -1
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +35 -15
- package/dist/features/structure.js.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.js +88 -73
- package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
- package/dist/graph/algorithms/leiden/index.js +43 -28
- package/dist/graph/algorithms/leiden/index.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +90 -104
- package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
- package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/partition.js +89 -106
- package/dist/graph/algorithms/leiden/partition.js.map +1 -1
- package/dist/graph/model.d.ts +2 -0
- package/dist/graph/model.d.ts.map +1 -1
- package/dist/graph/model.js +20 -8
- package/dist/graph/model.js.map +1 -1
- package/dist/infrastructure/config.d.ts +0 -8
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +73 -62
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +0 -8
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +12 -14
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +47 -45
- package/dist/mcp/server.js.map +1 -1
- package/dist/presentation/audit.d.ts.map +1 -1
- package/dist/presentation/audit.js +61 -57
- package/dist/presentation/audit.js.map +1 -1
- package/dist/presentation/branch-compare.d.ts.map +1 -1
- package/dist/presentation/branch-compare.js +56 -38
- package/dist/presentation/branch-compare.js.map +1 -1
- package/dist/presentation/check.d.ts.map +1 -1
- package/dist/presentation/check.js +30 -32
- package/dist/presentation/check.js.map +1 -1
- package/dist/presentation/colors.d.ts.map +1 -1
- package/dist/presentation/colors.js +2 -0
- package/dist/presentation/colors.js.map +1 -1
- package/dist/presentation/complexity.d.ts.map +1 -1
- package/dist/presentation/complexity.js +25 -19
- package/dist/presentation/complexity.js.map +1 -1
- package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
- package/dist/presentation/queries-cli/exports.js +15 -15
- package/dist/presentation/queries-cli/exports.js.map +1 -1
- package/dist/presentation/queries-cli/impact.d.ts.map +1 -1
- package/dist/presentation/queries-cli/impact.js +29 -19
- package/dist/presentation/queries-cli/impact.js.map +1 -1
- package/dist/types.d.ts +406 -3
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-c.wasm +0 -0
- package/grammars/tree-sitter-cpp.wasm +0 -0
- package/grammars/tree-sitter-kotlin.wasm +0 -0
- package/grammars/tree-sitter-scala.wasm +0 -0
- package/grammars/tree-sitter-swift.wasm +0 -0
- package/package.json +67 -11
- package/src/ast-analysis/engine.ts +147 -138
- package/src/ast-analysis/rules/javascript.ts +1 -0
- package/src/ast-analysis/visitors/ast-store-visitor.ts +116 -34
- package/src/ast-analysis/visitors/complexity-visitor.ts +11 -11
- package/src/db/better-sqlite3.ts +20 -0
- package/src/db/connection.ts +148 -26
- package/src/db/index.ts +4 -1
- package/src/db/migrations.ts +38 -32
- package/src/db/query-builder.ts +30 -5
- package/src/db/repository/index.ts +1 -0
- package/src/db/repository/native-repository.ts +361 -0
- package/src/db/repository/nodes.ts +7 -3
- package/src/domain/analysis/context.ts +73 -75
- package/src/domain/analysis/dependencies.ts +78 -68
- package/src/domain/analysis/exports.ts +45 -34
- package/src/domain/analysis/fn-impact.ts +67 -64
- package/src/domain/analysis/module-map.ts +103 -8
- package/src/domain/analysis/query-helpers.ts +35 -0
- package/src/domain/graph/builder/context.ts +2 -0
- package/src/domain/graph/builder/helpers.ts +12 -6
- package/src/domain/graph/builder/incremental.ts +3 -2
- package/src/domain/graph/builder/pipeline.ts +98 -6
- package/src/domain/graph/builder/stages/build-edges.ts +116 -83
- package/src/domain/graph/builder/stages/build-structure.ts +46 -8
- package/src/domain/graph/builder/stages/collect-files.ts +83 -6
- package/src/domain/graph/builder/stages/detect-changes.ts +44 -21
- package/src/domain/graph/builder/stages/finalize.ts +172 -109
- package/src/domain/graph/builder/stages/insert-nodes.ts +147 -17
- package/src/domain/graph/builder/stages/resolve-imports.ts +3 -2
- package/src/domain/graph/resolve.ts +34 -46
- package/src/domain/graph/watcher.ts +12 -14
- package/src/domain/parser.ts +169 -97
- package/src/domain/search/search/cli-formatter.ts +121 -94
- package/src/extractors/bash.ts +97 -0
- package/src/extractors/c.ts +212 -0
- package/src/extractors/cpp.ts +298 -0
- package/src/extractors/csharp.ts +53 -56
- package/src/extractors/go.ts +152 -134
- package/src/extractors/hcl.ts +6 -6
- package/src/extractors/helpers.ts +93 -1
- package/src/extractors/index.ts +6 -0
- package/src/extractors/java.ts +43 -48
- package/src/extractors/javascript.ts +382 -317
- package/src/extractors/kotlin.ts +293 -0
- package/src/extractors/php.ts +46 -40
- package/src/extractors/python.ts +81 -104
- package/src/extractors/ruby.ts +6 -13
- package/src/extractors/rust.ts +65 -84
- package/src/extractors/scala.ts +285 -0
- package/src/extractors/swift.ts +293 -0
- package/src/features/ast.ts +74 -24
- package/src/features/audit.ts +24 -20
- package/src/features/branch-compare.ts +54 -5
- package/src/features/cfg.ts +158 -65
- package/src/features/check.ts +90 -74
- package/src/features/complexity-query.ts +181 -163
- package/src/features/complexity.ts +64 -1
- package/src/features/dataflow.ts +462 -217
- package/src/features/graph-enrichment.ts +161 -117
- package/src/features/sequence.ts +27 -4
- package/src/features/snapshot.ts +2 -1
- package/src/features/structure-query.ts +43 -4
- package/src/features/structure.ts +50 -22
- package/src/graph/algorithms/leiden/adapter.ts +126 -71
- package/src/graph/algorithms/leiden/index.ts +67 -28
- package/src/graph/algorithms/leiden/optimiser.ts +114 -105
- package/src/graph/algorithms/leiden/partition.ts +131 -98
- package/src/graph/model.ts +19 -7
- package/src/infrastructure/config.ts +60 -58
- package/src/infrastructure/registry.ts +17 -14
- package/src/mcp/server.ts +48 -47
- package/src/presentation/audit.ts +72 -67
- package/src/presentation/branch-compare.ts +54 -50
- package/src/presentation/check.ts +34 -34
- package/src/presentation/colors.ts +2 -0
- package/src/presentation/complexity.ts +39 -33
- package/src/presentation/queries-cli/exports.ts +17 -17
- package/src/presentation/queries-cli/impact.ts +30 -22
- package/src/types.ts +458 -3
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Call,
|
|
3
|
+
ExtractorOutput,
|
|
4
|
+
SubDeclaration,
|
|
5
|
+
TreeSitterNode,
|
|
6
|
+
TreeSitterTree,
|
|
7
|
+
} from '../types.js';
|
|
8
|
+
import { extractModifierVisibility, findChild, nodeEndLine } from './helpers.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Extract symbols from Swift files.
|
|
12
|
+
*/
|
|
13
|
+
export function extractSwiftSymbols(tree: TreeSitterTree, _filePath: string): ExtractorOutput {
|
|
14
|
+
const ctx: ExtractorOutput = {
|
|
15
|
+
definitions: [],
|
|
16
|
+
calls: [],
|
|
17
|
+
imports: [],
|
|
18
|
+
classes: [],
|
|
19
|
+
exports: [],
|
|
20
|
+
typeMap: new Map(),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
walkSwiftNode(tree.rootNode, ctx);
|
|
24
|
+
return ctx;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function walkSwiftNode(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
28
|
+
switch (node.type) {
|
|
29
|
+
case 'class_declaration':
|
|
30
|
+
handleSwiftClassDecl(node, ctx);
|
|
31
|
+
break;
|
|
32
|
+
case 'protocol_declaration':
|
|
33
|
+
handleSwiftProtocolDecl(node, ctx);
|
|
34
|
+
break;
|
|
35
|
+
case 'function_declaration':
|
|
36
|
+
handleSwiftFunctionDecl(node, ctx);
|
|
37
|
+
break;
|
|
38
|
+
case 'import_declaration':
|
|
39
|
+
handleSwiftImportDecl(node, ctx);
|
|
40
|
+
break;
|
|
41
|
+
case 'call_expression':
|
|
42
|
+
handleSwiftCallExpression(node, ctx);
|
|
43
|
+
break;
|
|
44
|
+
case 'property_declaration':
|
|
45
|
+
handleSwiftPropertyDecl(node, ctx);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
50
|
+
const child = node.child(i);
|
|
51
|
+
if (child) walkSwiftNode(child, ctx);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ── Walk-path per-node-type handlers ────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
function hasKeywordChild(node: TreeSitterNode, keyword: string): boolean {
|
|
58
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
59
|
+
const child = node.child(i);
|
|
60
|
+
if (child && child.text === keyword) return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function handleSwiftClassDecl(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
66
|
+
const isStruct = hasKeywordChild(node, 'struct');
|
|
67
|
+
const isEnum = hasKeywordChild(node, 'enum');
|
|
68
|
+
|
|
69
|
+
// Name is a type_identifier direct child
|
|
70
|
+
const nameNode = findChild(node, 'type_identifier');
|
|
71
|
+
if (!nameNode) return;
|
|
72
|
+
const name = nameNode.text;
|
|
73
|
+
|
|
74
|
+
const kind = isEnum ? 'enum' : isStruct ? 'struct' : 'class';
|
|
75
|
+
|
|
76
|
+
const children: SubDeclaration[] = [];
|
|
77
|
+
|
|
78
|
+
if (isEnum) {
|
|
79
|
+
// Enum cases: enum_entry > simple_identifier, inside enum_class_body
|
|
80
|
+
const body = findChild(node, 'enum_class_body');
|
|
81
|
+
if (body) {
|
|
82
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
83
|
+
const child = body.child(i);
|
|
84
|
+
if (child && child.type === 'enum_entry') {
|
|
85
|
+
const entryName = findChild(child, 'simple_identifier');
|
|
86
|
+
if (entryName) {
|
|
87
|
+
children.push({
|
|
88
|
+
name: entryName.text,
|
|
89
|
+
kind: 'constant',
|
|
90
|
+
line: child.startPosition.row + 1,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
// Extract properties from class_body
|
|
98
|
+
const body = findChild(node, 'class_body');
|
|
99
|
+
if (body) {
|
|
100
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
101
|
+
const child = body.child(i);
|
|
102
|
+
if (child && child.type === 'property_declaration') {
|
|
103
|
+
const pattern = findChild(child, 'pattern');
|
|
104
|
+
if (pattern) {
|
|
105
|
+
const propName = findChild(pattern, 'simple_identifier');
|
|
106
|
+
if (propName) {
|
|
107
|
+
children.push({
|
|
108
|
+
name: propName.text,
|
|
109
|
+
kind: 'property',
|
|
110
|
+
line: child.startPosition.row + 1,
|
|
111
|
+
visibility: extractModifierVisibility(child),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
ctx.definitions.push({
|
|
121
|
+
name,
|
|
122
|
+
kind,
|
|
123
|
+
line: node.startPosition.row + 1,
|
|
124
|
+
endLine: nodeEndLine(node),
|
|
125
|
+
children: children.length > 0 ? children : undefined,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Methods inside class_body or enum_class_body
|
|
129
|
+
const body = findChild(node, 'class_body') || findChild(node, 'enum_class_body');
|
|
130
|
+
if (body) {
|
|
131
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
132
|
+
const child = body.child(i);
|
|
133
|
+
if (child && child.type === 'function_declaration') {
|
|
134
|
+
const methName = findChild(child, 'simple_identifier');
|
|
135
|
+
if (methName) {
|
|
136
|
+
ctx.definitions.push({
|
|
137
|
+
name: `${name}.${methName.text}`,
|
|
138
|
+
kind: 'method',
|
|
139
|
+
line: child.startPosition.row + 1,
|
|
140
|
+
endLine: child.endPosition.row + 1,
|
|
141
|
+
visibility: extractModifierVisibility(child),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Inheritance: inheritance_specifier nodes are DIRECT children of class_declaration
|
|
149
|
+
// First specifier is the superclass (extends), rest are protocol conformances (implements)
|
|
150
|
+
let first = true;
|
|
151
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
152
|
+
const child = node.child(i);
|
|
153
|
+
if (!child || child.type !== 'inheritance_specifier') continue;
|
|
154
|
+
// inheritance_specifier > user_type > type_identifier
|
|
155
|
+
const userType = findChild(child, 'user_type');
|
|
156
|
+
if (userType) {
|
|
157
|
+
const typeId = findChild(userType, 'type_identifier');
|
|
158
|
+
if (typeId) {
|
|
159
|
+
if (first) {
|
|
160
|
+
ctx.classes.push({
|
|
161
|
+
name,
|
|
162
|
+
extends: typeId.text,
|
|
163
|
+
line: node.startPosition.row + 1,
|
|
164
|
+
});
|
|
165
|
+
first = false;
|
|
166
|
+
} else {
|
|
167
|
+
ctx.classes.push({
|
|
168
|
+
name,
|
|
169
|
+
implements: typeId.text,
|
|
170
|
+
line: node.startPosition.row + 1,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function handleSwiftProtocolDecl(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
179
|
+
const nameNode = findChild(node, 'type_identifier');
|
|
180
|
+
if (!nameNode) return;
|
|
181
|
+
const name = nameNode.text;
|
|
182
|
+
|
|
183
|
+
ctx.definitions.push({
|
|
184
|
+
name,
|
|
185
|
+
kind: 'interface',
|
|
186
|
+
line: node.startPosition.row + 1,
|
|
187
|
+
endLine: nodeEndLine(node),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Methods inside protocol_body or class_body
|
|
191
|
+
const body = findChild(node, 'protocol_body') || findChild(node, 'class_body');
|
|
192
|
+
if (body) {
|
|
193
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
194
|
+
const child = body.child(i);
|
|
195
|
+
if (child && child.type === 'function_declaration') {
|
|
196
|
+
const methName = findChild(child, 'simple_identifier');
|
|
197
|
+
if (methName) {
|
|
198
|
+
ctx.definitions.push({
|
|
199
|
+
name: `${name}.${methName.text}`,
|
|
200
|
+
kind: 'method',
|
|
201
|
+
line: child.startPosition.row + 1,
|
|
202
|
+
endLine: child.endPosition.row + 1,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function handleSwiftFunctionDecl(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
211
|
+
// Skip methods already emitted by class/protocol handlers
|
|
212
|
+
if (
|
|
213
|
+
node.parent?.type === 'class_body' ||
|
|
214
|
+
node.parent?.type === 'protocol_body' ||
|
|
215
|
+
node.parent?.type === 'enum_class_body'
|
|
216
|
+
) {
|
|
217
|
+
if (
|
|
218
|
+
node.parent.parent?.type === 'class_declaration' ||
|
|
219
|
+
node.parent.parent?.type === 'protocol_declaration'
|
|
220
|
+
) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const nameNode = findChild(node, 'simple_identifier');
|
|
225
|
+
if (!nameNode) return;
|
|
226
|
+
ctx.definitions.push({
|
|
227
|
+
name: nameNode.text,
|
|
228
|
+
kind: 'function',
|
|
229
|
+
line: node.startPosition.row + 1,
|
|
230
|
+
endLine: nodeEndLine(node),
|
|
231
|
+
visibility: extractModifierVisibility(node),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function handleSwiftImportDecl(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
236
|
+
const identNode = findChild(node, 'identifier');
|
|
237
|
+
if (!identNode) return;
|
|
238
|
+
const source = identNode.text;
|
|
239
|
+
ctx.imports.push({
|
|
240
|
+
source,
|
|
241
|
+
names: [source],
|
|
242
|
+
line: node.startPosition.row + 1,
|
|
243
|
+
swiftImport: true,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function handleSwiftCallExpression(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
248
|
+
const funcNode = node.child(0);
|
|
249
|
+
if (!funcNode) return;
|
|
250
|
+
const call: Call = { name: '', line: node.startPosition.row + 1 };
|
|
251
|
+
if (funcNode.type === 'navigation_expression') {
|
|
252
|
+
// obj.method(...)
|
|
253
|
+
const lastChild = funcNode.child(funcNode.childCount - 1);
|
|
254
|
+
const firstChild = funcNode.child(0);
|
|
255
|
+
if (lastChild && lastChild.type === 'simple_identifier' && firstChild) {
|
|
256
|
+
call.name = lastChild.text;
|
|
257
|
+
call.receiver = firstChild.text;
|
|
258
|
+
}
|
|
259
|
+
} else if (funcNode.type === 'simple_identifier') {
|
|
260
|
+
call.name = funcNode.text;
|
|
261
|
+
} else {
|
|
262
|
+
call.name = funcNode.text;
|
|
263
|
+
}
|
|
264
|
+
if (call.name) ctx.calls.push(call);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function handleSwiftPropertyDecl(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
268
|
+
// Only handle top-level properties (class properties are handled inline)
|
|
269
|
+
if (
|
|
270
|
+
node.parent?.type === 'class_body' ||
|
|
271
|
+
node.parent?.type === 'protocol_body' ||
|
|
272
|
+
node.parent?.type === 'enum_class_body'
|
|
273
|
+
) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// Skip function-local let/var bindings
|
|
277
|
+
if (node.parent?.type === 'statements' || node.parent?.type === 'function_body') {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const pattern = findChild(node, 'pattern');
|
|
281
|
+
if (!pattern) return;
|
|
282
|
+
const nameNode = findChild(pattern, 'simple_identifier');
|
|
283
|
+
if (!nameNode) return;
|
|
284
|
+
// let → constant, var → variable
|
|
285
|
+
const isLet = hasKeywordChild(node, 'let');
|
|
286
|
+
const kind = isLet ? 'constant' : 'variable';
|
|
287
|
+
ctx.definitions.push({
|
|
288
|
+
name: nameNode.text,
|
|
289
|
+
kind,
|
|
290
|
+
line: node.startPosition.row + 1,
|
|
291
|
+
endLine: nodeEndLine(node),
|
|
292
|
+
});
|
|
293
|
+
}
|
package/src/features/ast.ts
CHANGED
|
@@ -65,8 +65,81 @@ export async function buildAstNodes(
|
|
|
65
65
|
db: BetterSqlite3Database,
|
|
66
66
|
fileSymbols: Map<string, FileSymbols>,
|
|
67
67
|
_rootDir: string,
|
|
68
|
-
|
|
68
|
+
engineOpts?: {
|
|
69
|
+
nativeDb?: {
|
|
70
|
+
bulkInsertAstNodes(
|
|
71
|
+
batches: Array<{
|
|
72
|
+
file: string;
|
|
73
|
+
nodes: Array<{
|
|
74
|
+
line: number;
|
|
75
|
+
kind: string;
|
|
76
|
+
name: string;
|
|
77
|
+
text?: string | null;
|
|
78
|
+
receiver?: string | null;
|
|
79
|
+
}>;
|
|
80
|
+
}>,
|
|
81
|
+
): number;
|
|
82
|
+
};
|
|
83
|
+
suspendJsDb?: () => void;
|
|
84
|
+
resumeJsDb?: () => void;
|
|
85
|
+
},
|
|
69
86
|
): Promise<void> {
|
|
87
|
+
// ── Native bulk-insert fast path ──────────────────────────────────────
|
|
88
|
+
// Uses NativeDatabase persistent connection (Phase 6.15+).
|
|
89
|
+
// Standalone napi functions were removed in 6.17.
|
|
90
|
+
const nativeDb = engineOpts?.nativeDb;
|
|
91
|
+
if (nativeDb?.bulkInsertAstNodes) {
|
|
92
|
+
let needsJsFallback = false;
|
|
93
|
+
const batches: Array<{
|
|
94
|
+
file: string;
|
|
95
|
+
nodes: Array<{
|
|
96
|
+
line: number;
|
|
97
|
+
kind: string;
|
|
98
|
+
name: string;
|
|
99
|
+
text?: string | null;
|
|
100
|
+
receiver?: string | null;
|
|
101
|
+
}>;
|
|
102
|
+
}> = [];
|
|
103
|
+
|
|
104
|
+
for (const [relPath, symbols] of fileSymbols) {
|
|
105
|
+
if (Array.isArray(symbols.astNodes)) {
|
|
106
|
+
batches.push({
|
|
107
|
+
file: relPath,
|
|
108
|
+
nodes: symbols.astNodes.map((n) => ({
|
|
109
|
+
line: n.line,
|
|
110
|
+
kind: n.kind,
|
|
111
|
+
name: n.name,
|
|
112
|
+
text: n.text,
|
|
113
|
+
receiver: n.receiver ?? '',
|
|
114
|
+
})),
|
|
115
|
+
});
|
|
116
|
+
} else if (symbols.calls || symbols._tree) {
|
|
117
|
+
needsJsFallback = true;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!needsJsFallback) {
|
|
123
|
+
const expectedNodes = batches.reduce((s, b) => s + b.nodes.length, 0);
|
|
124
|
+
let inserted: number;
|
|
125
|
+
try {
|
|
126
|
+
engineOpts?.suspendJsDb?.();
|
|
127
|
+
inserted = nativeDb.bulkInsertAstNodes(batches);
|
|
128
|
+
} finally {
|
|
129
|
+
engineOpts?.resumeJsDb?.();
|
|
130
|
+
}
|
|
131
|
+
if (inserted === expectedNodes) {
|
|
132
|
+
debug(`AST extraction (native bulk): ${inserted} nodes stored`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
debug(
|
|
136
|
+
`AST extraction (native bulk): expected ${expectedNodes}, got ${inserted} — falling back to JS`,
|
|
137
|
+
);
|
|
138
|
+
// fall through to JS path
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ── JS fallback path ──────────────────────────────────────────────────
|
|
70
143
|
let insertStmt: ReturnType<BetterSqlite3Database['prepare']>;
|
|
71
144
|
try {
|
|
72
145
|
insertStmt = db.prepare(
|
|
@@ -93,29 +166,6 @@ export async function buildAstNodes(
|
|
|
93
166
|
nodeIdMap.set(`${row.name}|${row.kind}|${row.line}`, row.id);
|
|
94
167
|
}
|
|
95
168
|
|
|
96
|
-
// When native astNodes includes call entries, skip separate symbols.calls processing
|
|
97
|
-
// to avoid duplication. Fall back to symbols.calls for WASM or older native binaries.
|
|
98
|
-
const nativeProvidedAstNodes = Array.isArray(symbols.astNodes);
|
|
99
|
-
if (symbols.calls && !nativeProvidedAstNodes) {
|
|
100
|
-
for (const call of symbols.calls) {
|
|
101
|
-
const parentDef = findParentDef(defs, call.line);
|
|
102
|
-
let parentNodeId: number | null = null;
|
|
103
|
-
if (parentDef) {
|
|
104
|
-
parentNodeId =
|
|
105
|
-
nodeIdMap.get(`${parentDef.name}|${parentDef.kind}|${parentDef.line}`) || null;
|
|
106
|
-
}
|
|
107
|
-
allRows.push({
|
|
108
|
-
file: relPath,
|
|
109
|
-
line: call.line,
|
|
110
|
-
kind: 'call',
|
|
111
|
-
name: call.name,
|
|
112
|
-
text: call.dynamic ? `[dynamic] ${call.name}` : null,
|
|
113
|
-
receiver: call.receiver || null,
|
|
114
|
-
parentNodeId,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
169
|
if (Array.isArray(symbols.astNodes)) {
|
|
120
170
|
// Native engine provided AST nodes (may be empty for files with no AST content)
|
|
121
171
|
for (const n of symbols.astNodes) {
|
package/src/features/audit.ts
CHANGED
|
@@ -183,27 +183,8 @@ export function auditData(
|
|
|
183
183
|
let functions: unknown[];
|
|
184
184
|
try {
|
|
185
185
|
if (explained.kind === 'file') {
|
|
186
|
-
|
|
187
|
-
// We need to enrich each symbol
|
|
188
|
-
functions = [];
|
|
189
|
-
for (const fileResult of results) {
|
|
190
|
-
const allSymbols = [
|
|
191
|
-
...(fileResult.publicApi || []),
|
|
192
|
-
...(fileResult.internal || []),
|
|
193
|
-
] as FileSymbol[];
|
|
194
|
-
if (kind) {
|
|
195
|
-
const filtered = allSymbols.filter((s) => s.kind === kind);
|
|
196
|
-
for (const sym of filtered) {
|
|
197
|
-
functions.push(enrichSymbol(db, sym, fileResult.file, noTests, maxDepth, thresholds));
|
|
198
|
-
}
|
|
199
|
-
} else {
|
|
200
|
-
for (const sym of allSymbols) {
|
|
201
|
-
functions.push(enrichSymbol(db, sym, fileResult.file, noTests, maxDepth, thresholds));
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
186
|
+
functions = enrichFileResults(db, results, kind, noTests, maxDepth, thresholds);
|
|
205
187
|
} else {
|
|
206
|
-
// Function target: explainData returns per-function results
|
|
207
188
|
functions = results.map((r: ExplainResult) =>
|
|
208
189
|
enrichFunction(db, r, noTests, maxDepth, thresholds),
|
|
209
190
|
);
|
|
@@ -232,6 +213,29 @@ interface ExplainResult {
|
|
|
232
213
|
relatedTests?: { file: string }[];
|
|
233
214
|
}
|
|
234
215
|
|
|
216
|
+
/** Enrich all symbols from file-target results. */
|
|
217
|
+
function enrichFileResults(
|
|
218
|
+
db: BetterSqlite3Database,
|
|
219
|
+
results: any[],
|
|
220
|
+
kind: string | undefined,
|
|
221
|
+
noTests: boolean,
|
|
222
|
+
maxDepth: number,
|
|
223
|
+
thresholds: Record<string, ThresholdEntry>,
|
|
224
|
+
): unknown[] {
|
|
225
|
+
const functions: unknown[] = [];
|
|
226
|
+
for (const fileResult of results) {
|
|
227
|
+
let allSymbols = [
|
|
228
|
+
...(fileResult.publicApi || []),
|
|
229
|
+
...(fileResult.internal || []),
|
|
230
|
+
] as FileSymbol[];
|
|
231
|
+
if (kind) allSymbols = allSymbols.filter((s) => s.kind === kind);
|
|
232
|
+
for (const sym of allSymbols) {
|
|
233
|
+
functions.push(enrichSymbol(db, sym, fileResult.file, noTests, maxDepth, thresholds));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return functions;
|
|
237
|
+
}
|
|
238
|
+
|
|
235
239
|
function enrichFunction(
|
|
236
240
|
db: BetterSqlite3Database,
|
|
237
241
|
r: ExplainResult,
|
|
@@ -2,11 +2,13 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import
|
|
5
|
+
import { getDatabase } from '../db/better-sqlite3.js';
|
|
6
6
|
import { buildGraph } from '../domain/graph/builder.js';
|
|
7
7
|
import { kindIcon } from '../domain/queries.js';
|
|
8
|
+
import { debug } from '../infrastructure/logger.js';
|
|
9
|
+
import { getNative, isNativeAvailable } from '../infrastructure/native.js';
|
|
8
10
|
import { isTestFile } from '../infrastructure/test-filter.js';
|
|
9
|
-
import type { EngineMode } from '../types.js';
|
|
11
|
+
import type { EngineMode, NativeDatabase } from '../types.js';
|
|
10
12
|
|
|
11
13
|
// ─── Git Helpers ────────────────────────────────────────────────────────
|
|
12
14
|
|
|
@@ -105,7 +107,20 @@ function loadSymbolsFromDb(
|
|
|
105
107
|
changedFiles: string[],
|
|
106
108
|
noTests: boolean,
|
|
107
109
|
): Map<string, SymbolInfo> {
|
|
110
|
+
const Database = getDatabase();
|
|
108
111
|
const db = new Database(dbPath, { readonly: true });
|
|
112
|
+
|
|
113
|
+
// Try opening a NativeDatabase for batched fan metrics
|
|
114
|
+
let nativeDb: NativeDatabase | undefined;
|
|
115
|
+
if (isNativeAvailable()) {
|
|
116
|
+
try {
|
|
117
|
+
const native = getNative();
|
|
118
|
+
nativeDb = native.NativeDatabase.openReadonly(dbPath);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
debug(`loadSymbolsFromDb: native path failed: ${(e as Error).message}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
109
124
|
try {
|
|
110
125
|
const symbols = new Map<string, SymbolInfo>();
|
|
111
126
|
|
|
@@ -131,6 +146,34 @@ function loadSymbolsFromDb(
|
|
|
131
146
|
end_line: number | null;
|
|
132
147
|
}>;
|
|
133
148
|
|
|
149
|
+
// Filter first, then batch fan metrics for all surviving rows
|
|
150
|
+
const filtered = noTests ? rows.filter((r) => !isTestFile(r.file)) : rows;
|
|
151
|
+
|
|
152
|
+
// ── Native fast path: batch all fan-in/fan-out in one napi call ──
|
|
153
|
+
if (nativeDb?.batchFanMetrics && filtered.length > 0) {
|
|
154
|
+
const nodeIds = filtered.map((r) => r.id);
|
|
155
|
+
const metrics = nativeDb.batchFanMetrics(nodeIds);
|
|
156
|
+
const metricsMap = new Map(metrics.map((m) => [m.nodeId, m]));
|
|
157
|
+
|
|
158
|
+
for (const row of filtered) {
|
|
159
|
+
const lineCount = row.end_line ? row.end_line - row.line + 1 : 0;
|
|
160
|
+
const m = metricsMap.get(row.id);
|
|
161
|
+
const key = makeSymbolKey(row.kind, row.file, row.name);
|
|
162
|
+
symbols.set(key, {
|
|
163
|
+
id: row.id,
|
|
164
|
+
name: row.name,
|
|
165
|
+
kind: row.kind,
|
|
166
|
+
file: row.file,
|
|
167
|
+
line: row.line,
|
|
168
|
+
lineCount,
|
|
169
|
+
fanIn: m?.fanIn ?? 0,
|
|
170
|
+
fanOut: m?.fanOut ?? 0,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return symbols;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ── JS fallback ───────────────────────────────────────────────────
|
|
134
177
|
const fanInStmt = db.prepare(
|
|
135
178
|
`SELECT COUNT(*) AS cnt FROM edges WHERE target_id = ? AND kind = 'calls'`,
|
|
136
179
|
);
|
|
@@ -138,9 +181,7 @@ function loadSymbolsFromDb(
|
|
|
138
181
|
`SELECT COUNT(*) AS cnt FROM edges WHERE source_id = ? AND kind = 'calls'`,
|
|
139
182
|
);
|
|
140
183
|
|
|
141
|
-
for (const row of
|
|
142
|
-
if (noTests && isTestFile(row.file)) continue;
|
|
143
|
-
|
|
184
|
+
for (const row of filtered) {
|
|
144
185
|
const lineCount = row.end_line ? row.end_line - row.line + 1 : 0;
|
|
145
186
|
const fanIn = (fanInStmt.get(row.id) as { cnt: number }).cnt;
|
|
146
187
|
const fanOut = (fanOutStmt.get(row.id) as { cnt: number }).cnt;
|
|
@@ -161,6 +202,13 @@ function loadSymbolsFromDb(
|
|
|
161
202
|
return symbols;
|
|
162
203
|
} finally {
|
|
163
204
|
db.close();
|
|
205
|
+
if (nativeDb) {
|
|
206
|
+
try {
|
|
207
|
+
nativeDb.close();
|
|
208
|
+
} catch {
|
|
209
|
+
/* already closed */
|
|
210
|
+
}
|
|
211
|
+
}
|
|
164
212
|
}
|
|
165
213
|
}
|
|
166
214
|
|
|
@@ -174,6 +222,7 @@ function loadCallersFromDb(
|
|
|
174
222
|
): CallerInfo[] {
|
|
175
223
|
if (nodeIds.length === 0) return [];
|
|
176
224
|
|
|
225
|
+
const Database = getDatabase();
|
|
177
226
|
const db = new Database(dbPath, { readonly: true });
|
|
178
227
|
try {
|
|
179
228
|
const allCallers = new Set<string>();
|