@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.
Files changed (213) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/ai-context.d.ts +19 -0
  3. package/dist/cli/ai-context.js +168 -0
  4. package/dist/cli/analyze.d.ts +7 -0
  5. package/dist/cli/analyze.js +325 -0
  6. package/dist/cli/augment.d.ts +7 -0
  7. package/dist/cli/augment.js +27 -0
  8. package/dist/cli/clean.d.ts +5 -0
  9. package/dist/cli/clean.js +56 -0
  10. package/dist/cli/eval-server.d.ts +25 -0
  11. package/dist/cli/eval-server.js +365 -0
  12. package/dist/cli/index.d.ts +6 -0
  13. package/dist/cli/index.js +102 -0
  14. package/dist/cli/lazy-action.d.ts +6 -0
  15. package/dist/cli/lazy-action.js +19 -0
  16. package/dist/cli/list.d.ts +2 -0
  17. package/dist/cli/list.js +27 -0
  18. package/dist/cli/mcp.d.ts +8 -0
  19. package/dist/cli/mcp.js +35 -0
  20. package/dist/cli/refresh.d.ts +12 -0
  21. package/dist/cli/refresh.js +165 -0
  22. package/dist/cli/serve.d.ts +5 -0
  23. package/dist/cli/serve.js +8 -0
  24. package/dist/cli/setup.d.ts +6 -0
  25. package/dist/cli/setup.js +218 -0
  26. package/dist/cli/status.d.ts +2 -0
  27. package/dist/cli/status.js +33 -0
  28. package/dist/cli/tool.d.ts +28 -0
  29. package/dist/cli/tool.js +87 -0
  30. package/dist/config/ignore-service.d.ts +32 -0
  31. package/dist/config/ignore-service.js +282 -0
  32. package/dist/config/supported-languages.d.ts +23 -0
  33. package/dist/config/supported-languages.js +52 -0
  34. package/dist/core/augmentation/engine.d.ts +22 -0
  35. package/dist/core/augmentation/engine.js +232 -0
  36. package/dist/core/embeddings/embedder.d.ts +35 -0
  37. package/dist/core/embeddings/embedder.js +171 -0
  38. package/dist/core/embeddings/embedding-pipeline.d.ts +41 -0
  39. package/dist/core/embeddings/embedding-pipeline.js +402 -0
  40. package/dist/core/embeddings/index.d.ts +5 -0
  41. package/dist/core/embeddings/index.js +6 -0
  42. package/dist/core/embeddings/text-generator.d.ts +20 -0
  43. package/dist/core/embeddings/text-generator.js +159 -0
  44. package/dist/core/embeddings/types.d.ts +60 -0
  45. package/dist/core/embeddings/types.js +23 -0
  46. package/dist/core/graph/graph.d.ts +4 -0
  47. package/dist/core/graph/graph.js +65 -0
  48. package/dist/core/graph/types.d.ts +69 -0
  49. package/dist/core/graph/types.js +3 -0
  50. package/dist/core/incremental/child-process.d.ts +8 -0
  51. package/dist/core/incremental/child-process.js +649 -0
  52. package/dist/core/incremental/refresh-coordinator.d.ts +32 -0
  53. package/dist/core/incremental/refresh-coordinator.js +147 -0
  54. package/dist/core/incremental/types.d.ts +78 -0
  55. package/dist/core/incremental/types.js +153 -0
  56. package/dist/core/incremental/watcher.d.ts +63 -0
  57. package/dist/core/incremental/watcher.js +338 -0
  58. package/dist/core/ingestion/ast-cache.d.ts +12 -0
  59. package/dist/core/ingestion/ast-cache.js +34 -0
  60. package/dist/core/ingestion/call-processor.d.ts +34 -0
  61. package/dist/core/ingestion/call-processor.js +937 -0
  62. package/dist/core/ingestion/call-routing.d.ts +40 -0
  63. package/dist/core/ingestion/call-routing.js +97 -0
  64. package/dist/core/ingestion/cluster-enricher.d.ts +30 -0
  65. package/dist/core/ingestion/cluster-enricher.js +151 -0
  66. package/dist/core/ingestion/community-processor.d.ts +26 -0
  67. package/dist/core/ingestion/community-processor.js +272 -0
  68. package/dist/core/ingestion/constants.d.ts +5 -0
  69. package/dist/core/ingestion/constants.js +8 -0
  70. package/dist/core/ingestion/entry-point-scoring.d.ts +23 -0
  71. package/dist/core/ingestion/entry-point-scoring.js +317 -0
  72. package/dist/core/ingestion/export-detection.d.ts +11 -0
  73. package/dist/core/ingestion/export-detection.js +203 -0
  74. package/dist/core/ingestion/filesystem-walker.d.ts +18 -0
  75. package/dist/core/ingestion/filesystem-walker.js +64 -0
  76. package/dist/core/ingestion/framework-detection.d.ts +42 -0
  77. package/dist/core/ingestion/framework-detection.js +405 -0
  78. package/dist/core/ingestion/heritage-processor.d.ts +15 -0
  79. package/dist/core/ingestion/heritage-processor.js +237 -0
  80. package/dist/core/ingestion/import-processor.d.ts +31 -0
  81. package/dist/core/ingestion/import-processor.js +416 -0
  82. package/dist/core/ingestion/language-config.d.ts +32 -0
  83. package/dist/core/ingestion/language-config.js +161 -0
  84. package/dist/core/ingestion/mro-processor.d.ts +32 -0
  85. package/dist/core/ingestion/mro-processor.js +343 -0
  86. package/dist/core/ingestion/named-binding-extraction.d.ts +51 -0
  87. package/dist/core/ingestion/named-binding-extraction.js +343 -0
  88. package/dist/core/ingestion/parsing-processor.d.ts +20 -0
  89. package/dist/core/ingestion/parsing-processor.js +282 -0
  90. package/dist/core/ingestion/pipeline.d.ts +3 -0
  91. package/dist/core/ingestion/pipeline.js +416 -0
  92. package/dist/core/ingestion/process-processor.d.ts +42 -0
  93. package/dist/core/ingestion/process-processor.js +357 -0
  94. package/dist/core/ingestion/resolution-context.d.ts +40 -0
  95. package/dist/core/ingestion/resolution-context.js +171 -0
  96. package/dist/core/ingestion/resolvers/csharp.d.ts +10 -0
  97. package/dist/core/ingestion/resolvers/csharp.js +101 -0
  98. package/dist/core/ingestion/resolvers/go.d.ts +8 -0
  99. package/dist/core/ingestion/resolvers/go.js +33 -0
  100. package/dist/core/ingestion/resolvers/index.d.ts +14 -0
  101. package/dist/core/ingestion/resolvers/index.js +10 -0
  102. package/dist/core/ingestion/resolvers/jvm.d.ts +9 -0
  103. package/dist/core/ingestion/resolvers/jvm.js +74 -0
  104. package/dist/core/ingestion/resolvers/php.d.ts +7 -0
  105. package/dist/core/ingestion/resolvers/php.js +30 -0
  106. package/dist/core/ingestion/resolvers/ruby.d.ts +9 -0
  107. package/dist/core/ingestion/resolvers/ruby.js +13 -0
  108. package/dist/core/ingestion/resolvers/rust.d.ts +5 -0
  109. package/dist/core/ingestion/resolvers/rust.js +62 -0
  110. package/dist/core/ingestion/resolvers/standard.d.ts +16 -0
  111. package/dist/core/ingestion/resolvers/standard.js +144 -0
  112. package/dist/core/ingestion/resolvers/utils.d.ts +18 -0
  113. package/dist/core/ingestion/resolvers/utils.js +113 -0
  114. package/dist/core/ingestion/structure-processor.d.ts +4 -0
  115. package/dist/core/ingestion/structure-processor.js +39 -0
  116. package/dist/core/ingestion/symbol-table.d.ts +34 -0
  117. package/dist/core/ingestion/symbol-table.js +48 -0
  118. package/dist/core/ingestion/tree-sitter-queries.d.ts +20 -0
  119. package/dist/core/ingestion/tree-sitter-queries.js +691 -0
  120. package/dist/core/ingestion/type-env.d.ts +52 -0
  121. package/dist/core/ingestion/type-env.js +349 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +4 -0
  123. package/dist/core/ingestion/type-extractors/c-cpp.js +214 -0
  124. package/dist/core/ingestion/type-extractors/csharp.d.ts +4 -0
  125. package/dist/core/ingestion/type-extractors/csharp.js +224 -0
  126. package/dist/core/ingestion/type-extractors/go.d.ts +4 -0
  127. package/dist/core/ingestion/type-extractors/go.js +261 -0
  128. package/dist/core/ingestion/type-extractors/index.d.ts +20 -0
  129. package/dist/core/ingestion/type-extractors/index.js +30 -0
  130. package/dist/core/ingestion/type-extractors/jvm.d.ts +5 -0
  131. package/dist/core/ingestion/type-extractors/jvm.js +386 -0
  132. package/dist/core/ingestion/type-extractors/php.d.ts +4 -0
  133. package/dist/core/ingestion/type-extractors/php.js +280 -0
  134. package/dist/core/ingestion/type-extractors/python.d.ts +4 -0
  135. package/dist/core/ingestion/type-extractors/python.js +175 -0
  136. package/dist/core/ingestion/type-extractors/ruby.d.ts +12 -0
  137. package/dist/core/ingestion/type-extractors/ruby.js +218 -0
  138. package/dist/core/ingestion/type-extractors/rust.d.ts +4 -0
  139. package/dist/core/ingestion/type-extractors/rust.js +290 -0
  140. package/dist/core/ingestion/type-extractors/shared.d.ts +81 -0
  141. package/dist/core/ingestion/type-extractors/shared.js +322 -0
  142. package/dist/core/ingestion/type-extractors/swift.d.ts +4 -0
  143. package/dist/core/ingestion/type-extractors/swift.js +140 -0
  144. package/dist/core/ingestion/type-extractors/types.d.ts +111 -0
  145. package/dist/core/ingestion/type-extractors/types.js +4 -0
  146. package/dist/core/ingestion/type-extractors/typescript.d.ts +4 -0
  147. package/dist/core/ingestion/type-extractors/typescript.js +227 -0
  148. package/dist/core/ingestion/utils.d.ts +73 -0
  149. package/dist/core/ingestion/utils.js +992 -0
  150. package/dist/core/ingestion/workers/parse-worker.d.ts +99 -0
  151. package/dist/core/ingestion/workers/parse-worker.js +1055 -0
  152. package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
  153. package/dist/core/ingestion/workers/worker-pool.js +123 -0
  154. package/dist/core/lbug/csv-generator.d.ts +28 -0
  155. package/dist/core/lbug/csv-generator.js +355 -0
  156. package/dist/core/lbug/lbug-adapter.d.ts +96 -0
  157. package/dist/core/lbug/lbug-adapter.js +753 -0
  158. package/dist/core/lbug/schema.d.ts +46 -0
  159. package/dist/core/lbug/schema.js +402 -0
  160. package/dist/core/search/bm25-index.d.ts +20 -0
  161. package/dist/core/search/bm25-index.js +123 -0
  162. package/dist/core/search/hybrid-search.d.ts +32 -0
  163. package/dist/core/search/hybrid-search.js +131 -0
  164. package/dist/core/search/query-cache.d.ts +18 -0
  165. package/dist/core/search/query-cache.js +47 -0
  166. package/dist/core/search/query-expansion.d.ts +19 -0
  167. package/dist/core/search/query-expansion.js +75 -0
  168. package/dist/core/search/reranker.d.ts +29 -0
  169. package/dist/core/search/reranker.js +122 -0
  170. package/dist/core/search/types.d.ts +154 -0
  171. package/dist/core/search/types.js +51 -0
  172. package/dist/core/semantic/tsgo-service.d.ts +67 -0
  173. package/dist/core/semantic/tsgo-service.js +355 -0
  174. package/dist/core/tree-sitter/parser-loader.d.ts +12 -0
  175. package/dist/core/tree-sitter/parser-loader.js +71 -0
  176. package/dist/lib/memory-guard.d.ts +35 -0
  177. package/dist/lib/memory-guard.js +70 -0
  178. package/dist/lib/utils.d.ts +3 -0
  179. package/dist/lib/utils.js +6 -0
  180. package/dist/mcp/compatible-stdio-transport.d.ts +32 -0
  181. package/dist/mcp/compatible-stdio-transport.js +209 -0
  182. package/dist/mcp/core/embedder.d.ts +24 -0
  183. package/dist/mcp/core/embedder.js +168 -0
  184. package/dist/mcp/core/lbug-adapter.d.ts +29 -0
  185. package/dist/mcp/core/lbug-adapter.js +330 -0
  186. package/dist/mcp/local/local-backend.d.ts +188 -0
  187. package/dist/mcp/local/local-backend.js +2759 -0
  188. package/dist/mcp/resources.d.ts +22 -0
  189. package/dist/mcp/resources.js +379 -0
  190. package/dist/mcp/server.d.ts +10 -0
  191. package/dist/mcp/server.js +217 -0
  192. package/dist/mcp/staleness.d.ts +10 -0
  193. package/dist/mcp/staleness.js +25 -0
  194. package/dist/mcp/tools.d.ts +21 -0
  195. package/dist/mcp/tools.js +202 -0
  196. package/dist/server/api.d.ts +5 -0
  197. package/dist/server/api.js +340 -0
  198. package/dist/server/mcp-http.d.ts +7 -0
  199. package/dist/server/mcp-http.js +95 -0
  200. package/dist/storage/git.d.ts +6 -0
  201. package/dist/storage/git.js +35 -0
  202. package/dist/storage/repo-manager.d.ts +87 -0
  203. package/dist/storage/repo-manager.js +249 -0
  204. package/dist/types/pipeline.d.ts +35 -0
  205. package/dist/types/pipeline.js +20 -0
  206. package/hooks/claude/code-mapper-hook.cjs +238 -0
  207. package/hooks/claude/pre-tool-use.sh +79 -0
  208. package/hooks/claude/session-start.sh +42 -0
  209. package/models/mlx-embedder.py +185 -0
  210. package/package.json +100 -0
  211. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  212. package/vendor/leiden/index.cjs +355 -0
  213. 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;