@optave/codegraph 3.8.0 → 3.9.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 +13 -8
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +137 -86
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/metrics.d.ts +0 -3
- package/dist/ast-analysis/metrics.d.ts.map +1 -1
- package/dist/ast-analysis/metrics.js +30 -13
- package/dist/ast-analysis/metrics.js.map +1 -1
- package/dist/ast-analysis/shared.d.ts.map +1 -1
- package/dist/ast-analysis/shared.js +24 -19
- package/dist/ast-analysis/shared.js.map +1 -1
- package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
- package/dist/ast-analysis/visitor-utils.js +55 -39
- package/dist/ast-analysis/visitor-utils.js.map +1 -1
- package/dist/ast-analysis/visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitor.js +91 -70
- package/dist/ast-analysis/visitor.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 +54 -58
- 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 +81 -39
- package/dist/ast-analysis/visitors/complexity-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 +57 -38
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/branch-compare.d.ts.map +1 -1
- package/dist/cli/commands/branch-compare.js +4 -0
- package/dist/cli/commands/branch-compare.js.map +1 -1
- package/dist/cli/commands/diff-impact.d.ts.map +1 -1
- package/dist/cli/commands/diff-impact.js +2 -1
- package/dist/cli/commands/diff-impact.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +3 -2
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +16 -2
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +29 -26
- package/dist/db/connection.js.map +1 -1
- package/dist/db/query-builder.d.ts.map +1 -1
- package/dist/db/query-builder.js +16 -5
- package/dist/db/query-builder.js.map +1 -1
- package/dist/db/repository/base.d.ts +16 -0
- package/dist/db/repository/base.d.ts.map +1 -1
- package/dist/db/repository/base.js +31 -0
- package/dist/db/repository/base.js.map +1 -1
- package/dist/db/repository/native-repository.d.ts +7 -1
- package/dist/db/repository/native-repository.d.ts.map +1 -1
- package/dist/db/repository/native-repository.js +100 -1
- package/dist/db/repository/native-repository.js.map +1 -1
- package/dist/db/repository/nodes.d.ts.map +1 -1
- package/dist/db/repository/nodes.js +8 -4
- package/dist/db/repository/nodes.js.map +1 -1
- package/dist/db/repository/sqlite-repository.d.ts +4 -0
- package/dist/db/repository/sqlite-repository.d.ts.map +1 -1
- package/dist/db/repository/sqlite-repository.js +51 -0
- package/dist/db/repository/sqlite-repository.js.map +1 -1
- package/dist/domain/analysis/brief.d.ts.map +1 -1
- package/dist/domain/analysis/brief.js +13 -17
- package/dist/domain/analysis/brief.js.map +1 -1
- package/dist/domain/analysis/context.d.ts.map +1 -1
- package/dist/domain/analysis/context.js +14 -11
- 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 +64 -59
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts +2 -7
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +33 -31
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/implementations.d.ts.map +1 -1
- package/dist/domain/analysis/implementations.js +11 -19
- package/dist/domain/analysis/implementations.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +55 -76
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/query-helpers.d.ts +7 -0
- package/dist/domain/analysis/query-helpers.d.ts.map +1 -1
- package/dist/domain/analysis/query-helpers.js +15 -1
- package/dist/domain/analysis/query-helpers.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +352 -107
- 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 +49 -18
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +2 -2
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +2 -2
- 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 +32 -21
- 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 +95 -84
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/cycles.d.ts +6 -0
- package/dist/domain/graph/cycles.d.ts.map +1 -1
- package/dist/domain/graph/cycles.js +114 -22
- package/dist/domain/graph/cycles.js.map +1 -1
- package/dist/domain/graph/resolve.js +1 -1
- package/dist/domain/graph/resolve.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts +2 -0
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +170 -75
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +3 -4
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +141 -89
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/generator.js +1 -1
- package/dist/domain/search/generator.js.map +1 -1
- package/dist/domain/search/models.d.ts +4 -3
- package/dist/domain/search/models.d.ts.map +1 -1
- package/dist/domain/search/models.js +23 -8
- 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 +29 -18
- package/dist/domain/search/search/hybrid.js.map +1 -1
- package/dist/extractors/go.js +36 -33
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +40 -29
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.js +58 -46
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.js +65 -54
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.js +84 -78
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/python.js +29 -24
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/rust.js +41 -32
- package/dist/extractors/rust.js.map +1 -1
- package/dist/extractors/solidity.js +58 -67
- package/dist/extractors/solidity.js.map +1 -1
- package/dist/extractors/swift.js +83 -81
- package/dist/extractors/swift.js.map +1 -1
- package/dist/extractors/zig.js +58 -60
- package/dist/extractors/zig.js.map +1 -1
- package/dist/features/ast.d.ts +16 -14
- package/dist/features/ast.d.ts.map +1 -1
- package/dist/features/ast.js +83 -81
- package/dist/features/ast.js.map +1 -1
- package/dist/features/audit.d.ts.map +1 -1
- package/dist/features/audit.js +8 -6
- package/dist/features/audit.js.map +1 -1
- package/dist/features/branch-compare.d.ts.map +1 -1
- package/dist/features/branch-compare.js +69 -72
- package/dist/features/branch-compare.js.map +1 -1
- package/dist/features/communities.d.ts.map +1 -1
- package/dist/features/communities.js +19 -7
- package/dist/features/communities.js.map +1 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +120 -125
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +136 -137
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/flow.d.ts.map +1 -1
- package/dist/features/flow.js +84 -79
- package/dist/features/flow.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +69 -65
- package/dist/features/structure-query.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +70 -55
- 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 +288 -266
- package/dist/graph/algorithms/leiden/partition.js.map +1 -1
- package/dist/graph/model.d.ts.map +1 -1
- package/dist/graph/model.js +5 -1
- package/dist/graph/model.js.map +1 -1
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +6 -4
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/suppress.d.ts +25 -0
- package/dist/infrastructure/suppress.d.ts.map +1 -0
- package/dist/infrastructure/suppress.js +43 -0
- package/dist/infrastructure/suppress.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +29 -24
- package/dist/mcp/server.js.map +1 -1
- package/dist/presentation/dataflow.d.ts.map +1 -1
- package/dist/presentation/dataflow.js +47 -38
- package/dist/presentation/dataflow.js.map +1 -1
- package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -1
- package/dist/presentation/diff-impact-mermaid.js +60 -51
- package/dist/presentation/diff-impact-mermaid.js.map +1 -1
- package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
- package/dist/presentation/queries-cli/exports.js +20 -14
- 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 +15 -13
- package/dist/presentation/queries-cli/impact.js.map +1 -1
- package/dist/presentation/queries-cli/inspect.d.ts.map +1 -1
- package/dist/presentation/queries-cli/inspect.js +101 -79
- package/dist/presentation/queries-cli/inspect.js.map +1 -1
- package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
- package/dist/presentation/queries-cli/overview.js +25 -16
- package/dist/presentation/queries-cli/overview.js.map +1 -1
- package/dist/presentation/queries-cli/path.js +26 -20
- package/dist/presentation/queries-cli/path.js.map +1 -1
- package/dist/presentation/result-formatter.d.ts +10 -0
- package/dist/presentation/result-formatter.d.ts.map +1 -1
- package/dist/presentation/result-formatter.js +16 -1
- package/dist/presentation/result-formatter.js.map +1 -1
- package/dist/presentation/viewer.d.ts.map +1 -1
- package/dist/presentation/viewer.js +18 -12
- package/dist/presentation/viewer.js.map +1 -1
- package/dist/shared/errors.d.ts +5 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +5 -0
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/hierarchy.d.ts +8 -2
- package/dist/shared/hierarchy.d.ts.map +1 -1
- package/dist/shared/hierarchy.js +42 -1
- package/dist/shared/hierarchy.js.map +1 -1
- package/dist/shared/normalize.d.ts +6 -1
- package/dist/shared/normalize.d.ts.map +1 -1
- package/dist/shared/normalize.js +20 -12
- package/dist/shared/normalize.js.map +1 -1
- package/dist/shared/paginate.d.ts +0 -9
- package/dist/shared/paginate.d.ts.map +1 -1
- package/dist/shared/paginate.js +0 -15
- package/dist/shared/paginate.js.map +1 -1
- package/dist/types.d.ts +12 -5
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-erlang.wasm +0 -0
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +9 -9
- package/src/ast-analysis/engine.ts +176 -104
- package/src/ast-analysis/metrics.ts +33 -11
- package/src/ast-analysis/shared.ts +33 -24
- package/src/ast-analysis/visitor-utils.ts +52 -32
- package/src/ast-analysis/visitor.ts +132 -71
- package/src/ast-analysis/visitors/ast-store-visitor.ts +53 -50
- package/src/ast-analysis/visitors/complexity-visitor.ts +89 -40
- package/src/ast-analysis/visitors/dataflow-visitor.ts +87 -43
- package/src/cli/commands/branch-compare.ts +4 -0
- package/src/cli/commands/diff-impact.ts +2 -1
- package/src/cli/commands/info.ts +3 -2
- package/src/cli/commands/watch.ts +16 -2
- package/src/db/connection.ts +29 -28
- package/src/db/query-builder.ts +15 -3
- package/src/db/repository/base.ts +34 -0
- package/src/db/repository/native-repository.ts +104 -1
- package/src/db/repository/nodes.ts +13 -8
- package/src/db/repository/sqlite-repository.ts +55 -0
- package/src/domain/analysis/brief.ts +15 -25
- package/src/domain/analysis/context.ts +17 -10
- package/src/domain/analysis/dependencies.ts +77 -81
- package/src/domain/analysis/fn-impact.ts +36 -43
- package/src/domain/analysis/implementations.ts +11 -17
- package/src/domain/analysis/module-map.ts +58 -92
- package/src/domain/analysis/query-helpers.ts +18 -1
- package/src/domain/graph/builder/pipeline.ts +409 -99
- package/src/domain/graph/builder/stages/build-edges.ts +45 -19
- package/src/domain/graph/builder/stages/detect-changes.ts +2 -2
- package/src/domain/graph/builder/stages/finalize.ts +2 -2
- package/src/domain/graph/builder/stages/insert-nodes.ts +59 -34
- package/src/domain/graph/builder/stages/resolve-imports.ts +122 -100
- package/src/domain/graph/cycles.ts +110 -23
- package/src/domain/graph/resolve.ts +1 -1
- package/src/domain/graph/watcher.ts +202 -96
- package/src/domain/parser.ts +143 -89
- package/src/domain/search/generator.ts +1 -1
- package/src/domain/search/models.ts +26 -7
- package/src/domain/search/search/hybrid.ts +69 -51
- package/src/extractors/go.ts +43 -33
- package/src/extractors/helpers.ts +37 -23
- package/src/extractors/java.ts +66 -47
- package/src/extractors/javascript.ts +66 -54
- package/src/extractors/kotlin.ts +84 -77
- package/src/extractors/python.ts +31 -25
- package/src/extractors/rust.ts +37 -29
- package/src/extractors/solidity.ts +57 -61
- package/src/extractors/swift.ts +81 -80
- package/src/extractors/zig.ts +58 -61
- package/src/features/ast.ts +130 -110
- package/src/features/audit.ts +8 -6
- package/src/features/branch-compare.ts +105 -79
- package/src/features/communities.ts +25 -10
- package/src/features/complexity.ts +171 -134
- package/src/features/dataflow.ts +165 -175
- package/src/features/flow.ts +129 -92
- package/src/features/structure-query.ts +79 -64
- package/src/graph/algorithms/leiden/optimiser.ts +99 -55
- package/src/graph/algorithms/leiden/partition.ts +359 -294
- package/src/graph/model.ts +6 -1
- package/src/infrastructure/config.ts +6 -4
- package/src/infrastructure/suppress.ts +47 -0
- package/src/mcp/server.ts +53 -37
- package/src/presentation/dataflow.ts +50 -44
- package/src/presentation/diff-impact-mermaid.ts +104 -62
- package/src/presentation/queries-cli/exports.ts +21 -13
- package/src/presentation/queries-cli/impact.ts +15 -13
- package/src/presentation/queries-cli/inspect.ts +100 -81
- package/src/presentation/queries-cli/overview.ts +26 -16
- package/src/presentation/queries-cli/path.ts +33 -25
- package/src/presentation/result-formatter.ts +19 -1
- package/src/presentation/viewer.ts +42 -14
- package/src/shared/errors.ts +6 -0
- package/src/shared/hierarchy.ts +50 -2
- package/src/shared/normalize.ts +31 -12
- package/src/shared/paginate.ts +0 -17
- package/src/types.ts +26 -5
package/src/extractors/kotlin.ts
CHANGED
|
@@ -81,48 +81,7 @@ function handleKotlinClassDecl(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
81
81
|
|
|
82
82
|
const kind = isInterface ? 'interface' : isEnum ? 'enum' : 'class';
|
|
83
83
|
|
|
84
|
-
const children
|
|
85
|
-
if (isEnum) {
|
|
86
|
-
// Enum entries are inside class_body
|
|
87
|
-
const body = findChild(node, 'class_body');
|
|
88
|
-
if (body) {
|
|
89
|
-
for (let i = 0; i < body.childCount; i++) {
|
|
90
|
-
const child = body.child(i);
|
|
91
|
-
if (child && child.type === 'enum_entry') {
|
|
92
|
-
const entryName = findChild(child, 'simple_identifier');
|
|
93
|
-
if (entryName) {
|
|
94
|
-
children.push({
|
|
95
|
-
name: entryName.text,
|
|
96
|
-
kind: 'constant',
|
|
97
|
-
line: child.startPosition.row + 1,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
// Extract properties from class_body
|
|
105
|
-
const body = findChild(node, 'class_body');
|
|
106
|
-
if (body) {
|
|
107
|
-
for (let i = 0; i < body.childCount; i++) {
|
|
108
|
-
const child = body.child(i);
|
|
109
|
-
if (child && child.type === 'property_declaration') {
|
|
110
|
-
const propName = findChild(child, 'variable_declaration');
|
|
111
|
-
if (propName) {
|
|
112
|
-
const id = findChild(propName, 'simple_identifier');
|
|
113
|
-
if (id) {
|
|
114
|
-
children.push({
|
|
115
|
-
name: id.text,
|
|
116
|
-
kind: 'property',
|
|
117
|
-
line: child.startPosition.row + 1,
|
|
118
|
-
visibility: extractModifierVisibility(child),
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
84
|
+
const children = isEnum ? collectKotlinEnumEntries(node) : collectKotlinProperties(node);
|
|
126
85
|
|
|
127
86
|
ctx.definitions.push({
|
|
128
87
|
name,
|
|
@@ -132,27 +91,79 @@ function handleKotlinClassDecl(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
132
91
|
children: children.length > 0 ? children : undefined,
|
|
133
92
|
});
|
|
134
93
|
|
|
135
|
-
|
|
94
|
+
collectKotlinMethods(node, name, ctx);
|
|
95
|
+
collectKotlinInheritance(node, name, ctx);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Collect enum constant entries from a class_body. */
|
|
99
|
+
function collectKotlinEnumEntries(node: TreeSitterNode): SubDeclaration[] {
|
|
100
|
+
const entries: SubDeclaration[] = [];
|
|
136
101
|
const body = findChild(node, 'class_body');
|
|
137
|
-
if (body)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
visibility: extractModifierVisibility(child),
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
102
|
+
if (!body) return entries;
|
|
103
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
104
|
+
const child = body.child(i);
|
|
105
|
+
if (!child || child.type !== 'enum_entry') continue;
|
|
106
|
+
const entryName = findChild(child, 'simple_identifier');
|
|
107
|
+
if (entryName) {
|
|
108
|
+
entries.push({
|
|
109
|
+
name: entryName.text,
|
|
110
|
+
kind: 'constant',
|
|
111
|
+
line: child.startPosition.row + 1,
|
|
112
|
+
});
|
|
152
113
|
}
|
|
153
114
|
}
|
|
115
|
+
return entries;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Collect property declarations from a class_body. */
|
|
119
|
+
function collectKotlinProperties(node: TreeSitterNode): SubDeclaration[] {
|
|
120
|
+
const props: SubDeclaration[] = [];
|
|
121
|
+
const body = findChild(node, 'class_body');
|
|
122
|
+
if (!body) return props;
|
|
123
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
124
|
+
const child = body.child(i);
|
|
125
|
+
if (!child || child.type !== 'property_declaration') continue;
|
|
126
|
+
const varDecl = findChild(child, 'variable_declaration');
|
|
127
|
+
if (!varDecl) continue;
|
|
128
|
+
const id = findChild(varDecl, 'simple_identifier');
|
|
129
|
+
if (id) {
|
|
130
|
+
props.push({
|
|
131
|
+
name: id.text,
|
|
132
|
+
kind: 'property',
|
|
133
|
+
line: child.startPosition.row + 1,
|
|
134
|
+
visibility: extractModifierVisibility(child),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return props;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Collect method declarations from a class_body. */
|
|
142
|
+
function collectKotlinMethods(node: TreeSitterNode, className: string, ctx: ExtractorOutput): void {
|
|
143
|
+
const body = findChild(node, 'class_body');
|
|
144
|
+
if (!body) return;
|
|
145
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
146
|
+
const child = body.child(i);
|
|
147
|
+
if (!child || child.type !== 'function_declaration') continue;
|
|
148
|
+
const methName = findChild(child, 'simple_identifier');
|
|
149
|
+
if (methName) {
|
|
150
|
+
ctx.definitions.push({
|
|
151
|
+
name: `${className}.${methName.text}`,
|
|
152
|
+
kind: 'method',
|
|
153
|
+
line: child.startPosition.row + 1,
|
|
154
|
+
endLine: child.endPosition.row + 1,
|
|
155
|
+
visibility: extractModifierVisibility(child),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
154
160
|
|
|
155
|
-
|
|
161
|
+
/** Collect inheritance relationships from delegation_specifier children. */
|
|
162
|
+
function collectKotlinInheritance(
|
|
163
|
+
node: TreeSitterNode,
|
|
164
|
+
className: string,
|
|
165
|
+
ctx: ExtractorOutput,
|
|
166
|
+
): void {
|
|
156
167
|
for (let i = 0; i < node.childCount; i++) {
|
|
157
168
|
const child = node.child(i);
|
|
158
169
|
if (!child || child.type !== 'delegation_specifier') continue;
|
|
@@ -161,30 +172,26 @@ function handleKotlinClassDecl(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
161
172
|
const ctorInvocation = findChild(child, 'constructor_invocation');
|
|
162
173
|
if (ctorInvocation) {
|
|
163
174
|
const userType = findChild(ctorInvocation, 'user_type');
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
});
|
|
172
|
-
}
|
|
175
|
+
const typeId = userType ? findChild(userType, 'type_identifier') : null;
|
|
176
|
+
if (typeId) {
|
|
177
|
+
ctx.classes.push({
|
|
178
|
+
name: className,
|
|
179
|
+
extends: typeId.text,
|
|
180
|
+
line: node.startPosition.row + 1,
|
|
181
|
+
});
|
|
173
182
|
}
|
|
174
183
|
continue;
|
|
175
184
|
}
|
|
176
185
|
|
|
177
186
|
// user_type > type_identifier (implements)
|
|
178
187
|
const userType = findChild(child, 'user_type');
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
+
const typeId = userType ? findChild(userType, 'type_identifier') : null;
|
|
189
|
+
if (typeId) {
|
|
190
|
+
ctx.classes.push({
|
|
191
|
+
name: className,
|
|
192
|
+
implements: typeId.text,
|
|
193
|
+
line: node.startPosition.row + 1,
|
|
194
|
+
});
|
|
188
195
|
}
|
|
189
196
|
}
|
|
190
197
|
}
|
package/src/extractors/python.ts
CHANGED
|
@@ -245,35 +245,41 @@ function extractPythonParameters(fnNode: TreeSitterNode): SubDeclaration[] {
|
|
|
245
245
|
for (let i = 0; i < paramsNode.childCount; i++) {
|
|
246
246
|
const child = paramsNode.child(i);
|
|
247
247
|
if (!child) continue;
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
params.push({ name: child.text, kind: 'parameter', line: child.startPosition.row + 1 });
|
|
251
|
-
} else if (
|
|
252
|
-
t === 'typed_parameter' ||
|
|
253
|
-
t === 'default_parameter' ||
|
|
254
|
-
t === 'typed_default_parameter'
|
|
255
|
-
) {
|
|
256
|
-
const nameNode = child.childForFieldName('name') || child.child(0);
|
|
257
|
-
if (nameNode && nameNode.type === 'identifier') {
|
|
258
|
-
params.push({
|
|
259
|
-
name: nameNode.text,
|
|
260
|
-
kind: 'parameter',
|
|
261
|
-
line: child.startPosition.row + 1,
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
} else if (t === 'list_splat_pattern' || t === 'dictionary_splat_pattern') {
|
|
265
|
-
for (let j = 0; j < child.childCount; j++) {
|
|
266
|
-
const inner = child.child(j);
|
|
267
|
-
if (inner && inner.type === 'identifier') {
|
|
268
|
-
params.push({ name: inner.text, kind: 'parameter', line: child.startPosition.row + 1 });
|
|
269
|
-
break;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
248
|
+
const param = extractSinglePyParam(child);
|
|
249
|
+
if (param) params.push(param);
|
|
273
250
|
}
|
|
274
251
|
return params;
|
|
275
252
|
}
|
|
276
253
|
|
|
254
|
+
/** Extract a single parameter declaration from a parameter node. */
|
|
255
|
+
function extractSinglePyParam(child: TreeSitterNode): SubDeclaration | null {
|
|
256
|
+
const t = child.type;
|
|
257
|
+
if (t === 'identifier') {
|
|
258
|
+
return { name: child.text, kind: 'parameter', line: child.startPosition.row + 1 };
|
|
259
|
+
}
|
|
260
|
+
if (t === 'typed_parameter' || t === 'default_parameter' || t === 'typed_default_parameter') {
|
|
261
|
+
const nameNode = child.childForFieldName('name') || child.child(0);
|
|
262
|
+
if (nameNode && nameNode.type === 'identifier') {
|
|
263
|
+
return { name: nameNode.text, kind: 'parameter', line: child.startPosition.row + 1 };
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (t === 'list_splat_pattern' || t === 'dictionary_splat_pattern') {
|
|
267
|
+
return extractSplatParam(child);
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Extract the identifier name from a *args or **kwargs splat pattern. */
|
|
273
|
+
function extractSplatParam(node: TreeSitterNode): SubDeclaration | null {
|
|
274
|
+
for (let j = 0; j < node.childCount; j++) {
|
|
275
|
+
const inner = node.child(j);
|
|
276
|
+
if (inner && inner.type === 'identifier') {
|
|
277
|
+
return { name: inner.text, kind: 'parameter', line: node.startPosition.row + 1 };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
|
|
277
283
|
/** Extract class-level assignment properties from expression statements. */
|
|
278
284
|
function extractClassAssignment(
|
|
279
285
|
child: TreeSitterNode,
|
package/src/extractors/rust.ts
CHANGED
|
@@ -138,19 +138,22 @@ function handleRustTraitItem(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
138
138
|
endLine: nodeEndLine(node),
|
|
139
139
|
});
|
|
140
140
|
const body = node.childForFieldName('body');
|
|
141
|
-
if (body)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
141
|
+
if (body) extractTraitMethods(body, nameNode.text, ctx);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Extract method signatures/definitions from a trait body. */
|
|
145
|
+
function extractTraitMethods(body: TreeSitterNode, traitName: string, ctx: ExtractorOutput): void {
|
|
146
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
147
|
+
const child = body.child(i);
|
|
148
|
+
if (child && (child.type === 'function_signature_item' || child.type === 'function_item')) {
|
|
149
|
+
const methName = child.childForFieldName('name');
|
|
150
|
+
if (methName) {
|
|
151
|
+
ctx.definitions.push({
|
|
152
|
+
name: `${traitName}.${methName.text}`,
|
|
153
|
+
kind: 'method',
|
|
154
|
+
line: child.startPosition.row + 1,
|
|
155
|
+
endLine: child.endPosition.row + 1,
|
|
156
|
+
});
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
}
|
|
@@ -185,25 +188,30 @@ function handleRustUseDecl(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
185
188
|
function handleRustCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
186
189
|
const fn = node.childForFieldName('function');
|
|
187
190
|
if (!fn) return;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
const call = extractRustCallInfo(fn, node.startPosition.row + 1);
|
|
192
|
+
if (call) ctx.calls.push(call);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Extract call info from a Rust call function node. */
|
|
196
|
+
function extractRustCallInfo(fn: TreeSitterNode, line: number): Call | null {
|
|
197
|
+
if (fn.type === 'identifier') return { name: fn.text, line };
|
|
198
|
+
if (fn.type === 'field_expression') {
|
|
191
199
|
const field = fn.childForFieldName('field');
|
|
192
|
-
if (field)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
if (!field) return null;
|
|
201
|
+
const value = fn.childForFieldName('value');
|
|
202
|
+
const call: Call = { name: field.text, line };
|
|
203
|
+
if (value) call.receiver = value.text;
|
|
204
|
+
return call;
|
|
205
|
+
}
|
|
206
|
+
if (fn.type === 'scoped_identifier') {
|
|
199
207
|
const name = fn.childForFieldName('name');
|
|
200
|
-
if (name)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
208
|
+
if (!name) return null;
|
|
209
|
+
const path = fn.childForFieldName('path');
|
|
210
|
+
const call: Call = { name: name.text, line };
|
|
211
|
+
if (path) call.receiver = path.text;
|
|
212
|
+
return call;
|
|
206
213
|
}
|
|
214
|
+
return null;
|
|
207
215
|
}
|
|
208
216
|
|
|
209
217
|
function handleRustMacroInvocation(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
@@ -97,60 +97,8 @@ function handleContractDecl(
|
|
|
97
97
|
if (!nameNode) return;
|
|
98
98
|
const name = nameNode.text;
|
|
99
99
|
|
|
100
|
-
const members: SubDeclaration[] = [];
|
|
101
100
|
const body = node.childForFieldName('body') || findChild(node, 'contract_body');
|
|
102
|
-
|
|
103
|
-
for (let i = 0; i < body.childCount; i++) {
|
|
104
|
-
const child = body.child(i);
|
|
105
|
-
if (!child) continue;
|
|
106
|
-
if (child.type === 'function_definition') {
|
|
107
|
-
const fnName = child.childForFieldName('name');
|
|
108
|
-
if (fnName) {
|
|
109
|
-
members.push({ name: fnName.text, kind: 'method', line: child.startPosition.row + 1 });
|
|
110
|
-
}
|
|
111
|
-
} else if (child.type === 'state_variable_declaration') {
|
|
112
|
-
const varName = child.childForFieldName('name');
|
|
113
|
-
if (varName) {
|
|
114
|
-
members.push({
|
|
115
|
-
name: varName.text,
|
|
116
|
-
kind: 'property',
|
|
117
|
-
line: child.startPosition.row + 1,
|
|
118
|
-
visibility: extractSolVisibility(child),
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
} else if (child.type === 'event_definition') {
|
|
122
|
-
const evName = child.childForFieldName('name');
|
|
123
|
-
if (evName) {
|
|
124
|
-
members.push({
|
|
125
|
-
name: evName.text,
|
|
126
|
-
kind: 'property',
|
|
127
|
-
decorators: ['event'],
|
|
128
|
-
line: child.startPosition.row + 1,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
} else if (child.type === 'error_declaration') {
|
|
132
|
-
const errName = child.childForFieldName('name');
|
|
133
|
-
if (errName) {
|
|
134
|
-
members.push({
|
|
135
|
-
name: errName.text,
|
|
136
|
-
kind: 'property',
|
|
137
|
-
decorators: ['error'],
|
|
138
|
-
line: child.startPosition.row + 1,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
} else if (child.type === 'modifier_definition') {
|
|
142
|
-
const modName = child.childForFieldName('name');
|
|
143
|
-
if (modName) {
|
|
144
|
-
members.push({
|
|
145
|
-
name: modName.text,
|
|
146
|
-
kind: 'method',
|
|
147
|
-
decorators: ['modifier'],
|
|
148
|
-
line: child.startPosition.row + 1,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
101
|
+
const members = body ? extractContractMembers(body) : [];
|
|
154
102
|
|
|
155
103
|
ctx.definitions.push({
|
|
156
104
|
name,
|
|
@@ -160,15 +108,63 @@ function handleContractDecl(
|
|
|
160
108
|
children: members.length > 0 ? members : undefined,
|
|
161
109
|
});
|
|
162
110
|
|
|
163
|
-
|
|
111
|
+
extractInheritance(node, name, ctx);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Extract member declarations from a contract body node. */
|
|
115
|
+
function extractContractMembers(body: TreeSitterNode): SubDeclaration[] {
|
|
116
|
+
const members: SubDeclaration[] = [];
|
|
117
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
118
|
+
const child = body.child(i);
|
|
119
|
+
if (!child) continue;
|
|
120
|
+
const member = extractContractMember(child);
|
|
121
|
+
if (member) members.push(member);
|
|
122
|
+
}
|
|
123
|
+
return members;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Map a single contract body child to a SubDeclaration, or null if not a recognized member. */
|
|
127
|
+
function extractContractMember(child: TreeSitterNode): SubDeclaration | null {
|
|
128
|
+
const line = child.startPosition.row + 1;
|
|
129
|
+
switch (child.type) {
|
|
130
|
+
case 'function_definition': {
|
|
131
|
+
const fnName = child.childForFieldName('name');
|
|
132
|
+
return fnName ? { name: fnName.text, kind: 'method', line } : null;
|
|
133
|
+
}
|
|
134
|
+
case 'state_variable_declaration': {
|
|
135
|
+
const varName = child.childForFieldName('name');
|
|
136
|
+
return varName
|
|
137
|
+
? { name: varName.text, kind: 'property', line, visibility: extractSolVisibility(child) }
|
|
138
|
+
: null;
|
|
139
|
+
}
|
|
140
|
+
case 'event_definition': {
|
|
141
|
+
const evName = child.childForFieldName('name');
|
|
142
|
+
return evName ? { name: evName.text, kind: 'property', decorators: ['event'], line } : null;
|
|
143
|
+
}
|
|
144
|
+
case 'error_declaration': {
|
|
145
|
+
const errName = child.childForFieldName('name');
|
|
146
|
+
return errName ? { name: errName.text, kind: 'property', decorators: ['error'], line } : null;
|
|
147
|
+
}
|
|
148
|
+
case 'modifier_definition': {
|
|
149
|
+
const modName = child.childForFieldName('name');
|
|
150
|
+
return modName
|
|
151
|
+
? { name: modName.text, kind: 'method', decorators: ['modifier'], line }
|
|
152
|
+
: null;
|
|
153
|
+
}
|
|
154
|
+
default:
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Extract inheritance (extends) relationships from a contract node. */
|
|
160
|
+
function extractInheritance(node: TreeSitterNode, name: string, ctx: ExtractorOutput): void {
|
|
164
161
|
const inheritance = findChild(node, 'inheritance_specifier');
|
|
165
|
-
if (inheritance)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
162
|
+
if (!inheritance) return;
|
|
163
|
+
for (let i = 0; i < inheritance.childCount; i++) {
|
|
164
|
+
const child = inheritance.child(i);
|
|
165
|
+
if (!child) continue;
|
|
166
|
+
if (child.type === 'user_defined_type' || child.type === 'identifier') {
|
|
167
|
+
ctx.classes.push({ name, extends: child.text, line: node.startPosition.row + 1 });
|
|
172
168
|
}
|
|
173
169
|
}
|
|
174
170
|
}
|
package/src/extractors/swift.ts
CHANGED
|
@@ -73,49 +73,7 @@ function handleSwiftClassDecl(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
73
73
|
|
|
74
74
|
const kind = isEnum ? 'enum' : isStruct ? 'struct' : 'class';
|
|
75
75
|
|
|
76
|
-
const children
|
|
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
|
-
}
|
|
76
|
+
const children = isEnum ? collectSwiftEnumEntries(node) : collectSwiftProperties(node);
|
|
119
77
|
|
|
120
78
|
ctx.definitions.push({
|
|
121
79
|
name,
|
|
@@ -125,52 +83,95 @@ function handleSwiftClassDecl(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
125
83
|
children: children.length > 0 ? children : undefined,
|
|
126
84
|
});
|
|
127
85
|
|
|
128
|
-
|
|
86
|
+
collectSwiftMethods(node, name, ctx);
|
|
87
|
+
collectSwiftInheritance(node, name, ctx);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Collect enum constant entries from an enum_class_body. */
|
|
91
|
+
function collectSwiftEnumEntries(node: TreeSitterNode): SubDeclaration[] {
|
|
92
|
+
const entries: SubDeclaration[] = [];
|
|
93
|
+
const body = findChild(node, 'enum_class_body');
|
|
94
|
+
if (!body) return entries;
|
|
95
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
96
|
+
const child = body.child(i);
|
|
97
|
+
if (!child || child.type !== 'enum_entry') continue;
|
|
98
|
+
const entryName = findChild(child, 'simple_identifier');
|
|
99
|
+
if (entryName) {
|
|
100
|
+
entries.push({
|
|
101
|
+
name: entryName.text,
|
|
102
|
+
kind: 'constant',
|
|
103
|
+
line: child.startPosition.row + 1,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return entries;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Collect property declarations from a class_body. */
|
|
111
|
+
function collectSwiftProperties(node: TreeSitterNode): SubDeclaration[] {
|
|
112
|
+
const props: SubDeclaration[] = [];
|
|
113
|
+
const body = findChild(node, 'class_body');
|
|
114
|
+
if (!body) return props;
|
|
115
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
116
|
+
const child = body.child(i);
|
|
117
|
+
if (!child || child.type !== 'property_declaration') continue;
|
|
118
|
+
const pattern = findChild(child, 'pattern');
|
|
119
|
+
if (!pattern) continue;
|
|
120
|
+
const propName = findChild(pattern, 'simple_identifier');
|
|
121
|
+
if (propName) {
|
|
122
|
+
props.push({
|
|
123
|
+
name: propName.text,
|
|
124
|
+
kind: 'property',
|
|
125
|
+
line: child.startPosition.row + 1,
|
|
126
|
+
visibility: extractModifierVisibility(child),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return props;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Collect method declarations from class_body or enum_class_body. */
|
|
134
|
+
function collectSwiftMethods(node: TreeSitterNode, className: string, ctx: ExtractorOutput): void {
|
|
129
135
|
const body = findChild(node, 'class_body') || findChild(node, 'enum_class_body');
|
|
130
|
-
if (body)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
}
|
|
136
|
+
if (!body) return;
|
|
137
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
138
|
+
const child = body.child(i);
|
|
139
|
+
if (!child || child.type !== 'function_declaration') continue;
|
|
140
|
+
const methName = findChild(child, 'simple_identifier');
|
|
141
|
+
if (methName) {
|
|
142
|
+
ctx.definitions.push({
|
|
143
|
+
name: `${className}.${methName.text}`,
|
|
144
|
+
kind: 'method',
|
|
145
|
+
line: child.startPosition.row + 1,
|
|
146
|
+
endLine: child.endPosition.row + 1,
|
|
147
|
+
visibility: extractModifierVisibility(child),
|
|
148
|
+
});
|
|
145
149
|
}
|
|
146
150
|
}
|
|
151
|
+
}
|
|
147
152
|
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
/** Collect inheritance from inheritance_specifier children. First = extends, rest = implements. */
|
|
154
|
+
function collectSwiftInheritance(
|
|
155
|
+
node: TreeSitterNode,
|
|
156
|
+
className: string,
|
|
157
|
+
ctx: ExtractorOutput,
|
|
158
|
+
): void {
|
|
150
159
|
let first = true;
|
|
151
160
|
for (let i = 0; i < node.childCount; i++) {
|
|
152
161
|
const child = node.child(i);
|
|
153
162
|
if (!child || child.type !== 'inheritance_specifier') continue;
|
|
154
|
-
// inheritance_specifier > user_type > type_identifier
|
|
155
163
|
const userType = findChild(child, 'user_type');
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
ctx.classes.push({
|
|
168
|
-
name,
|
|
169
|
-
implements: typeId.text,
|
|
170
|
-
line: node.startPosition.row + 1,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
164
|
+
const typeId = userType ? findChild(userType, 'type_identifier') : null;
|
|
165
|
+
if (!typeId) continue;
|
|
166
|
+
if (first) {
|
|
167
|
+
ctx.classes.push({ name: className, extends: typeId.text, line: node.startPosition.row + 1 });
|
|
168
|
+
first = false;
|
|
169
|
+
} else {
|
|
170
|
+
ctx.classes.push({
|
|
171
|
+
name: className,
|
|
172
|
+
implements: typeId.text,
|
|
173
|
+
line: node.startPosition.row + 1,
|
|
174
|
+
});
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
}
|