@zuvia-software-solutions/code-mapper 1.4.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 +215 -0
- package/dist/cli/ai-context.d.ts +19 -0
- package/dist/cli/ai-context.js +168 -0
- package/dist/cli/analyze.d.ts +7 -0
- package/dist/cli/analyze.js +325 -0
- package/dist/cli/augment.d.ts +7 -0
- package/dist/cli/augment.js +27 -0
- package/dist/cli/clean.d.ts +5 -0
- package/dist/cli/clean.js +56 -0
- package/dist/cli/eval-server.d.ts +25 -0
- package/dist/cli/eval-server.js +365 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.js +102 -0
- package/dist/cli/lazy-action.d.ts +6 -0
- package/dist/cli/lazy-action.js +19 -0
- package/dist/cli/list.d.ts +2 -0
- package/dist/cli/list.js +27 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +35 -0
- package/dist/cli/refresh.d.ts +12 -0
- package/dist/cli/refresh.js +165 -0
- package/dist/cli/serve.d.ts +5 -0
- package/dist/cli/serve.js +8 -0
- package/dist/cli/setup.d.ts +6 -0
- package/dist/cli/setup.js +218 -0
- package/dist/cli/status.d.ts +2 -0
- package/dist/cli/status.js +33 -0
- package/dist/cli/tool.d.ts +28 -0
- package/dist/cli/tool.js +87 -0
- package/dist/config/ignore-service.d.ts +32 -0
- package/dist/config/ignore-service.js +282 -0
- package/dist/config/supported-languages.d.ts +23 -0
- package/dist/config/supported-languages.js +52 -0
- package/dist/core/augmentation/engine.d.ts +22 -0
- package/dist/core/augmentation/engine.js +232 -0
- package/dist/core/embeddings/embedder.d.ts +35 -0
- package/dist/core/embeddings/embedder.js +171 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +41 -0
- package/dist/core/embeddings/embedding-pipeline.js +402 -0
- package/dist/core/embeddings/index.d.ts +5 -0
- package/dist/core/embeddings/index.js +6 -0
- package/dist/core/embeddings/text-generator.d.ts +20 -0
- package/dist/core/embeddings/text-generator.js +159 -0
- package/dist/core/embeddings/types.d.ts +60 -0
- package/dist/core/embeddings/types.js +23 -0
- package/dist/core/graph/graph.d.ts +4 -0
- package/dist/core/graph/graph.js +65 -0
- package/dist/core/graph/types.d.ts +69 -0
- package/dist/core/graph/types.js +3 -0
- package/dist/core/incremental/child-process.d.ts +8 -0
- package/dist/core/incremental/child-process.js +649 -0
- package/dist/core/incremental/refresh-coordinator.d.ts +32 -0
- package/dist/core/incremental/refresh-coordinator.js +147 -0
- package/dist/core/incremental/types.d.ts +78 -0
- package/dist/core/incremental/types.js +153 -0
- package/dist/core/incremental/watcher.d.ts +63 -0
- package/dist/core/incremental/watcher.js +338 -0
- package/dist/core/ingestion/ast-cache.d.ts +12 -0
- package/dist/core/ingestion/ast-cache.js +34 -0
- package/dist/core/ingestion/call-processor.d.ts +34 -0
- package/dist/core/ingestion/call-processor.js +937 -0
- package/dist/core/ingestion/call-routing.d.ts +40 -0
- package/dist/core/ingestion/call-routing.js +97 -0
- package/dist/core/ingestion/cluster-enricher.d.ts +30 -0
- package/dist/core/ingestion/cluster-enricher.js +151 -0
- package/dist/core/ingestion/community-processor.d.ts +26 -0
- package/dist/core/ingestion/community-processor.js +272 -0
- package/dist/core/ingestion/constants.d.ts +5 -0
- package/dist/core/ingestion/constants.js +8 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +23 -0
- package/dist/core/ingestion/entry-point-scoring.js +317 -0
- package/dist/core/ingestion/export-detection.d.ts +11 -0
- package/dist/core/ingestion/export-detection.js +203 -0
- package/dist/core/ingestion/filesystem-walker.d.ts +18 -0
- package/dist/core/ingestion/filesystem-walker.js +64 -0
- package/dist/core/ingestion/framework-detection.d.ts +42 -0
- package/dist/core/ingestion/framework-detection.js +405 -0
- package/dist/core/ingestion/heritage-processor.d.ts +15 -0
- package/dist/core/ingestion/heritage-processor.js +237 -0
- package/dist/core/ingestion/import-processor.d.ts +31 -0
- package/dist/core/ingestion/import-processor.js +416 -0
- package/dist/core/ingestion/language-config.d.ts +32 -0
- package/dist/core/ingestion/language-config.js +161 -0
- package/dist/core/ingestion/mro-processor.d.ts +32 -0
- package/dist/core/ingestion/mro-processor.js +343 -0
- package/dist/core/ingestion/named-binding-extraction.d.ts +51 -0
- package/dist/core/ingestion/named-binding-extraction.js +343 -0
- package/dist/core/ingestion/parsing-processor.d.ts +20 -0
- package/dist/core/ingestion/parsing-processor.js +282 -0
- package/dist/core/ingestion/pipeline.d.ts +3 -0
- package/dist/core/ingestion/pipeline.js +416 -0
- package/dist/core/ingestion/process-processor.d.ts +42 -0
- package/dist/core/ingestion/process-processor.js +357 -0
- package/dist/core/ingestion/resolution-context.d.ts +40 -0
- package/dist/core/ingestion/resolution-context.js +171 -0
- package/dist/core/ingestion/resolvers/csharp.d.ts +10 -0
- package/dist/core/ingestion/resolvers/csharp.js +101 -0
- package/dist/core/ingestion/resolvers/go.d.ts +8 -0
- package/dist/core/ingestion/resolvers/go.js +33 -0
- package/dist/core/ingestion/resolvers/index.d.ts +14 -0
- package/dist/core/ingestion/resolvers/index.js +10 -0
- package/dist/core/ingestion/resolvers/jvm.d.ts +9 -0
- package/dist/core/ingestion/resolvers/jvm.js +74 -0
- package/dist/core/ingestion/resolvers/php.d.ts +7 -0
- package/dist/core/ingestion/resolvers/php.js +30 -0
- package/dist/core/ingestion/resolvers/ruby.d.ts +9 -0
- package/dist/core/ingestion/resolvers/ruby.js +13 -0
- package/dist/core/ingestion/resolvers/rust.d.ts +5 -0
- package/dist/core/ingestion/resolvers/rust.js +62 -0
- package/dist/core/ingestion/resolvers/standard.d.ts +16 -0
- package/dist/core/ingestion/resolvers/standard.js +144 -0
- package/dist/core/ingestion/resolvers/utils.d.ts +18 -0
- package/dist/core/ingestion/resolvers/utils.js +113 -0
- package/dist/core/ingestion/structure-processor.d.ts +4 -0
- package/dist/core/ingestion/structure-processor.js +39 -0
- package/dist/core/ingestion/symbol-table.d.ts +34 -0
- package/dist/core/ingestion/symbol-table.js +48 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +20 -0
- package/dist/core/ingestion/tree-sitter-queries.js +691 -0
- package/dist/core/ingestion/type-env.d.ts +52 -0
- package/dist/core/ingestion/type-env.js +349 -0
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +214 -0
- package/dist/core/ingestion/type-extractors/csharp.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/csharp.js +224 -0
- package/dist/core/ingestion/type-extractors/go.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/go.js +261 -0
- package/dist/core/ingestion/type-extractors/index.d.ts +20 -0
- package/dist/core/ingestion/type-extractors/index.js +30 -0
- package/dist/core/ingestion/type-extractors/jvm.d.ts +5 -0
- package/dist/core/ingestion/type-extractors/jvm.js +386 -0
- package/dist/core/ingestion/type-extractors/php.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/php.js +280 -0
- package/dist/core/ingestion/type-extractors/python.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/python.js +175 -0
- package/dist/core/ingestion/type-extractors/ruby.d.ts +12 -0
- package/dist/core/ingestion/type-extractors/ruby.js +218 -0
- package/dist/core/ingestion/type-extractors/rust.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/rust.js +290 -0
- package/dist/core/ingestion/type-extractors/shared.d.ts +81 -0
- package/dist/core/ingestion/type-extractors/shared.js +322 -0
- package/dist/core/ingestion/type-extractors/swift.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/swift.js +140 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +111 -0
- package/dist/core/ingestion/type-extractors/types.js +4 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +4 -0
- package/dist/core/ingestion/type-extractors/typescript.js +227 -0
- package/dist/core/ingestion/utils.d.ts +73 -0
- package/dist/core/ingestion/utils.js +992 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +99 -0
- package/dist/core/ingestion/workers/parse-worker.js +1055 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
- package/dist/core/ingestion/workers/worker-pool.js +123 -0
- package/dist/core/lbug/csv-generator.d.ts +28 -0
- package/dist/core/lbug/csv-generator.js +355 -0
- package/dist/core/lbug/lbug-adapter.d.ts +96 -0
- package/dist/core/lbug/lbug-adapter.js +753 -0
- package/dist/core/lbug/schema.d.ts +46 -0
- package/dist/core/lbug/schema.js +402 -0
- package/dist/core/search/bm25-index.d.ts +20 -0
- package/dist/core/search/bm25-index.js +123 -0
- package/dist/core/search/hybrid-search.d.ts +32 -0
- package/dist/core/search/hybrid-search.js +131 -0
- package/dist/core/search/query-cache.d.ts +18 -0
- package/dist/core/search/query-cache.js +47 -0
- package/dist/core/search/query-expansion.d.ts +19 -0
- package/dist/core/search/query-expansion.js +75 -0
- package/dist/core/search/reranker.d.ts +29 -0
- package/dist/core/search/reranker.js +122 -0
- package/dist/core/search/types.d.ts +154 -0
- package/dist/core/search/types.js +51 -0
- package/dist/core/semantic/tsgo-service.d.ts +67 -0
- package/dist/core/semantic/tsgo-service.js +355 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +12 -0
- package/dist/core/tree-sitter/parser-loader.js +71 -0
- package/dist/lib/memory-guard.d.ts +35 -0
- package/dist/lib/memory-guard.js +70 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.js +6 -0
- package/dist/mcp/compatible-stdio-transport.d.ts +32 -0
- package/dist/mcp/compatible-stdio-transport.js +209 -0
- package/dist/mcp/core/embedder.d.ts +24 -0
- package/dist/mcp/core/embedder.js +168 -0
- package/dist/mcp/core/lbug-adapter.d.ts +29 -0
- package/dist/mcp/core/lbug-adapter.js +330 -0
- package/dist/mcp/local/local-backend.d.ts +188 -0
- package/dist/mcp/local/local-backend.js +2759 -0
- package/dist/mcp/resources.d.ts +22 -0
- package/dist/mcp/resources.js +379 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.js +217 -0
- package/dist/mcp/staleness.d.ts +10 -0
- package/dist/mcp/staleness.js +25 -0
- package/dist/mcp/tools.d.ts +21 -0
- package/dist/mcp/tools.js +202 -0
- package/dist/server/api.d.ts +5 -0
- package/dist/server/api.js +340 -0
- package/dist/server/mcp-http.d.ts +7 -0
- package/dist/server/mcp-http.js +95 -0
- package/dist/storage/git.d.ts +6 -0
- package/dist/storage/git.js +35 -0
- package/dist/storage/repo-manager.d.ts +87 -0
- package/dist/storage/repo-manager.js +249 -0
- package/dist/types/pipeline.d.ts +35 -0
- package/dist/types/pipeline.js +20 -0
- package/hooks/claude/code-mapper-hook.cjs +238 -0
- package/hooks/claude/pre-tool-use.sh +79 -0
- package/hooks/claude/session-start.sh +42 -0
- package/models/mlx-embedder.py +185 -0
- package/package.json +100 -0
- package/scripts/patch-tree-sitter-swift.cjs +74 -0
- package/vendor/leiden/index.cjs +355 -0
- package/vendor/leiden/utils.cjs +392 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// code-mapper/src/core/ingestion/type-extractors/rust.ts
|
|
2
|
+
/** @file rust.ts
|
|
3
|
+
* @description Type extraction for Rust (let bindings, pattern matching, struct literals) */
|
|
4
|
+
import { extractSimpleTypeName, extractVarName, hasTypeAnnotation, unwrapAwait, extractGenericTypeArgs } from './shared.js';
|
|
5
|
+
const DECLARATION_NODE_TYPES = new Set([
|
|
6
|
+
'let_declaration',
|
|
7
|
+
'let_condition',
|
|
8
|
+
]);
|
|
9
|
+
// Walk up the AST to find the enclosing impl block and extract the implementing type name
|
|
10
|
+
const findEnclosingImplType = (node) => {
|
|
11
|
+
let current = node.parent;
|
|
12
|
+
while (current) {
|
|
13
|
+
if (current.type === 'impl_item') {
|
|
14
|
+
// The 'type' field holds the implementing type (e.g., `impl User { ... }`)
|
|
15
|
+
const typeNode = current.childForFieldName('type');
|
|
16
|
+
if (typeNode)
|
|
17
|
+
return extractSimpleTypeName(typeNode);
|
|
18
|
+
}
|
|
19
|
+
current = current.parent;
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
};
|
|
23
|
+
// Extract the type name from a struct_pattern's 'type' field
|
|
24
|
+
// Handles both simple `User { .. }` and scoped `Message::Data { .. }`
|
|
25
|
+
const extractStructPatternType = (structPattern) => {
|
|
26
|
+
const typeNode = structPattern.childForFieldName('type');
|
|
27
|
+
if (!typeNode)
|
|
28
|
+
return undefined;
|
|
29
|
+
return extractSimpleTypeName(typeNode);
|
|
30
|
+
};
|
|
31
|
+
// Recursively scan a pattern tree for captured_pattern nodes (x @ StructType { .. })
|
|
32
|
+
// and extract variable -> type bindings from them
|
|
33
|
+
const extractCapturedPatternBindings = (pattern, env) => {
|
|
34
|
+
if (pattern.type === 'captured_pattern') {
|
|
35
|
+
// captured_pattern: identifier @ inner_pattern
|
|
36
|
+
// The first named child is the identifier, followed by the inner pattern
|
|
37
|
+
const nameNode = pattern.firstNamedChild;
|
|
38
|
+
if (!nameNode || nameNode.type !== 'identifier')
|
|
39
|
+
return;
|
|
40
|
+
// Find the struct_pattern child -- that gives us the type
|
|
41
|
+
for (let i = 0; i < pattern.namedChildCount; i++) {
|
|
42
|
+
const child = pattern.namedChild(i);
|
|
43
|
+
if (child?.type === 'struct_pattern') {
|
|
44
|
+
const typeName = extractStructPatternType(child);
|
|
45
|
+
if (typeName)
|
|
46
|
+
env.set(nameNode.text, typeName);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Recurse into tuple_struct_pattern children to find nested captured_patterns
|
|
53
|
+
// e.g., Some(user @ User { .. })
|
|
54
|
+
if (pattern.type === 'tuple_struct_pattern') {
|
|
55
|
+
for (let i = 0; i < pattern.namedChildCount; i++) {
|
|
56
|
+
const child = pattern.namedChild(i);
|
|
57
|
+
if (child)
|
|
58
|
+
extractCapturedPatternBindings(child, env);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
// Rust: let x: Foo = ... | if let / while let pattern bindings
|
|
63
|
+
const extractDeclaration = (node, env) => {
|
|
64
|
+
if (node.type === 'let_condition') {
|
|
65
|
+
// if let / while let: extract type bindings from pattern matching
|
|
66
|
+
//
|
|
67
|
+
// Supported patterns:
|
|
68
|
+
// - captured_pattern: `if let user @ User { .. } = expr` -> user: User
|
|
69
|
+
// - tuple_struct_pattern with nested captured_pattern:
|
|
70
|
+
// `if let Some(user @ User { .. }) = expr` -> user: User
|
|
71
|
+
//
|
|
72
|
+
// NOT supported (requires generic unwrapping):
|
|
73
|
+
// - `if let Some(x) = opt` where opt: Option<T> -> x: T
|
|
74
|
+
//
|
|
75
|
+
// struct_pattern without capture (`if let User { name } = expr`)
|
|
76
|
+
// destructures fields -- individual field types are unknown without
|
|
77
|
+
// field-type resolution, so no bindings are extracted
|
|
78
|
+
const pattern = node.childForFieldName('pattern');
|
|
79
|
+
if (!pattern)
|
|
80
|
+
return;
|
|
81
|
+
extractCapturedPatternBindings(pattern, env);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Standard let_declaration: let x: Foo = ...
|
|
85
|
+
const pattern = node.childForFieldName('pattern');
|
|
86
|
+
const typeNode = node.childForFieldName('type');
|
|
87
|
+
if (!pattern || !typeNode)
|
|
88
|
+
return;
|
|
89
|
+
const varName = extractVarName(pattern);
|
|
90
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
91
|
+
if (varName && typeName)
|
|
92
|
+
env.set(varName, typeName);
|
|
93
|
+
};
|
|
94
|
+
// Rust: let x = User::new(), let x = User::default(), or let x = User { ... }
|
|
95
|
+
const extractInitializer = (node, env, _classNames) => {
|
|
96
|
+
// Skip if there's an explicit type annotation -- Tier 0 already handled it
|
|
97
|
+
if (node.childForFieldName('type') !== null)
|
|
98
|
+
return;
|
|
99
|
+
const pattern = node.childForFieldName('pattern');
|
|
100
|
+
const value = node.childForFieldName('value');
|
|
101
|
+
if (!pattern || !value)
|
|
102
|
+
return;
|
|
103
|
+
// Rust struct literal: let user = User { name: "alice", age: 30 }
|
|
104
|
+
// tree-sitter-rust: struct_expression with 'name' field holding the type
|
|
105
|
+
if (value.type === 'struct_expression') {
|
|
106
|
+
const typeNode = value.childForFieldName('name');
|
|
107
|
+
if (!typeNode)
|
|
108
|
+
return;
|
|
109
|
+
const rawType = extractSimpleTypeName(typeNode);
|
|
110
|
+
if (!rawType)
|
|
111
|
+
return;
|
|
112
|
+
// Resolve Self to the actual struct/enum name from the enclosing impl block
|
|
113
|
+
const typeName = rawType === 'Self' ? findEnclosingImplType(node) : rawType;
|
|
114
|
+
const varName = extractVarName(pattern);
|
|
115
|
+
if (varName && typeName)
|
|
116
|
+
env.set(varName, typeName);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (value.type !== 'call_expression')
|
|
120
|
+
return;
|
|
121
|
+
const func = value.childForFieldName('function');
|
|
122
|
+
if (!func || func.type !== 'scoped_identifier')
|
|
123
|
+
return;
|
|
124
|
+
const nameField = func.childForFieldName('name');
|
|
125
|
+
// Only match ::new() and ::default() -- the two idiomatic Rust constructors
|
|
126
|
+
// Deliberately excludes ::from(), ::with_capacity(), etc. to avoid false positives
|
|
127
|
+
// (e.g. String::from("x") is not necessarily the "String" type we want for method resolution)
|
|
128
|
+
if (!nameField || (nameField.text !== 'new' && nameField.text !== 'default'))
|
|
129
|
+
return;
|
|
130
|
+
const pathField = func.childForFieldName('path');
|
|
131
|
+
if (!pathField)
|
|
132
|
+
return;
|
|
133
|
+
const rawType = extractSimpleTypeName(pathField);
|
|
134
|
+
if (!rawType)
|
|
135
|
+
return;
|
|
136
|
+
// Resolve Self to the actual struct/enum name from the enclosing impl block
|
|
137
|
+
const typeName = rawType === 'Self' ? findEnclosingImplType(node) : rawType;
|
|
138
|
+
const varName = extractVarName(pattern);
|
|
139
|
+
if (varName && typeName)
|
|
140
|
+
env.set(varName, typeName);
|
|
141
|
+
};
|
|
142
|
+
// Rust: parameter -> pattern: type
|
|
143
|
+
const extractParameter = (node, env) => {
|
|
144
|
+
let nameNode = null;
|
|
145
|
+
let typeNode = null;
|
|
146
|
+
if (node.type === 'parameter') {
|
|
147
|
+
nameNode = node.childForFieldName('pattern');
|
|
148
|
+
typeNode = node.childForFieldName('type');
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
152
|
+
typeNode = node.childForFieldName('type');
|
|
153
|
+
}
|
|
154
|
+
if (!nameNode || !typeNode)
|
|
155
|
+
return;
|
|
156
|
+
const varName = extractVarName(nameNode);
|
|
157
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
158
|
+
if (varName && typeName)
|
|
159
|
+
env.set(varName, typeName);
|
|
160
|
+
};
|
|
161
|
+
// Rust: let user = get_user("alice") -- let_declaration with call_expression value, no type annotation
|
|
162
|
+
// Skips annotated declarations (handled by extractDeclaration) and ::new()/ ::default()
|
|
163
|
+
// (handled by extractInitializer). Unwraps mut_pattern for inner identifier
|
|
164
|
+
const scanConstructorBinding = (node) => {
|
|
165
|
+
if (node.type !== 'let_declaration')
|
|
166
|
+
return undefined;
|
|
167
|
+
if (hasTypeAnnotation(node))
|
|
168
|
+
return undefined;
|
|
169
|
+
let patternNode = node.childForFieldName('pattern');
|
|
170
|
+
if (!patternNode)
|
|
171
|
+
return undefined;
|
|
172
|
+
if (patternNode.type === 'mut_pattern') {
|
|
173
|
+
patternNode = patternNode.firstNamedChild;
|
|
174
|
+
if (!patternNode)
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
if (patternNode.type !== 'identifier')
|
|
178
|
+
return undefined;
|
|
179
|
+
// Unwrap `.await`: `let user = get_user().await` -> await_expression wraps call_expression
|
|
180
|
+
const value = unwrapAwait(node.childForFieldName('value'));
|
|
181
|
+
if (!value || value.type !== 'call_expression')
|
|
182
|
+
return undefined;
|
|
183
|
+
const func = value.childForFieldName('function');
|
|
184
|
+
if (!func)
|
|
185
|
+
return undefined;
|
|
186
|
+
if (func.type === 'scoped_identifier') {
|
|
187
|
+
const methodName = func.lastNamedChild;
|
|
188
|
+
if (methodName?.text === 'new' || methodName?.text === 'default')
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
const calleeName = extractSimpleTypeName(func);
|
|
192
|
+
if (!calleeName)
|
|
193
|
+
return undefined;
|
|
194
|
+
return { varName: patternNode.text, calleeName };
|
|
195
|
+
};
|
|
196
|
+
// Rust: let alias = u; -> let_declaration with pattern + value fields
|
|
197
|
+
const extractPendingAssignment = (node, scopeEnv) => {
|
|
198
|
+
if (node.type !== 'let_declaration')
|
|
199
|
+
return undefined;
|
|
200
|
+
const pattern = node.childForFieldName('pattern');
|
|
201
|
+
const value = node.childForFieldName('value');
|
|
202
|
+
if (!pattern || !value)
|
|
203
|
+
return undefined;
|
|
204
|
+
const lhs = extractVarName(pattern);
|
|
205
|
+
if (!lhs || scopeEnv.has(lhs))
|
|
206
|
+
return undefined;
|
|
207
|
+
if (value.type === 'identifier')
|
|
208
|
+
return { lhs, rhs: value.text };
|
|
209
|
+
return undefined;
|
|
210
|
+
};
|
|
211
|
+
// Rust pattern binding extractor for `if let` / `while let` constructs that unwrap
|
|
212
|
+
// enum variants and introduce new typed variables
|
|
213
|
+
//
|
|
214
|
+
// Supported patterns:
|
|
215
|
+
// - `if let Some(x) = opt` -> x: T (opt: Option<T>, T via NULLABLE_WRAPPER_TYPES)
|
|
216
|
+
// - `if let Ok(x) = res` -> x: T (res: Result<T, E>, T from declarationTypeNodes)
|
|
217
|
+
//
|
|
218
|
+
// Complements captured_pattern support in extractDeclaration (which handles
|
|
219
|
+
// `if let x @ Struct { .. } = expr` but NOT tuple struct unwrapping)
|
|
220
|
+
//
|
|
221
|
+
// Conservative: returns undefined when source variable's type is unknown, wrapper is
|
|
222
|
+
// not a known single-unwrap variant, or value is not a simple identifier
|
|
223
|
+
const extractPatternBinding = (node, scopeEnv, declarationTypeNodes, scope) => {
|
|
224
|
+
if (node.type !== 'let_condition')
|
|
225
|
+
return undefined;
|
|
226
|
+
const patternNode = node.childForFieldName('pattern');
|
|
227
|
+
const valueNode = node.childForFieldName('value');
|
|
228
|
+
if (!patternNode || !valueNode)
|
|
229
|
+
return undefined;
|
|
230
|
+
// Only handle tuple_struct_pattern: Some(x) or Ok(x)
|
|
231
|
+
if (patternNode.type !== 'tuple_struct_pattern')
|
|
232
|
+
return undefined;
|
|
233
|
+
// Extract the wrapper type name: Some | Ok
|
|
234
|
+
const wrapperTypeNode = patternNode.childForFieldName('type');
|
|
235
|
+
if (!wrapperTypeNode)
|
|
236
|
+
return undefined;
|
|
237
|
+
const wrapperName = extractSimpleTypeName(wrapperTypeNode);
|
|
238
|
+
if (wrapperName !== 'Some' && wrapperName !== 'Ok' && wrapperName !== 'Err')
|
|
239
|
+
return undefined;
|
|
240
|
+
// Extract the inner variable name from the single child of the tuple_struct_pattern
|
|
241
|
+
// `Some(x)` -> the first named child after the type field is the identifier
|
|
242
|
+
// tree-sitter-rust: tuple_struct_pattern has 'type' field + unnamed children for args
|
|
243
|
+
let innerVar;
|
|
244
|
+
for (let i = 0; i < patternNode.namedChildCount; i++) {
|
|
245
|
+
const child = patternNode.namedChild(i);
|
|
246
|
+
if (!child)
|
|
247
|
+
continue;
|
|
248
|
+
// Skip the type node itself
|
|
249
|
+
if (child === wrapperTypeNode)
|
|
250
|
+
continue;
|
|
251
|
+
if (child.type === 'identifier') {
|
|
252
|
+
innerVar = child.text;
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!innerVar)
|
|
257
|
+
return undefined;
|
|
258
|
+
// The value must be a simple identifier so we can look it up in scopeEnv
|
|
259
|
+
const sourceVarName = valueNode.type === 'identifier' ? valueNode.text : undefined;
|
|
260
|
+
if (!sourceVarName)
|
|
261
|
+
return undefined;
|
|
262
|
+
// For `Some(x)`: Option<T> is already unwrapped to T in scopeEnv (via NULLABLE_WRAPPER_TYPES)
|
|
263
|
+
// For `Ok(x)`: Result<T, E> stores "Result" in scopeEnv -- must use declarationTypeNodes
|
|
264
|
+
if (wrapperName === 'Some') {
|
|
265
|
+
const innerType = scopeEnv.get(sourceVarName);
|
|
266
|
+
if (!innerType)
|
|
267
|
+
return undefined;
|
|
268
|
+
return { varName: innerVar, typeName: innerType };
|
|
269
|
+
}
|
|
270
|
+
// wrapperName === 'Ok' or 'Err': look up the Result<T, E> type AST node
|
|
271
|
+
// Ok(x) -> extract T (typeArgs[0]), Err(e) -> extract E (typeArgs[1])
|
|
272
|
+
const typeNodeKey = `${scope}\0${sourceVarName}`;
|
|
273
|
+
const typeAstNode = declarationTypeNodes.get(typeNodeKey);
|
|
274
|
+
if (!typeAstNode)
|
|
275
|
+
return undefined;
|
|
276
|
+
const typeArgs = extractGenericTypeArgs(typeAstNode);
|
|
277
|
+
const argIndex = wrapperName === 'Err' ? 1 : 0;
|
|
278
|
+
if (typeArgs.length < argIndex + 1)
|
|
279
|
+
return undefined;
|
|
280
|
+
return { varName: innerVar, typeName: typeArgs[argIndex] };
|
|
281
|
+
};
|
|
282
|
+
export const typeConfig = {
|
|
283
|
+
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
284
|
+
extractDeclaration,
|
|
285
|
+
extractInitializer,
|
|
286
|
+
extractParameter,
|
|
287
|
+
scanConstructorBinding,
|
|
288
|
+
extractPendingAssignment,
|
|
289
|
+
extractPatternBinding,
|
|
290
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** @file shared.ts
|
|
2
|
+
* @description Shared utilities for type extraction across all languages */
|
|
3
|
+
import type { SyntaxNode } from '../utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Extract the simple type name from a type AST node
|
|
6
|
+
*
|
|
7
|
+
* Handles generic types (List<User> -> List), qualified names (models.User -> User),
|
|
8
|
+
* and nullable types (User? -> User). Returns undefined for complex types
|
|
9
|
+
*/
|
|
10
|
+
export declare const extractSimpleTypeName: (typeNode: SyntaxNode) => string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Extract variable name from a declarator or pattern node
|
|
13
|
+
*
|
|
14
|
+
* Returns the simple identifier text, or undefined for destructuring/complex patterns
|
|
15
|
+
*/
|
|
16
|
+
export declare const extractVarName: (node: SyntaxNode) => string | undefined;
|
|
17
|
+
/** Node types for function/method parameters with type annotations */
|
|
18
|
+
export declare const TYPED_PARAMETER_TYPES: Set<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Extract type arguments from a generic type node
|
|
21
|
+
*
|
|
22
|
+
* e.g. List<User, String> -> ['User', 'String'], Vec<User> -> ['User']
|
|
23
|
+
* Used by extractSimpleTypeName to unwrap nullable wrappers (Optional<User> -> User)
|
|
24
|
+
*
|
|
25
|
+
* Handles language-specific AST structures:
|
|
26
|
+
* - TS/Java/Rust/Go: generic_type > type_arguments > type nodes
|
|
27
|
+
* - C#: generic_type > type_argument_list > type nodes
|
|
28
|
+
* - Kotlin: generic_type > type_arguments > type_projection > type nodes
|
|
29
|
+
*
|
|
30
|
+
* Note: Go slices/maps use slice_type/map_type, not generic_type -- those are
|
|
31
|
+
* NOT handled here; use language-specific extractors for Go container types
|
|
32
|
+
*
|
|
33
|
+
* @param typeNode A generic_type or parameterized_type AST node (returns [] for non-generic types)
|
|
34
|
+
* @returns Array of resolved type argument names (unresolvable arguments are omitted)
|
|
35
|
+
*/
|
|
36
|
+
export declare const extractGenericTypeArgs: (typeNode: SyntaxNode) => string[];
|
|
37
|
+
/**
|
|
38
|
+
* Match Ruby constructor assignment: `user = User.new` or `service = Models::User.new`
|
|
39
|
+
*
|
|
40
|
+
* Handles both simple constants and scope_resolution (namespaced) receivers
|
|
41
|
+
* @returns `{ varName, calleeName }` or undefined if not a Ruby constructor assignment
|
|
42
|
+
*/
|
|
43
|
+
export declare const extractRubyConstructorAssignment: (node: SyntaxNode) => {
|
|
44
|
+
varName: string;
|
|
45
|
+
calleeName: string;
|
|
46
|
+
} | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Check if an AST node has an explicit type annotation
|
|
49
|
+
*
|
|
50
|
+
* Checks both named fields ('type') and child nodes ('type_annotation')
|
|
51
|
+
* Used by constructor binding scanners to skip annotated declarations
|
|
52
|
+
*/
|
|
53
|
+
export declare const hasTypeAnnotation: (node: SyntaxNode) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Strip nullable wrappers from a type name string
|
|
56
|
+
*
|
|
57
|
+
* Used by both lookupInEnv (TypeEnv annotations) and extractReturnTypeName
|
|
58
|
+
* (return-type text) to normalize types before receiver lookup
|
|
59
|
+
*
|
|
60
|
+
* "User | null" -> "User"
|
|
61
|
+
* "User | undefined" -> "User"
|
|
62
|
+
* "User | null | undefined" -> "User"
|
|
63
|
+
* "User?" -> "User"
|
|
64
|
+
* "User | Repo" -> undefined (genuine union -- refuse)
|
|
65
|
+
* "null" -> undefined
|
|
66
|
+
*/
|
|
67
|
+
export declare const stripNullable: (typeName: string) => string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Unwrap an await_expression to get the inner value
|
|
70
|
+
*
|
|
71
|
+
* Returns the node itself if not an await_expression, or null if input is null
|
|
72
|
+
*/
|
|
73
|
+
export declare const unwrapAwait: (node: SyntaxNode | null) => SyntaxNode | null;
|
|
74
|
+
/**
|
|
75
|
+
* Extract the callee name from a call_expression node
|
|
76
|
+
*
|
|
77
|
+
* Navigates to the 'function' field (or first named child) and extracts a simple type name
|
|
78
|
+
*/
|
|
79
|
+
export declare const extractCalleeName: (callNode: SyntaxNode) => string | undefined;
|
|
80
|
+
/** Find the first named child with the given node type */
|
|
81
|
+
export declare const findChildByType: (node: SyntaxNode, type: string) => SyntaxNode | null;
|