@optave/codegraph 3.10.0 → 3.11.1
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 +40 -33
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +91 -60
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/rules/index.d.ts.map +1 -1
- package/dist/ast-analysis/rules/index.js +77 -0
- package/dist/ast-analysis/rules/index.js.map +1 -1
- package/dist/ast-analysis/visitor-utils.d.ts +3 -0
- package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
- package/dist/ast-analysis/visitor-utils.js +83 -49
- package/dist/ast-analysis/visitor-utils.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 +78 -62
- package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.js +61 -42
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/audit.js +1 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +2 -0
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/check.js +1 -1
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/children.js +1 -1
- package/dist/cli/commands/children.js.map +1 -1
- package/dist/cli/commands/diff-impact.js +1 -1
- package/dist/cli/commands/diff-impact.js.map +1 -1
- package/dist/cli/commands/embed.d.ts.map +1 -1
- package/dist/cli/commands/embed.js +49 -4
- package/dist/cli/commands/embed.js.map +1 -1
- package/dist/cli/commands/roles.js +1 -1
- package/dist/cli/commands/roles.js.map +1 -1
- package/dist/cli/commands/structure.js +1 -1
- package/dist/cli/commands/structure.js.map +1 -1
- package/dist/cli/shared/options.js +1 -1
- package/dist/cli/shared/options.js.map +1 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +8 -0
- package/dist/db/connection.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +106 -80
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +77 -52
- 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 +132 -121
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +4 -4
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +47 -33
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts +6 -6
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +148 -99
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts +1 -0
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +23 -637
- 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 +141 -98
- 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 +82 -65
- package/dist/domain/graph/builder/stages/build-structure.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 +84 -56
- 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 +60 -51
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts +8 -6
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.js +107 -122
- package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-db-lifecycle.d.ts +14 -0
- package/dist/domain/graph/builder/stages/native-db-lifecycle.d.ts.map +1 -0
- package/dist/domain/graph/builder/stages/native-db-lifecycle.js +77 -0
- package/dist/domain/graph/builder/stages/native-db-lifecycle.js.map +1 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts +62 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.js +747 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -0
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +73 -22
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/cycles.d.ts +6 -4
- package/dist/domain/graph/cycles.d.ts.map +1 -1
- package/dist/domain/graph/cycles.js +50 -55
- package/dist/domain/graph/cycles.js.map +1 -1
- package/dist/domain/graph/journal.d.ts.map +1 -1
- package/dist/domain/graph/journal.js +89 -70
- package/dist/domain/graph/journal.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +28 -20
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +12 -23
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +153 -80
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/generator.d.ts +3 -1
- package/dist/domain/search/generator.d.ts.map +1 -1
- package/dist/domain/search/generator.js +68 -45
- package/dist/domain/search/generator.js.map +1 -1
- package/dist/domain/search/models.d.ts +18 -0
- package/dist/domain/search/models.d.ts.map +1 -1
- package/dist/domain/search/models.js +72 -4
- package/dist/domain/search/models.js.map +1 -1
- package/dist/domain/search/search/hybrid.d.ts.map +1 -1
- package/dist/domain/search/search/hybrid.js +49 -40
- package/dist/domain/search/search/hybrid.js.map +1 -1
- package/dist/domain/search/search/semantic.d.ts.map +1 -1
- package/dist/domain/search/search/semantic.js +69 -49
- package/dist/domain/search/search/semantic.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +209 -137
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/extractors/c.js +25 -6
- package/dist/extractors/c.js.map +1 -1
- package/dist/extractors/cpp.js +47 -6
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/cuda.js +90 -14
- package/dist/extractors/cuda.js.map +1 -1
- package/dist/extractors/elixir.js +108 -4
- package/dist/extractors/elixir.js.map +1 -1
- package/dist/extractors/erlang.js +56 -20
- package/dist/extractors/erlang.js.map +1 -1
- package/dist/extractors/fsharp.d.ts +7 -0
- package/dist/extractors/fsharp.d.ts.map +1 -1
- package/dist/extractors/fsharp.js +94 -0
- package/dist/extractors/fsharp.js.map +1 -1
- package/dist/extractors/gleam.d.ts.map +1 -1
- package/dist/extractors/gleam.js +29 -33
- package/dist/extractors/gleam.js.map +1 -1
- package/dist/extractors/groovy.js +41 -1
- package/dist/extractors/groovy.js.map +1 -1
- package/dist/extractors/haskell.js +48 -4
- package/dist/extractors/haskell.js.map +1 -1
- package/dist/extractors/helpers.d.ts +79 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +137 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +37 -49
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +44 -44
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/julia.js +198 -74
- package/dist/extractors/julia.js.map +1 -1
- package/dist/extractors/kotlin.js +4 -0
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/objc.js +184 -47
- package/dist/extractors/objc.js.map +1 -1
- package/dist/extractors/python.js +7 -4
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/r.d.ts.map +1 -1
- package/dist/extractors/r.js +103 -87
- package/dist/extractors/r.js.map +1 -1
- package/dist/extractors/scala.d.ts.map +1 -1
- package/dist/extractors/scala.js +18 -32
- package/dist/extractors/scala.js.map +1 -1
- package/dist/extractors/solidity.d.ts.map +1 -1
- package/dist/extractors/solidity.js +55 -69
- package/dist/extractors/solidity.js.map +1 -1
- package/dist/extractors/verilog.js +80 -15
- package/dist/extractors/verilog.js.map +1 -1
- package/dist/features/boundaries.d.ts.map +1 -1
- package/dist/features/boundaries.js +49 -39
- package/dist/features/boundaries.js.map +1 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +90 -63
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +43 -34
- package/dist/features/check.js.map +1 -1
- package/dist/features/cochange.d.ts.map +1 -1
- package/dist/features/cochange.js +68 -56
- package/dist/features/cochange.js.map +1 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +105 -75
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +37 -29
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/flow.d.ts.map +1 -1
- package/dist/features/flow.js +31 -22
- package/dist/features/flow.js.map +1 -1
- package/dist/features/graph-enrichment.d.ts.map +1 -1
- package/dist/features/graph-enrichment.js +77 -70
- package/dist/features/graph-enrichment.js.map +1 -1
- package/dist/features/owners.d.ts +17 -26
- package/dist/features/owners.d.ts.map +1 -1
- package/dist/features/owners.js +120 -109
- package/dist/features/owners.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +59 -54
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +60 -60
- package/dist/features/structure-query.js.map +1 -1
- package/dist/features/structure.js +28 -36
- package/dist/features/structure.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +100 -69
- package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
- package/dist/graph/classifiers/roles.d.ts.map +1 -1
- package/dist/graph/classifiers/roles.js +63 -59
- package/dist/graph/classifiers/roles.js.map +1 -1
- package/dist/infrastructure/config.d.ts +1 -1
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +1 -1
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +4 -0
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/mcp/tools/semantic-search.d.ts +1 -0
- package/dist/mcp/tools/semantic-search.d.ts.map +1 -1
- package/dist/mcp/tools/semantic-search.js +1 -0
- package/dist/mcp/tools/semantic-search.js.map +1 -1
- package/dist/presentation/cfg.d.ts.map +1 -1
- package/dist/presentation/cfg.js +44 -29
- package/dist/presentation/cfg.js.map +1 -1
- package/dist/presentation/flow.d.ts.map +1 -1
- package/dist/presentation/flow.js +58 -38
- package/dist/presentation/flow.js.map +1 -1
- package/dist/types.d.ts +16 -2
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-erlang.wasm +0 -0
- package/grammars/tree-sitter-fsharp.wasm +0 -0
- package/grammars/tree-sitter-fsharp_signature.wasm +0 -0
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +10 -10
- package/src/ast-analysis/engine.ts +145 -61
- package/src/ast-analysis/rules/index.ts +87 -0
- package/src/ast-analysis/visitor-utils.ts +86 -46
- package/src/ast-analysis/visitors/ast-store-visitor.ts +104 -69
- package/src/ast-analysis/visitors/dataflow-visitor.ts +86 -47
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +2 -0
- package/src/cli/commands/check.ts +1 -1
- package/src/cli/commands/children.ts +1 -1
- package/src/cli/commands/diff-impact.ts +1 -1
- package/src/cli/commands/embed.ts +54 -4
- package/src/cli/commands/roles.ts +1 -1
- package/src/cli/commands/structure.ts +1 -1
- package/src/cli/shared/options.ts +1 -1
- package/src/db/connection.ts +8 -0
- package/src/domain/analysis/dependencies.ts +166 -85
- package/src/domain/analysis/fn-impact.ts +120 -50
- package/src/domain/analysis/module-map.ts +175 -140
- package/src/domain/graph/builder/helpers.ts +85 -76
- package/src/domain/graph/builder/incremental.ts +223 -131
- package/src/domain/graph/builder/pipeline.ts +32 -785
- package/src/domain/graph/builder/stages/build-edges.ts +207 -142
- package/src/domain/graph/builder/stages/build-structure.ts +115 -82
- package/src/domain/graph/builder/stages/detect-changes.ts +107 -64
- package/src/domain/graph/builder/stages/finalize.ts +72 -70
- package/src/domain/graph/builder/stages/insert-nodes.ts +154 -120
- package/src/domain/graph/builder/stages/native-db-lifecycle.ts +74 -0
- package/src/domain/graph/builder/stages/native-orchestrator.ts +942 -0
- package/src/domain/graph/builder/stages/resolve-imports.ts +79 -25
- package/src/domain/graph/cycles.ts +51 -49
- package/src/domain/graph/journal.ts +84 -69
- package/src/domain/graph/watcher.ts +29 -25
- package/src/domain/parser.ts +170 -67
- package/src/domain/search/generator.ts +132 -74
- package/src/domain/search/models.ts +75 -4
- package/src/domain/search/search/hybrid.ts +53 -42
- package/src/domain/search/search/semantic.ts +105 -65
- package/src/domain/wasm-worker-entry.ts +243 -153
- package/src/extractors/c.ts +27 -8
- package/src/extractors/cpp.ts +50 -8
- package/src/extractors/cuda.ts +90 -16
- package/src/extractors/elixir.ts +103 -4
- package/src/extractors/erlang.ts +63 -20
- package/src/extractors/fsharp.ts +104 -0
- package/src/extractors/gleam.ts +40 -39
- package/src/extractors/groovy.ts +45 -1
- package/src/extractors/haskell.ts +45 -4
- package/src/extractors/helpers.ts +205 -1
- package/src/extractors/java.ts +42 -45
- package/src/extractors/javascript.ts +44 -43
- package/src/extractors/julia.ts +191 -77
- package/src/extractors/kotlin.ts +4 -0
- package/src/extractors/objc.ts +171 -47
- package/src/extractors/python.ts +5 -3
- package/src/extractors/r.ts +104 -82
- package/src/extractors/scala.ts +24 -36
- package/src/extractors/solidity.ts +59 -78
- package/src/extractors/verilog.ts +83 -15
- package/src/features/boundaries.ts +64 -46
- package/src/features/cfg.ts +145 -74
- package/src/features/check.ts +60 -43
- package/src/features/cochange.ts +95 -72
- package/src/features/complexity.ts +134 -79
- package/src/features/dataflow.ts +57 -34
- package/src/features/flow.ts +48 -24
- package/src/features/graph-enrichment.ts +105 -70
- package/src/features/owners.ts +186 -146
- package/src/features/sequence.ts +99 -69
- package/src/features/structure-query.ts +94 -79
- package/src/features/structure.ts +56 -56
- package/src/graph/algorithms/leiden/optimiser.ts +142 -87
- package/src/graph/classifiers/roles.ts +64 -54
- package/src/infrastructure/config.ts +1 -1
- package/src/mcp/tool-registry.ts +5 -0
- package/src/mcp/tools/semantic-search.ts +2 -0
- package/src/presentation/cfg.ts +48 -32
- package/src/presentation/flow.ts +100 -52
- package/src/types.ts +16 -1
package/src/extractors/julia.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtractorOutput, SubDeclaration, TreeSitterNode, TreeSitterTree } from '../types.js';
|
|
2
|
-
import { findChild, nodeEndLine } from './helpers.js';
|
|
2
|
+
import { findChild, nodeEndLine, nodeStartLine, pushCall, pushImport } from './helpers.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Extract symbols from Julia files.
|
|
@@ -76,29 +76,61 @@ function handleModuleDef(node: TreeSitterNode, ctx: ExtractorOutput): string | n
|
|
|
76
76
|
ctx.definitions.push({
|
|
77
77
|
name: nameNode.text,
|
|
78
78
|
kind: 'module',
|
|
79
|
-
line: node
|
|
79
|
+
line: nodeStartLine(node),
|
|
80
80
|
endLine: nodeEndLine(node),
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
return nameNode.text;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
function qualifyName(base: string, currentModule: string | null): string {
|
|
87
|
+
// For qualified names (`function Base.show ... end` inside `module Foo`,
|
|
88
|
+
// or short-form `Foo.bar(x, y) = x + y` inside `module Outer`), the LHS
|
|
89
|
+
// is a `scoped_identifier` already containing the qualifier — skip the
|
|
90
|
+
// module prefix to avoid producing `Foo.Base.show` / `Outer.Foo.bar`.
|
|
91
|
+
if (currentModule && !base.includes('.')) return `${currentModule}.${base}`;
|
|
92
|
+
return base;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Extract the call_expression from a function/macro definition's signature.
|
|
97
|
+
*
|
|
98
|
+
* tree-sitter-julia wraps the signature in a `signature` node whose direct
|
|
99
|
+
* children include the `call_expression` for the function name and parameters.
|
|
100
|
+
* `findChild` only inspects direct children, so we unwrap one level explicitly.
|
|
101
|
+
* Without this step, `findChild(node, 'call_expression')` on a
|
|
102
|
+
* `function_definition` would match the *body's* first call_expression
|
|
103
|
+
* (e.g. `println(...)` inside the body) instead of the signature.
|
|
104
|
+
*
|
|
105
|
+
* Grammar assumption: every `function_definition` / `macro_definition` emits a
|
|
106
|
+
* `signature` child in the current tree-sitter-julia grammar. The fallback to
|
|
107
|
+
* `findChild(node, 'call_expression')` exists only as a defensive measure for
|
|
108
|
+
* grammar drift — if it ever fires on a real definition, that fallback would
|
|
109
|
+
* silently match the first body call_expression and mis-record the function
|
|
110
|
+
* name. Callers must therefore treat a missing `signature` as a parser/grammar
|
|
111
|
+
* mismatch worth investigating, not as a routine code path.
|
|
112
|
+
*/
|
|
113
|
+
function signatureCall(node: TreeSitterNode): TreeSitterNode | null {
|
|
114
|
+
const sig = findChild(node, 'signature');
|
|
115
|
+
if (sig) return findChild(sig, 'call_expression');
|
|
116
|
+
return findChild(node, 'call_expression');
|
|
117
|
+
}
|
|
118
|
+
|
|
86
119
|
function handleFunctionDef(
|
|
87
120
|
node: TreeSitterNode,
|
|
88
121
|
ctx: ExtractorOutput,
|
|
89
122
|
currentModule: string | null,
|
|
90
123
|
): void {
|
|
91
|
-
|
|
92
|
-
const callSig = findChild(node, 'call_expression');
|
|
124
|
+
const callSig = signatureCall(node);
|
|
93
125
|
if (callSig) {
|
|
94
126
|
const funcNameNode = callSig.child(0);
|
|
95
127
|
if (funcNameNode) {
|
|
96
|
-
const name =
|
|
128
|
+
const name = qualifyName(funcNameNode.text, currentModule);
|
|
97
129
|
const params = extractJuliaParams(callSig);
|
|
98
130
|
ctx.definitions.push({
|
|
99
131
|
name,
|
|
100
132
|
kind: 'function',
|
|
101
|
-
line: node
|
|
133
|
+
line: nodeStartLine(node),
|
|
102
134
|
endLine: nodeEndLine(node),
|
|
103
135
|
children: params.length > 0 ? params : undefined,
|
|
104
136
|
});
|
|
@@ -110,11 +142,10 @@ function handleFunctionDef(
|
|
|
110
142
|
const nameNode = node.childForFieldName('name') || findChild(node, 'identifier');
|
|
111
143
|
if (!nameNode) return;
|
|
112
144
|
|
|
113
|
-
const name = currentModule ? `${currentModule}.${nameNode.text}` : nameNode.text;
|
|
114
145
|
ctx.definitions.push({
|
|
115
|
-
name,
|
|
146
|
+
name: qualifyName(nameNode.text, currentModule),
|
|
116
147
|
kind: 'function',
|
|
117
|
-
line: node
|
|
148
|
+
line: nodeStartLine(node),
|
|
118
149
|
endLine: nodeEndLine(node),
|
|
119
150
|
});
|
|
120
151
|
}
|
|
@@ -133,29 +164,86 @@ function handleAssignment(
|
|
|
133
164
|
const funcNameNode = lhs.child(0);
|
|
134
165
|
if (!funcNameNode) return;
|
|
135
166
|
|
|
136
|
-
const name = currentModule ? `${currentModule}.${funcNameNode.text}` : funcNameNode.text;
|
|
137
167
|
const params = extractJuliaParams(lhs);
|
|
138
168
|
|
|
139
169
|
ctx.definitions.push({
|
|
140
|
-
name,
|
|
170
|
+
name: qualifyName(funcNameNode.text, currentModule),
|
|
141
171
|
kind: 'function',
|
|
142
|
-
line: node
|
|
172
|
+
line: nodeStartLine(node),
|
|
143
173
|
endLine: nodeEndLine(node),
|
|
144
174
|
children: params.length > 0 ? params : undefined,
|
|
145
175
|
});
|
|
146
176
|
}
|
|
147
177
|
}
|
|
148
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Locate the base-name identifier within a `type_head` node.
|
|
181
|
+
*
|
|
182
|
+
* Handles plain identifiers, `Name <: Super` binary expressions, and
|
|
183
|
+
* parameterized forms like `Name{T}` / `Name{T} <: Super{T,1}` by recursing
|
|
184
|
+
* into wrapper kinds the Julia grammar actually emits for type heads
|
|
185
|
+
* (binary expressions, parametrized type expressions, parameterized
|
|
186
|
+
* identifiers). Returns `null` when no identifier can be located — callers
|
|
187
|
+
* should skip emitting a definition in that case.
|
|
188
|
+
*
|
|
189
|
+
* Note: `type_parameter_list` / `type_argument_list` are intentionally
|
|
190
|
+
* excluded — Julia's grammar uses `curly_expression` for `{T}` constructs,
|
|
191
|
+
* not those node kinds. Including them would risk recursing into a
|
|
192
|
+
* type-parameter list and returning a type variable (e.g. `T`) instead of
|
|
193
|
+
* the struct name if `findBaseName` were ever called on a node lacking a
|
|
194
|
+
* direct `identifier` child.
|
|
195
|
+
*/
|
|
196
|
+
const TYPE_HEAD_WRAPPERS: ReadonlySet<string> = new Set([
|
|
197
|
+
'binary_expression',
|
|
198
|
+
'parametrized_type_expression',
|
|
199
|
+
'parameterized_identifier',
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
function findBaseName(node: TreeSitterNode): TreeSitterNode | null {
|
|
203
|
+
if (node.type === 'identifier') return node;
|
|
204
|
+
const direct = findChild(node, 'identifier');
|
|
205
|
+
if (direct) return direct;
|
|
206
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
207
|
+
const child = node.child(i);
|
|
208
|
+
if (!child) continue;
|
|
209
|
+
if (TYPE_HEAD_WRAPPERS.has(child.type)) {
|
|
210
|
+
const found = findBaseName(child);
|
|
211
|
+
if (found) return found;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
149
217
|
function handleStructDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
150
218
|
// struct_definition: struct type_head fields... end
|
|
219
|
+
// type_head wraps the name and optional supertype. The name may be a
|
|
220
|
+
// bare `identifier`, a parameterized form (e.g. `Vec{T}`), or either
|
|
221
|
+
// of those nested inside a `binary_expression` (`Name <: Super`).
|
|
151
222
|
const typeHead = findChild(node, 'type_head');
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
223
|
+
if (!typeHead) return;
|
|
224
|
+
|
|
225
|
+
let nameNode: TreeSitterNode | null;
|
|
226
|
+
let supertypeNode: TreeSitterNode | null = null;
|
|
227
|
+
|
|
228
|
+
const binary = findChild(typeHead, 'binary_expression');
|
|
229
|
+
if (binary) {
|
|
230
|
+
// Walk into each side of the binary expression to find the base-name
|
|
231
|
+
// identifier — handles parameterized forms like `Vec{T} <: AbstractArray{T,1}`.
|
|
232
|
+
const sides: TreeSitterNode[] = [];
|
|
233
|
+
for (let i = 0; i < binary.childCount; i++) {
|
|
234
|
+
const c = binary.child(i);
|
|
235
|
+
if (c && c.type !== 'operator') sides.push(c);
|
|
236
|
+
}
|
|
237
|
+
nameNode = sides[0] ? findBaseName(sides[0]) : null;
|
|
238
|
+
supertypeNode = sides[1] ? findBaseName(sides[1]) : null;
|
|
239
|
+
} else {
|
|
240
|
+
nameNode = findBaseName(typeHead);
|
|
241
|
+
}
|
|
242
|
+
|
|
155
243
|
if (!nameNode) return;
|
|
244
|
+
const structName = nameNode.text;
|
|
156
245
|
|
|
157
246
|
const children: SubDeclaration[] = [];
|
|
158
|
-
// Fields are typed_expression children of struct_definition
|
|
159
247
|
for (let i = 0; i < node.childCount; i++) {
|
|
160
248
|
const child = node.child(i);
|
|
161
249
|
if (!child) continue;
|
|
@@ -165,51 +253,49 @@ function handleStructDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
165
253
|
children.push({
|
|
166
254
|
name: fieldName.text,
|
|
167
255
|
kind: 'property',
|
|
168
|
-
line: child
|
|
256
|
+
line: nodeStartLine(child),
|
|
169
257
|
});
|
|
170
258
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
259
|
+
} else if (child.type === 'identifier') {
|
|
260
|
+
// Plain identifier fields (no type annotation) appear as direct
|
|
261
|
+
// identifier children of struct_definition. The type_head is a
|
|
262
|
+
// separate node so there is nothing to filter out here.
|
|
263
|
+
children.push({ name: child.text, kind: 'property', line: nodeStartLine(child) });
|
|
175
264
|
}
|
|
176
265
|
}
|
|
177
266
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const child = subtypeExpr.child(i);
|
|
185
|
-
if (child?.type === 'identifier' && i > 0) {
|
|
186
|
-
ctx.classes.push({
|
|
187
|
-
name: nameNode.text,
|
|
188
|
-
extends: child.text,
|
|
189
|
-
line: node.startPosition.row + 1,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
267
|
+
if (supertypeNode) {
|
|
268
|
+
ctx.classes.push({
|
|
269
|
+
name: structName,
|
|
270
|
+
extends: supertypeNode.text,
|
|
271
|
+
line: nodeStartLine(node),
|
|
272
|
+
});
|
|
194
273
|
}
|
|
195
274
|
|
|
196
275
|
ctx.definitions.push({
|
|
197
|
-
name:
|
|
276
|
+
name: structName,
|
|
198
277
|
kind: 'struct',
|
|
199
|
-
line: node
|
|
278
|
+
line: nodeStartLine(node),
|
|
200
279
|
endLine: nodeEndLine(node),
|
|
201
280
|
children: children.length > 0 ? children : undefined,
|
|
202
281
|
});
|
|
203
282
|
}
|
|
204
283
|
|
|
205
284
|
function handleAbstractDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
206
|
-
|
|
285
|
+
// abstract_definition: `abstract type` type_head `end`
|
|
286
|
+
// The identifier is nested inside `type_head` — possibly wrapped in a
|
|
287
|
+
// `Name <: Super` binary_expression or a `Name{T,...}` parameterized form.
|
|
288
|
+
// Mirror handleStructDef and skip rather than emit a garbled name when no
|
|
289
|
+
// base identifier can be located.
|
|
290
|
+
const typeHead = findChild(node, 'type_head');
|
|
291
|
+
if (!typeHead) return;
|
|
292
|
+
const nameNode = findBaseName(typeHead);
|
|
207
293
|
if (!nameNode) return;
|
|
208
294
|
|
|
209
295
|
ctx.definitions.push({
|
|
210
296
|
name: nameNode.text,
|
|
211
297
|
kind: 'type',
|
|
212
|
-
line: node
|
|
298
|
+
line: nodeStartLine(node),
|
|
213
299
|
endLine: nodeEndLine(node),
|
|
214
300
|
});
|
|
215
301
|
}
|
|
@@ -219,69 +305,108 @@ function handleMacroDef(
|
|
|
219
305
|
ctx: ExtractorOutput,
|
|
220
306
|
currentModule: string | null,
|
|
221
307
|
): void {
|
|
222
|
-
|
|
308
|
+
// macro_definition: `macro` signature/call_expression body `end`.
|
|
309
|
+
// The name lives in the same shape as a function signature — unwrap via
|
|
310
|
+
// signatureCall so we don't pick up an identifier from the body (e.g.
|
|
311
|
+
// `macro mymac(x) x end` would otherwise resolve to `@x`).
|
|
312
|
+
const callSig = signatureCall(node);
|
|
313
|
+
const nameNode =
|
|
314
|
+
callSig?.child(0) ?? node.childForFieldName('name') ?? findChild(node, 'identifier');
|
|
223
315
|
if (!nameNode) return;
|
|
224
316
|
|
|
225
|
-
const
|
|
317
|
+
const base = nameNode.text;
|
|
318
|
+
const name = currentModule ? `${currentModule}.@${base}` : `@${base}`;
|
|
226
319
|
ctx.definitions.push({
|
|
227
320
|
name,
|
|
228
321
|
kind: 'function',
|
|
229
|
-
line: node
|
|
322
|
+
line: nodeStartLine(node),
|
|
230
323
|
endLine: nodeEndLine(node),
|
|
231
324
|
});
|
|
232
325
|
}
|
|
233
326
|
|
|
234
327
|
function handleImport(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
328
|
+
// tree-sitter-julia shapes:
|
|
329
|
+
// `using LinearAlgebra` → using_statement [ using, identifier ]
|
|
330
|
+
// `import Foo.Bar` → import_statement [ import, scoped_identifier ]
|
|
331
|
+
// `import Base: show` → import_statement [ import, selected_import[Base, show] ]
|
|
332
|
+
// `import Foo.Bar: baz` → import_statement [ import, selected_import[scoped_identifier, baz] ]
|
|
235
333
|
const names: string[] = [];
|
|
236
334
|
let source = '';
|
|
237
335
|
|
|
238
336
|
for (let i = 0; i < node.childCount; i++) {
|
|
239
337
|
const child = node.child(i);
|
|
240
338
|
if (!child) continue;
|
|
241
|
-
if (
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
) {
|
|
246
|
-
|
|
247
|
-
names.
|
|
339
|
+
if (child.type === 'identifier' || child.type === 'scoped_identifier') {
|
|
340
|
+
const txt = child.text;
|
|
341
|
+
if (!source) source = txt;
|
|
342
|
+
names.push(txt.split('.').pop() || txt);
|
|
343
|
+
} else if (child.type === 'selected_import') {
|
|
344
|
+
// First identifier-bearing node is the source module; the rest are
|
|
345
|
+
// imported names. The module may itself be a `scoped_identifier`
|
|
346
|
+
// (e.g. `import Foo.Bar: baz`) — handle it alongside bare
|
|
347
|
+
// `identifier` and use the trailing segment as the display name,
|
|
348
|
+
// mirroring the outer loop.
|
|
349
|
+
let first = true;
|
|
350
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
351
|
+
const part = child.child(j);
|
|
352
|
+
if (!part) continue;
|
|
353
|
+
if (part.type !== 'identifier' && part.type !== 'scoped_identifier') continue;
|
|
354
|
+
const txt = part.text;
|
|
355
|
+
if (first) {
|
|
356
|
+
if (!source) source = txt;
|
|
357
|
+
first = false;
|
|
358
|
+
} else {
|
|
359
|
+
names.push(txt.split('.').pop() || txt);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
248
362
|
}
|
|
249
363
|
}
|
|
250
364
|
|
|
251
365
|
if (source) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
});
|
|
366
|
+
// pushImport falls back to source basename for empty `names`. Julia module
|
|
367
|
+
// sources have no `/` separator, so the basename equals `source` — matching
|
|
368
|
+
// the previous explicit `[source]` fallback.
|
|
369
|
+
pushImport(ctx, node, source, names);
|
|
257
370
|
}
|
|
258
371
|
}
|
|
259
372
|
|
|
260
373
|
function handleCall(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
261
374
|
// Don't record if parent is assignment LHS (that's a function definition)
|
|
262
375
|
if (node.parent?.type === 'assignment' && node === node.parent.child(0)) return;
|
|
263
|
-
//
|
|
264
|
-
|
|
376
|
+
// Skip when this call is the signature of a function/macro definition.
|
|
377
|
+
// tree-sitter-julia wraps the signature in a `signature` node whose parent
|
|
378
|
+
// is `function_definition` or `macro_definition`. Body calls (e.g.
|
|
379
|
+
// `println(name)` inside `function greet ... end`) appear as descendants of
|
|
380
|
+
// the body, not as direct children of `signature`, so they are unaffected.
|
|
381
|
+
if (node.parent?.type === 'signature') {
|
|
382
|
+
const grand = node.parent.parent;
|
|
383
|
+
if (grand?.type === 'function_definition' || grand?.type === 'macro_definition') return;
|
|
384
|
+
}
|
|
265
385
|
|
|
266
386
|
const funcNode = node.child(0);
|
|
267
387
|
if (!funcNode) return;
|
|
268
388
|
|
|
269
389
|
if (funcNode.type === 'identifier') {
|
|
270
|
-
ctx
|
|
390
|
+
pushCall(ctx, node, funcNode.text);
|
|
271
391
|
} else if (funcNode.type === 'field_expression' || funcNode.type === 'scoped_identifier') {
|
|
272
392
|
const parts = funcNode.text.split('.');
|
|
273
393
|
if (parts.length >= 2) {
|
|
274
|
-
ctx.
|
|
275
|
-
name: parts[parts.length - 1]!,
|
|
394
|
+
pushCall(ctx, node, parts[parts.length - 1]!, {
|
|
276
395
|
receiver: parts.slice(0, -1).join('.'),
|
|
277
|
-
line: node.startPosition.row + 1,
|
|
278
396
|
});
|
|
279
397
|
} else {
|
|
280
|
-
ctx
|
|
398
|
+
pushCall(ctx, node, funcNode.text);
|
|
281
399
|
}
|
|
282
400
|
}
|
|
283
401
|
}
|
|
284
402
|
|
|
403
|
+
const JULIA_PARAM_WRAPPER_TYPES = new Set([
|
|
404
|
+
'typed_parameter',
|
|
405
|
+
'typed_expression',
|
|
406
|
+
'optional_parameter',
|
|
407
|
+
'default_parameter',
|
|
408
|
+
]);
|
|
409
|
+
|
|
285
410
|
function extractJuliaParams(callExpr: TreeSitterNode): SubDeclaration[] {
|
|
286
411
|
const params: SubDeclaration[] = [];
|
|
287
412
|
const argList = findChild(callExpr, 'argument_list') || findChild(callExpr, 'tuple_expression');
|
|
@@ -291,25 +416,14 @@ function extractJuliaParams(callExpr: TreeSitterNode): SubDeclaration[] {
|
|
|
291
416
|
const child = argList.child(i);
|
|
292
417
|
if (!child) continue;
|
|
293
418
|
if (child.type === 'identifier') {
|
|
294
|
-
params.push({ name: child.text, kind: 'parameter', line: child
|
|
295
|
-
}
|
|
296
|
-
if (child.type === 'typed_parameter' || child.type === 'typed_expression') {
|
|
297
|
-
const nameNode = findChild(child, 'identifier');
|
|
298
|
-
if (nameNode) {
|
|
299
|
-
params.push({
|
|
300
|
-
name: nameNode.text,
|
|
301
|
-
kind: 'parameter',
|
|
302
|
-
line: child.startPosition.row + 1,
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (child.type === 'optional_parameter' || child.type === 'default_parameter') {
|
|
419
|
+
params.push({ name: child.text, kind: 'parameter', line: nodeStartLine(child) });
|
|
420
|
+
} else if (JULIA_PARAM_WRAPPER_TYPES.has(child.type)) {
|
|
307
421
|
const nameNode = findChild(child, 'identifier');
|
|
308
422
|
if (nameNode) {
|
|
309
423
|
params.push({
|
|
310
424
|
name: nameNode.text,
|
|
311
425
|
kind: 'parameter',
|
|
312
|
-
line: child
|
|
426
|
+
line: nodeStartLine(child),
|
|
313
427
|
});
|
|
314
428
|
}
|
|
315
429
|
}
|
package/src/extractors/kotlin.ts
CHANGED
|
@@ -147,11 +147,13 @@ function collectKotlinMethods(node: TreeSitterNode, className: string, ctx: Extr
|
|
|
147
147
|
if (!child || child.type !== 'function_declaration') continue;
|
|
148
148
|
const methName = findChild(child, 'simple_identifier');
|
|
149
149
|
if (methName) {
|
|
150
|
+
const params = extractKotlinParameters(child);
|
|
150
151
|
ctx.definitions.push({
|
|
151
152
|
name: `${className}.${methName.text}`,
|
|
152
153
|
kind: 'method',
|
|
153
154
|
line: child.startPosition.row + 1,
|
|
154
155
|
endLine: child.endPosition.row + 1,
|
|
156
|
+
children: params.length > 0 ? params : undefined,
|
|
155
157
|
visibility: extractModifierVisibility(child),
|
|
156
158
|
});
|
|
157
159
|
}
|
|
@@ -214,11 +216,13 @@ function handleKotlinObjectDecl(node: TreeSitterNode, ctx: ExtractorOutput): voi
|
|
|
214
216
|
if (child && child.type === 'function_declaration') {
|
|
215
217
|
const methName = findChild(child, 'simple_identifier');
|
|
216
218
|
if (methName) {
|
|
219
|
+
const params = extractKotlinParameters(child);
|
|
217
220
|
ctx.definitions.push({
|
|
218
221
|
name: `${nameNode.text}.${methName.text}`,
|
|
219
222
|
kind: 'method',
|
|
220
223
|
line: child.startPosition.row + 1,
|
|
221
224
|
endLine: child.endPosition.row + 1,
|
|
225
|
+
children: params.length > 0 ? params : undefined,
|
|
222
226
|
visibility: extractModifierVisibility(child),
|
|
223
227
|
});
|
|
224
228
|
}
|