@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
package/src/domain/parser.ts
CHANGED
|
@@ -16,26 +16,38 @@ import type {
|
|
|
16
16
|
|
|
17
17
|
// Re-export all extractors for backward compatibility
|
|
18
18
|
export {
|
|
19
|
+
extractBashSymbols,
|
|
20
|
+
extractCppSymbols,
|
|
19
21
|
extractCSharpSymbols,
|
|
22
|
+
extractCSymbols,
|
|
20
23
|
extractGoSymbols,
|
|
21
24
|
extractHCLSymbols,
|
|
22
25
|
extractJavaSymbols,
|
|
26
|
+
extractKotlinSymbols,
|
|
23
27
|
extractPHPSymbols,
|
|
24
28
|
extractPythonSymbols,
|
|
25
29
|
extractRubySymbols,
|
|
26
30
|
extractRustSymbols,
|
|
31
|
+
extractScalaSymbols,
|
|
32
|
+
extractSwiftSymbols,
|
|
27
33
|
extractSymbols,
|
|
28
34
|
} from '../extractors/index.js';
|
|
29
35
|
|
|
30
36
|
import {
|
|
37
|
+
extractBashSymbols,
|
|
38
|
+
extractCppSymbols,
|
|
31
39
|
extractCSharpSymbols,
|
|
40
|
+
extractCSymbols,
|
|
32
41
|
extractGoSymbols,
|
|
33
42
|
extractHCLSymbols,
|
|
34
43
|
extractJavaSymbols,
|
|
44
|
+
extractKotlinSymbols,
|
|
35
45
|
extractPHPSymbols,
|
|
36
46
|
extractPythonSymbols,
|
|
37
47
|
extractRubySymbols,
|
|
38
48
|
extractRustSymbols,
|
|
49
|
+
extractScalaSymbols,
|
|
50
|
+
extractSwiftSymbols,
|
|
39
51
|
extractSymbols,
|
|
40
52
|
} from '../extractors/index.js';
|
|
41
53
|
|
|
@@ -85,6 +97,7 @@ const COMMON_QUERY_PATTERNS: string[] = [
|
|
|
85
97
|
'(variable_declarator name: (identifier) @varfn_name value: (arrow_function) @varfn_value)',
|
|
86
98
|
'(variable_declarator name: (identifier) @varfn_name value: (function_expression) @varfn_value)',
|
|
87
99
|
'(method_definition name: (property_identifier) @meth_name) @meth_node',
|
|
100
|
+
'(method_definition name: (private_property_identifier) @meth_name) @meth_node',
|
|
88
101
|
'(import_statement source: (string) @imp_source) @imp_node',
|
|
89
102
|
'(export_statement) @exp_node',
|
|
90
103
|
'(call_expression function: (identifier) @callfn_name) @callfn_node',
|
|
@@ -272,37 +285,38 @@ function resolveEngine(opts: ParseEngineOpts = {}): ResolvedEngine {
|
|
|
272
285
|
* - Backward compat for older native binaries missing js_name annotations
|
|
273
286
|
* - dataflow argFlows/mutations bindingType -> binding wrapper
|
|
274
287
|
*/
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// Backward compat for older binaries missing js_name annotations
|
|
281
|
-
if (r.definitions) {
|
|
282
|
-
for (const d of r.definitions) {
|
|
283
|
-
if (d.endLine === undefined && d.end_line !== undefined) {
|
|
284
|
-
d.endLine = d.end_line;
|
|
285
|
-
}
|
|
288
|
+
/** Patch definition fields for backward compat with older native binaries. */
|
|
289
|
+
function patchDefinitions(definitions: any[]): void {
|
|
290
|
+
for (const d of definitions) {
|
|
291
|
+
if (d.endLine === undefined && d.end_line !== undefined) {
|
|
292
|
+
d.endLine = d.end_line;
|
|
286
293
|
}
|
|
287
294
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/** Patch import fields for backward compat with older native binaries. */
|
|
298
|
+
function patchImports(imports: any[]): void {
|
|
299
|
+
for (const i of imports) {
|
|
300
|
+
if (i.typeOnly === undefined) i.typeOnly = i.type_only;
|
|
301
|
+
if (i.wildcardReexport === undefined) i.wildcardReexport = i.wildcard_reexport;
|
|
302
|
+
if (i.pythonImport === undefined) i.pythonImport = i.python_import;
|
|
303
|
+
if (i.goImport === undefined) i.goImport = i.go_import;
|
|
304
|
+
if (i.rustUse === undefined) i.rustUse = i.rust_use;
|
|
305
|
+
if (i.javaImport === undefined) i.javaImport = i.java_import;
|
|
306
|
+
if (i.csharpUsing === undefined) i.csharpUsing = i.csharp_using;
|
|
307
|
+
if (i.rubyRequire === undefined) i.rubyRequire = i.ruby_require;
|
|
308
|
+
if (i.phpUse === undefined) i.phpUse = i.php_use;
|
|
309
|
+
if (i.cInclude === undefined) i.cInclude = i.c_include;
|
|
310
|
+
if (i.kotlinImport === undefined) i.kotlinImport = i.kotlin_import;
|
|
311
|
+
if (i.swiftImport === undefined) i.swiftImport = i.swift_import;
|
|
312
|
+
if (i.scalaImport === undefined) i.scalaImport = i.scala_import;
|
|
313
|
+
if (i.bashSource === undefined) i.bashSource = i.bash_source;
|
|
314
|
+
if (i.dynamicImport === undefined) i.dynamicImport = i.dynamic_import;
|
|
301
315
|
}
|
|
316
|
+
}
|
|
302
317
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
// callers can safely access .entries()/.size without null checks.
|
|
318
|
+
/** Normalize native typeMap array to a Map instance. */
|
|
319
|
+
function patchTypeMap(r: any): void {
|
|
306
320
|
if (!r.typeMap) {
|
|
307
321
|
r.typeMap = new Map();
|
|
308
322
|
} else if (!(r.typeMap instanceof Map)) {
|
|
@@ -313,20 +327,31 @@ function patchNativeResult(r: any): ExtractorOutput {
|
|
|
313
327
|
]),
|
|
314
328
|
);
|
|
315
329
|
}
|
|
330
|
+
}
|
|
316
331
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
332
|
+
/** Wrap bindingType into binding object for dataflow argFlows and mutations. */
|
|
333
|
+
function patchDataflow(dataflow: any): void {
|
|
334
|
+
if (dataflow.argFlows) {
|
|
335
|
+
for (const f of dataflow.argFlows) {
|
|
336
|
+
f.binding = f.bindingType ? { type: f.bindingType } : null;
|
|
323
337
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
338
|
+
}
|
|
339
|
+
if (dataflow.mutations) {
|
|
340
|
+
for (const m of dataflow.mutations) {
|
|
341
|
+
m.binding = m.bindingType ? { type: m.bindingType } : null;
|
|
328
342
|
}
|
|
329
343
|
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function patchNativeResult(r: any): ExtractorOutput {
|
|
347
|
+
// lineCount: napi(js_name) emits "lineCount"; older binaries may emit "line_count"
|
|
348
|
+
r.lineCount = r.lineCount ?? r.line_count ?? null;
|
|
349
|
+
r._lineCount = r.lineCount;
|
|
350
|
+
|
|
351
|
+
if (r.definitions) patchDefinitions(r.definitions);
|
|
352
|
+
if (r.imports) patchImports(r.imports);
|
|
353
|
+
patchTypeMap(r);
|
|
354
|
+
if (r.dataflow) patchDataflow(r.dataflow);
|
|
330
355
|
|
|
331
356
|
return r;
|
|
332
357
|
}
|
|
@@ -413,6 +438,48 @@ export const LANGUAGE_REGISTRY: LanguageRegistryEntry[] = [
|
|
|
413
438
|
extractor: extractPHPSymbols,
|
|
414
439
|
required: false,
|
|
415
440
|
},
|
|
441
|
+
{
|
|
442
|
+
id: 'c',
|
|
443
|
+
extensions: ['.c', '.h'],
|
|
444
|
+
grammarFile: 'tree-sitter-c.wasm',
|
|
445
|
+
extractor: extractCSymbols,
|
|
446
|
+
required: false,
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
id: 'cpp',
|
|
450
|
+
extensions: ['.cpp', '.cc', '.cxx', '.hpp'],
|
|
451
|
+
grammarFile: 'tree-sitter-cpp.wasm',
|
|
452
|
+
extractor: extractCppSymbols,
|
|
453
|
+
required: false,
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
id: 'kotlin',
|
|
457
|
+
extensions: ['.kt', '.kts'],
|
|
458
|
+
grammarFile: 'tree-sitter-kotlin.wasm',
|
|
459
|
+
extractor: extractKotlinSymbols,
|
|
460
|
+
required: false,
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
id: 'swift',
|
|
464
|
+
extensions: ['.swift'],
|
|
465
|
+
grammarFile: 'tree-sitter-swift.wasm',
|
|
466
|
+
extractor: extractSwiftSymbols,
|
|
467
|
+
required: false,
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
id: 'scala',
|
|
471
|
+
extensions: ['.scala'],
|
|
472
|
+
grammarFile: 'tree-sitter-scala.wasm',
|
|
473
|
+
extractor: extractScalaSymbols,
|
|
474
|
+
required: false,
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
id: 'bash',
|
|
478
|
+
extensions: ['.sh', '.bash'],
|
|
479
|
+
grammarFile: 'tree-sitter-bash.wasm',
|
|
480
|
+
extractor: extractBashSymbols,
|
|
481
|
+
required: false,
|
|
482
|
+
},
|
|
416
483
|
];
|
|
417
484
|
|
|
418
485
|
const _extToLang: Map<string, LanguageRegistryEntry> = new Map();
|
|
@@ -521,73 +588,48 @@ export async function parseFileAuto(
|
|
|
521
588
|
return extracted ? extracted.symbols : null;
|
|
522
589
|
}
|
|
523
590
|
|
|
524
|
-
/**
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
)
|
|
532
|
-
|
|
533
|
-
const result = new Map<string, ExtractorOutput>();
|
|
591
|
+
/** Backfill typeMap via WASM for files missing type-map data from native engine. */
|
|
592
|
+
async function backfillTypeMapBatch(
|
|
593
|
+
needsTypeMap: { filePath: string; relPath: string }[],
|
|
594
|
+
result: Map<string, ExtractorOutput>,
|
|
595
|
+
): Promise<void> {
|
|
596
|
+
const tsFiles = needsTypeMap.filter(({ filePath }) =>
|
|
597
|
+
TS_BACKFILL_EXTS.has(path.extname(filePath)),
|
|
598
|
+
);
|
|
599
|
+
if (tsFiles.length === 0) return;
|
|
534
600
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
const relPath = path.relative(rootDir, r.file).split(path.sep).join('/');
|
|
547
|
-
result.set(relPath, patched);
|
|
548
|
-
if (patched.typeMap.size === 0) {
|
|
549
|
-
needsTypeMap.push({ filePath: r.file, relPath });
|
|
601
|
+
const parsers = await createParsers();
|
|
602
|
+
for (const { filePath, relPath } of tsFiles) {
|
|
603
|
+
let extracted: WasmExtractResult | null | undefined;
|
|
604
|
+
try {
|
|
605
|
+
const code = fs.readFileSync(filePath, 'utf-8');
|
|
606
|
+
extracted = wasmExtractSymbols(parsers, filePath, code);
|
|
607
|
+
if (extracted?.symbols && extracted.symbols.typeMap.size > 0) {
|
|
608
|
+
const symbols = result.get(relPath);
|
|
609
|
+
if (!symbols) continue;
|
|
610
|
+
symbols.typeMap = extracted.symbols.typeMap;
|
|
611
|
+
symbols._typeMapBackfilled = true;
|
|
550
612
|
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
if (tsFiles.length > 0) {
|
|
560
|
-
const parsers = await createParsers();
|
|
561
|
-
for (const { filePath, relPath } of tsFiles) {
|
|
562
|
-
let extracted: WasmExtractResult | null | undefined;
|
|
563
|
-
try {
|
|
564
|
-
const code = fs.readFileSync(filePath, 'utf-8');
|
|
565
|
-
extracted = wasmExtractSymbols(parsers, filePath, code);
|
|
566
|
-
if (extracted?.symbols && extracted.symbols.typeMap.size > 0) {
|
|
567
|
-
const symbols = result.get(relPath);
|
|
568
|
-
if (!symbols) continue;
|
|
569
|
-
symbols.typeMap = extracted.symbols.typeMap;
|
|
570
|
-
symbols._typeMapBackfilled = true;
|
|
571
|
-
}
|
|
572
|
-
} catch (e) {
|
|
573
|
-
debug(`batchExtract: typeMap backfill failed: ${toErrorMessage(e)}`);
|
|
574
|
-
} finally {
|
|
575
|
-
// Free the WASM tree to prevent memory accumulation across repeated builds
|
|
576
|
-
if (extracted?.tree && typeof extracted.tree.delete === 'function') {
|
|
577
|
-
try {
|
|
578
|
-
extracted.tree.delete();
|
|
579
|
-
} catch (e) {
|
|
580
|
-
debug(`batchExtract: WASM tree cleanup failed: ${toErrorMessage(e)}`);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
613
|
+
} catch (e) {
|
|
614
|
+
debug(`batchExtract: typeMap backfill failed: ${toErrorMessage(e)}`);
|
|
615
|
+
} finally {
|
|
616
|
+
if (extracted?.tree && typeof extracted.tree.delete === 'function') {
|
|
617
|
+
try {
|
|
618
|
+
extracted.tree.delete();
|
|
619
|
+
} catch (e) {
|
|
620
|
+
debug(`batchExtract: WASM tree cleanup failed: ${toErrorMessage(e)}`);
|
|
584
621
|
}
|
|
585
622
|
}
|
|
586
623
|
}
|
|
587
|
-
return result;
|
|
588
624
|
}
|
|
625
|
+
}
|
|
589
626
|
|
|
590
|
-
|
|
627
|
+
/** Parse files via WASM engine, returning a Map<relPath, symbols>. */
|
|
628
|
+
async function parseFilesWasm(
|
|
629
|
+
filePaths: string[],
|
|
630
|
+
rootDir: string,
|
|
631
|
+
): Promise<Map<string, ExtractorOutput>> {
|
|
632
|
+
const result = new Map<string, ExtractorOutput>();
|
|
591
633
|
const parsers = await createParsers();
|
|
592
634
|
for (const filePath of filePaths) {
|
|
593
635
|
let code: string;
|
|
@@ -609,6 +651,36 @@ export async function parseFilesAuto(
|
|
|
609
651
|
return result;
|
|
610
652
|
}
|
|
611
653
|
|
|
654
|
+
/**
|
|
655
|
+
* Parse multiple files in bulk and return a Map<relPath, symbols>.
|
|
656
|
+
*/
|
|
657
|
+
export async function parseFilesAuto(
|
|
658
|
+
filePaths: string[],
|
|
659
|
+
rootDir: string,
|
|
660
|
+
opts: ParseEngineOpts = {},
|
|
661
|
+
): Promise<Map<string, ExtractorOutput>> {
|
|
662
|
+
const { native } = resolveEngine(opts);
|
|
663
|
+
|
|
664
|
+
if (!native) return parseFilesWasm(filePaths, rootDir);
|
|
665
|
+
|
|
666
|
+
const result = new Map<string, ExtractorOutput>();
|
|
667
|
+
const nativeResults = native.parseFiles(filePaths, rootDir, !!opts.dataflow, opts.ast !== false);
|
|
668
|
+
const needsTypeMap: { filePath: string; relPath: string }[] = [];
|
|
669
|
+
for (const r of nativeResults) {
|
|
670
|
+
if (!r) continue;
|
|
671
|
+
const patched = patchNativeResult(r);
|
|
672
|
+
const relPath = path.relative(rootDir, r.file).split(path.sep).join('/');
|
|
673
|
+
result.set(relPath, patched);
|
|
674
|
+
if (patched.typeMap.size === 0) {
|
|
675
|
+
needsTypeMap.push({ filePath: r.file, relPath });
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
if (needsTypeMap.length > 0) {
|
|
679
|
+
await backfillTypeMapBatch(needsTypeMap, result);
|
|
680
|
+
}
|
|
681
|
+
return result;
|
|
682
|
+
}
|
|
683
|
+
|
|
612
684
|
/**
|
|
613
685
|
* Report which engine is active.
|
|
614
686
|
*/
|
|
@@ -11,113 +11,98 @@ interface SearchOpts extends SemanticSearchOpts {
|
|
|
11
11
|
offset?: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
customDbPath: string | undefined,
|
|
17
|
-
opts: SearchOpts = {},
|
|
18
|
-
): Promise<void> {
|
|
19
|
-
const mode = opts.mode || 'hybrid';
|
|
14
|
+
const kindIcon = (kind: string): string =>
|
|
15
|
+
kind === 'function' ? 'f' : kind === 'class' ? '*' : 'o';
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Keyword-only mode
|
|
30
|
-
if (mode === 'keyword') {
|
|
31
|
-
const singleQuery = queries.length === 1 ? queries[0]! : query;
|
|
32
|
-
const data = ftsSearchData(singleQuery, customDbPath, opts);
|
|
33
|
-
if (!data) {
|
|
34
|
-
console.log('No FTS5 index found. Run `codegraph embed` to build the keyword index.');
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
if (opts.json) {
|
|
38
|
-
console.log(JSON.stringify(data, null, 2));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
console.log(`\nKeyword search: "${singleQuery}" (BM25)\n`);
|
|
42
|
-
if (data.results.length === 0) {
|
|
43
|
-
console.log(' No results found.');
|
|
44
|
-
} else {
|
|
45
|
-
for (const r of data.results) {
|
|
46
|
-
console.log(
|
|
47
|
-
` BM25 ${r.bm25Score.toFixed(2)} ${kindIcon(r.kind)} ${r.name} -- ${r.file}:${r.line}`,
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
console.log(`\n ${data.results.length} results shown\n`);
|
|
17
|
+
function formatKeywordResults(
|
|
18
|
+
singleQuery: string,
|
|
19
|
+
customDbPath: string | undefined,
|
|
20
|
+
opts: SearchOpts,
|
|
21
|
+
): void {
|
|
22
|
+
const data = ftsSearchData(singleQuery, customDbPath, opts);
|
|
23
|
+
if (!data) {
|
|
24
|
+
console.log('No FTS5 index found. Run `codegraph embed` to build the keyword index.');
|
|
52
25
|
return;
|
|
53
26
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (mode === 'semantic') {
|
|
57
|
-
if (queries.length <= 1) {
|
|
58
|
-
const singleQuery = queries[0] || query;
|
|
59
|
-
const data = await searchData(singleQuery, customDbPath, opts);
|
|
60
|
-
if (!data) return;
|
|
61
|
-
if (opts.json) {
|
|
62
|
-
console.log(JSON.stringify(data, null, 2));
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
console.log(`\nSemantic search: "${singleQuery}"\n`);
|
|
66
|
-
if (data.results.length === 0) {
|
|
67
|
-
console.log(' No results above threshold.');
|
|
68
|
-
} else {
|
|
69
|
-
for (const r of data.results) {
|
|
70
|
-
const bar = '#'.repeat(Math.round(r.similarity * 20));
|
|
71
|
-
console.log(` ${(r.similarity * 100).toFixed(1)}% ${bar}`);
|
|
72
|
-
console.log(` ${kindIcon(r.kind)} ${r.name} -- ${r.file}:${r.line}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
console.log(`\n ${data.results.length} results shown\n`);
|
|
76
|
-
} else {
|
|
77
|
-
const data = await multiSearchData(queries, customDbPath, opts);
|
|
78
|
-
if (!data) return;
|
|
79
|
-
if (opts.json) {
|
|
80
|
-
console.log(JSON.stringify(data, null, 2));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
console.log(`\nMulti-query semantic search (RRF, k=${opts.rrfK || 60}):`);
|
|
84
|
-
for (let i = 0; i < queries.length; i++) console.log(` [${i + 1}] "${queries[i]}"`);
|
|
85
|
-
console.log();
|
|
86
|
-
if (data.results.length === 0) {
|
|
87
|
-
console.log(' No results above threshold.');
|
|
88
|
-
} else {
|
|
89
|
-
for (const r of data.results) {
|
|
90
|
-
console.log(
|
|
91
|
-
` RRF ${r.rrf.toFixed(4)} ${kindIcon(r.kind)} ${r.name} -- ${r.file}:${r.line}`,
|
|
92
|
-
);
|
|
93
|
-
for (const qs of r.queryScores) {
|
|
94
|
-
const bar = '#'.repeat(Math.round(qs.similarity * 20));
|
|
95
|
-
console.log(
|
|
96
|
-
` [${queries.indexOf(qs.query) + 1}] ${(qs.similarity * 100).toFixed(1)}% ${bar} (rank ${qs.rank})`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
console.log(`\n ${data.results.length} results shown\n`);
|
|
102
|
-
}
|
|
27
|
+
if (opts.json) {
|
|
28
|
+
console.log(JSON.stringify(data, null, 2));
|
|
103
29
|
return;
|
|
104
30
|
}
|
|
31
|
+
console.log(`\nKeyword search: "${singleQuery}" (BM25)\n`);
|
|
32
|
+
if (data.results.length === 0) {
|
|
33
|
+
console.log(' No results found.');
|
|
34
|
+
} else {
|
|
35
|
+
for (const r of data.results) {
|
|
36
|
+
console.log(
|
|
37
|
+
` BM25 ${r.bm25Score.toFixed(2)} ${kindIcon(r.kind)} ${r.name} -- ${r.file}:${r.line}`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
console.log(`\n ${data.results.length} results shown\n`);
|
|
42
|
+
}
|
|
105
43
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
44
|
+
async function formatSemanticSingle(
|
|
45
|
+
singleQuery: string,
|
|
46
|
+
customDbPath: string | undefined,
|
|
47
|
+
opts: SearchOpts,
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
const data = await searchData(singleQuery, customDbPath, opts);
|
|
50
|
+
if (!data) return;
|
|
51
|
+
if (opts.json) {
|
|
52
|
+
console.log(JSON.stringify(data, null, 2));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log(`\nSemantic search: "${singleQuery}"\n`);
|
|
56
|
+
if (data.results.length === 0) {
|
|
57
|
+
console.log(' No results above threshold.');
|
|
58
|
+
} else {
|
|
59
|
+
for (const r of data.results) {
|
|
60
|
+
const bar = '#'.repeat(Math.round(r.similarity * 20));
|
|
61
|
+
console.log(` ${(r.similarity * 100).toFixed(1)}% ${bar}`);
|
|
62
|
+
console.log(` ${kindIcon(r.kind)} ${r.name} -- ${r.file}:${r.line}`);
|
|
63
|
+
}
|
|
114
64
|
}
|
|
65
|
+
console.log(`\n ${data.results.length} results shown\n`);
|
|
66
|
+
}
|
|
115
67
|
|
|
68
|
+
async function formatSemanticMulti(
|
|
69
|
+
queries: string[],
|
|
70
|
+
customDbPath: string | undefined,
|
|
71
|
+
opts: SearchOpts,
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
const data = await multiSearchData(queries, customDbPath, opts);
|
|
74
|
+
if (!data) return;
|
|
116
75
|
if (opts.json) {
|
|
117
76
|
console.log(JSON.stringify(data, null, 2));
|
|
118
77
|
return;
|
|
119
78
|
}
|
|
79
|
+
console.log(`\nMulti-query semantic search (RRF, k=${opts.rrfK || 60}):`);
|
|
80
|
+
for (let i = 0; i < queries.length; i++) console.log(` [${i + 1}] "${queries[i]}"`);
|
|
81
|
+
console.log();
|
|
82
|
+
if (data.results.length === 0) {
|
|
83
|
+
console.log(' No results above threshold.');
|
|
84
|
+
} else {
|
|
85
|
+
for (const r of data.results) {
|
|
86
|
+
console.log(
|
|
87
|
+
` RRF ${r.rrf.toFixed(4)} ${kindIcon(r.kind)} ${r.name} -- ${r.file}:${r.line}`,
|
|
88
|
+
);
|
|
89
|
+
for (const qs of r.queryScores) {
|
|
90
|
+
const bar = '#'.repeat(Math.round(qs.similarity * 20));
|
|
91
|
+
console.log(
|
|
92
|
+
` [${queries.indexOf(qs.query) + 1}] ${(qs.similarity * 100).toFixed(1)}% ${bar} (rank ${qs.rank})`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
console.log(`\n ${data.results.length} results shown\n`);
|
|
98
|
+
}
|
|
120
99
|
|
|
100
|
+
function formatHybridResults(
|
|
101
|
+
queries: string[],
|
|
102
|
+
query: string,
|
|
103
|
+
data: { results: any[] },
|
|
104
|
+
opts: SearchOpts,
|
|
105
|
+
): void {
|
|
121
106
|
const rrfK = opts.rrfK || 60;
|
|
122
107
|
if (queries.length <= 1) {
|
|
123
108
|
const singleQuery = queries[0] || query;
|
|
@@ -150,3 +135,45 @@ export async function search(
|
|
|
150
135
|
|
|
151
136
|
console.log(`\n ${data.results.length} results shown\n`);
|
|
152
137
|
}
|
|
138
|
+
|
|
139
|
+
export async function search(
|
|
140
|
+
query: string,
|
|
141
|
+
customDbPath: string | undefined,
|
|
142
|
+
opts: SearchOpts = {},
|
|
143
|
+
): Promise<void> {
|
|
144
|
+
const mode = opts.mode || 'hybrid';
|
|
145
|
+
|
|
146
|
+
const queries = query
|
|
147
|
+
.split(';')
|
|
148
|
+
.map((q) => q.trim())
|
|
149
|
+
.filter((q) => q.length > 0);
|
|
150
|
+
|
|
151
|
+
if (mode === 'keyword') {
|
|
152
|
+
const singleQuery = queries.length === 1 ? queries[0]! : query;
|
|
153
|
+
return formatKeywordResults(singleQuery, customDbPath, opts);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (mode === 'semantic') {
|
|
157
|
+
if (queries.length <= 1) {
|
|
158
|
+
return formatSemanticSingle(queries[0] || query, customDbPath, opts);
|
|
159
|
+
}
|
|
160
|
+
return formatSemanticMulti(queries, customDbPath, opts);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Hybrid mode (default)
|
|
164
|
+
const data = await hybridSearchData(query, customDbPath, opts);
|
|
165
|
+
|
|
166
|
+
if (!data) {
|
|
167
|
+
warn(
|
|
168
|
+
'FTS5 index not found — using semantic search only. Re-run `codegraph embed` to enable hybrid mode.',
|
|
169
|
+
);
|
|
170
|
+
return search(query, customDbPath, { ...opts, mode: 'semantic' });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (opts.json) {
|
|
174
|
+
console.log(JSON.stringify(data, null, 2));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
formatHybridResults(queries, query, data, opts);
|
|
179
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Call, ExtractorOutput, TreeSitterNode, TreeSitterTree } from '../types.js';
|
|
2
|
+
import { nodeEndLine } from './helpers.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extract symbols from Bash/Shell files.
|
|
6
|
+
*/
|
|
7
|
+
export function extractBashSymbols(tree: TreeSitterTree, _filePath: string): ExtractorOutput {
|
|
8
|
+
const ctx: ExtractorOutput = {
|
|
9
|
+
definitions: [],
|
|
10
|
+
calls: [],
|
|
11
|
+
imports: [],
|
|
12
|
+
classes: [],
|
|
13
|
+
exports: [],
|
|
14
|
+
typeMap: new Map(),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
walkBashNode(tree.rootNode, ctx);
|
|
18
|
+
return ctx;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function walkBashNode(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
22
|
+
switch (node.type) {
|
|
23
|
+
case 'function_definition':
|
|
24
|
+
handleBashFunctionDef(node, ctx);
|
|
25
|
+
break;
|
|
26
|
+
case 'command':
|
|
27
|
+
handleBashCommand(node, ctx);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
32
|
+
const child = node.child(i);
|
|
33
|
+
if (child) walkBashNode(child, ctx);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ── Walk-path per-node-type handlers ────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
function handleBashFunctionDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
40
|
+
const nameNode = node.childForFieldName('name');
|
|
41
|
+
if (!nameNode) return;
|
|
42
|
+
ctx.definitions.push({
|
|
43
|
+
name: nameNode.text,
|
|
44
|
+
kind: 'function',
|
|
45
|
+
line: node.startPosition.row + 1,
|
|
46
|
+
endLine: nodeEndLine(node),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function handleBashCommand(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
51
|
+
// First child is command_name
|
|
52
|
+
let commandNameNode: TreeSitterNode | null = null;
|
|
53
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
54
|
+
const child = node.child(i);
|
|
55
|
+
if (child && child.type === 'command_name') {
|
|
56
|
+
commandNameNode = child;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!commandNameNode) return;
|
|
61
|
+
|
|
62
|
+
const cmdText = commandNameNode.text;
|
|
63
|
+
|
|
64
|
+
// "source" or "." commands are imports
|
|
65
|
+
if (cmdText === 'source' || cmdText === '.') {
|
|
66
|
+
// Second argument is the source path
|
|
67
|
+
let argNode: TreeSitterNode | null = null;
|
|
68
|
+
let foundCmd = false;
|
|
69
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
70
|
+
const child = node.child(i);
|
|
71
|
+
if (!child) continue;
|
|
72
|
+
if (child.type === 'command_name') {
|
|
73
|
+
foundCmd = true;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (foundCmd && child.type !== 'command_name') {
|
|
77
|
+
argNode = child;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (argNode) {
|
|
82
|
+
const source = argNode.text;
|
|
83
|
+
const lastName = source.split('/').pop() ?? source;
|
|
84
|
+
ctx.imports.push({
|
|
85
|
+
source,
|
|
86
|
+
names: [lastName],
|
|
87
|
+
line: node.startPosition.row + 1,
|
|
88
|
+
bashSource: true,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Regular command call
|
|
95
|
+
const call: Call = { name: cmdText, line: node.startPosition.row + 1 };
|
|
96
|
+
ctx.calls.push(call);
|
|
97
|
+
}
|