@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,386 @@
1
+ // code-mapper/src/core/ingestion/type-extractors/jvm.ts
2
+ /** @file jvm.ts
3
+ * @description Type extraction for Java and Kotlin */
4
+ import { extractSimpleTypeName, extractVarName, findChildByType } from './shared.js';
5
+ const JAVA_DECLARATION_NODE_TYPES = new Set([
6
+ 'local_variable_declaration',
7
+ 'field_declaration',
8
+ ]);
9
+ // Java: Type x = ...; Type x;
10
+ const extractJavaDeclaration = (node, env) => {
11
+ const typeNode = node.childForFieldName('type');
12
+ if (!typeNode)
13
+ return;
14
+ const typeName = extractSimpleTypeName(typeNode);
15
+ if (!typeName || typeName === 'var')
16
+ return; // skip Java 10 var -- handled by extractInitializer
17
+ // Find variable_declarator children
18
+ for (let i = 0; i < node.namedChildCount; i++) {
19
+ const child = node.namedChild(i);
20
+ if (child?.type !== 'variable_declarator')
21
+ continue;
22
+ const nameNode = child.childForFieldName('name');
23
+ if (nameNode) {
24
+ const varName = extractVarName(nameNode);
25
+ if (varName)
26
+ env.set(varName, typeName);
27
+ }
28
+ }
29
+ };
30
+ // Java 10+: var x = new User() -- infer type from object_creation_expression
31
+ const extractJavaInitializer = (node, env, _classNames) => {
32
+ for (let i = 0; i < node.namedChildCount; i++) {
33
+ const child = node.namedChild(i);
34
+ if (child?.type !== 'variable_declarator')
35
+ continue;
36
+ const nameNode = child.childForFieldName('name');
37
+ const valueNode = child.childForFieldName('value');
38
+ if (!nameNode || !valueNode)
39
+ continue;
40
+ // Skip declarators that already have a binding from extractDeclaration
41
+ const varName = extractVarName(nameNode);
42
+ if (!varName || env.has(varName))
43
+ continue;
44
+ if (valueNode.type !== 'object_creation_expression')
45
+ continue;
46
+ const ctorType = valueNode.childForFieldName('type');
47
+ if (!ctorType)
48
+ continue;
49
+ const typeName = extractSimpleTypeName(ctorType);
50
+ if (typeName)
51
+ env.set(varName, typeName);
52
+ }
53
+ };
54
+ // Java: formal_parameter -> type name
55
+ const extractJavaParameter = (node, env) => {
56
+ let nameNode = null;
57
+ let typeNode = null;
58
+ if (node.type === 'formal_parameter') {
59
+ typeNode = node.childForFieldName('type');
60
+ nameNode = node.childForFieldName('name');
61
+ }
62
+ else {
63
+ // Generic fallback
64
+ nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
65
+ typeNode = node.childForFieldName('type');
66
+ }
67
+ if (!nameNode || !typeNode)
68
+ return;
69
+ const varName = extractVarName(nameNode);
70
+ const typeName = extractSimpleTypeName(typeNode);
71
+ if (varName && typeName)
72
+ env.set(varName, typeName);
73
+ };
74
+ // Java: var x = SomeFactory.create() -- constructor binding for `var` with method_invocation
75
+ const scanJavaConstructorBinding = (node) => {
76
+ if (node.type !== 'local_variable_declaration')
77
+ return undefined;
78
+ const typeNode = node.childForFieldName('type');
79
+ if (!typeNode)
80
+ return undefined;
81
+ if (typeNode.text !== 'var')
82
+ return undefined;
83
+ const declarator = findChildByType(node, 'variable_declarator');
84
+ if (!declarator)
85
+ return undefined;
86
+ const nameNode = declarator.childForFieldName('name');
87
+ const value = declarator.childForFieldName('value');
88
+ if (!nameNode || !value)
89
+ return undefined;
90
+ if (value.type === 'object_creation_expression')
91
+ return undefined;
92
+ if (value.type !== 'method_invocation')
93
+ return undefined;
94
+ const methodName = value.childForFieldName('name');
95
+ if (!methodName)
96
+ return undefined;
97
+ return { varName: nameNode.text, calleeName: methodName.text };
98
+ };
99
+ const JAVA_FOR_LOOP_NODE_TYPES = new Set([
100
+ 'enhanced_for_statement',
101
+ ]);
102
+ // Java: for (User user : users) -- extract loop variable binding
103
+ const extractJavaForLoopBinding = (node, scopeEnv) => {
104
+ const typeNode = node.childForFieldName('type');
105
+ const nameNode = node.childForFieldName('name');
106
+ if (!typeNode || !nameNode)
107
+ return;
108
+ const typeName = extractSimpleTypeName(typeNode);
109
+ const varName = extractVarName(nameNode);
110
+ if (typeName && varName)
111
+ scopeEnv.set(varName, typeName);
112
+ };
113
+ // Java: var alias = u -> local_variable_declaration > variable_declarator with name/value
114
+ const extractJavaPendingAssignment = (node, scopeEnv) => {
115
+ for (let i = 0; i < node.namedChildCount; i++) {
116
+ const child = node.namedChild(i);
117
+ if (!child || child.type !== 'variable_declarator')
118
+ continue;
119
+ const nameNode = child.childForFieldName('name');
120
+ const valueNode = child.childForFieldName('value');
121
+ if (!nameNode || !valueNode)
122
+ continue;
123
+ const lhs = nameNode.text;
124
+ if (scopeEnv.has(lhs))
125
+ continue;
126
+ if (valueNode.type === 'identifier' || valueNode.type === 'simple_identifier')
127
+ return { lhs, rhs: valueNode.text };
128
+ }
129
+ return undefined;
130
+ };
131
+ // Java 16+ `instanceof` pattern variable: `x instanceof User user`
132
+ // AST: instanceof_expression { left, instanceof, right: type, name: identifier (Java 16+) }
133
+ // Conservative: returns undefined when name field is absent (plain instanceof) or
134
+ // type cannot be extracted. Source variable's type is NOT used -- the pattern
135
+ // explicitly declares the new type, so no scopeEnv lookup is needed
136
+ const extractJavaPatternBinding = (node) => {
137
+ if (node.type !== 'instanceof_expression')
138
+ return undefined;
139
+ const nameNode = node.childForFieldName('name');
140
+ if (!nameNode)
141
+ return undefined;
142
+ const typeNode = node.childForFieldName('right');
143
+ if (!typeNode)
144
+ return undefined;
145
+ const typeName = extractSimpleTypeName(typeNode);
146
+ const varName = extractVarName(nameNode);
147
+ if (!typeName || !varName)
148
+ return undefined;
149
+ return { varName, typeName };
150
+ };
151
+ export const javaTypeConfig = {
152
+ declarationNodeTypes: JAVA_DECLARATION_NODE_TYPES,
153
+ extractDeclaration: extractJavaDeclaration,
154
+ extractParameter: extractJavaParameter,
155
+ extractInitializer: extractJavaInitializer,
156
+ scanConstructorBinding: scanJavaConstructorBinding,
157
+ forLoopNodeTypes: JAVA_FOR_LOOP_NODE_TYPES,
158
+ extractForLoopBinding: extractJavaForLoopBinding,
159
+ extractPendingAssignment: extractJavaPendingAssignment,
160
+ extractPatternBinding: extractJavaPatternBinding,
161
+ };
162
+ // Kotlin
163
+ const KOTLIN_DECLARATION_NODE_TYPES = new Set([
164
+ 'property_declaration',
165
+ 'variable_declaration',
166
+ ]);
167
+ // Kotlin: val x: Foo = ...
168
+ const extractKotlinDeclaration = (node, env) => {
169
+ if (node.type === 'property_declaration') {
170
+ // Kotlin property_declaration: name/type are inside a variable_declaration child
171
+ const varDecl = findChildByType(node, 'variable_declaration');
172
+ if (varDecl) {
173
+ const nameNode = findChildByType(varDecl, 'simple_identifier');
174
+ const typeNode = findChildByType(varDecl, 'user_type');
175
+ if (!nameNode || !typeNode)
176
+ return;
177
+ const varName = extractVarName(nameNode);
178
+ const typeName = extractSimpleTypeName(typeNode);
179
+ if (varName && typeName)
180
+ env.set(varName, typeName);
181
+ return;
182
+ }
183
+ // Fallback: try direct fields
184
+ const nameNode = node.childForFieldName('name')
185
+ ?? findChildByType(node, 'simple_identifier');
186
+ const typeNode = node.childForFieldName('type')
187
+ ?? findChildByType(node, 'user_type');
188
+ if (!nameNode || !typeNode)
189
+ return;
190
+ const varName = extractVarName(nameNode);
191
+ const typeName = extractSimpleTypeName(typeNode);
192
+ if (varName && typeName)
193
+ env.set(varName, typeName);
194
+ }
195
+ else if (node.type === 'variable_declaration') {
196
+ // variable_declaration directly inside functions
197
+ const nameNode = findChildByType(node, 'simple_identifier');
198
+ const typeNode = findChildByType(node, 'user_type');
199
+ if (nameNode && typeNode) {
200
+ const varName = extractVarName(nameNode);
201
+ const typeName = extractSimpleTypeName(typeNode);
202
+ if (varName && typeName)
203
+ env.set(varName, typeName);
204
+ }
205
+ }
206
+ };
207
+ // Kotlin: formal_parameter -> type name
208
+ const extractKotlinParameter = (node, env) => {
209
+ let nameNode = null;
210
+ let typeNode = null;
211
+ if (node.type === 'formal_parameter') {
212
+ typeNode = node.childForFieldName('type');
213
+ nameNode = node.childForFieldName('name');
214
+ }
215
+ else {
216
+ nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
217
+ typeNode = node.childForFieldName('type');
218
+ }
219
+ if (!nameNode || !typeNode)
220
+ return;
221
+ const varName = extractVarName(nameNode);
222
+ const typeName = extractSimpleTypeName(typeNode);
223
+ if (varName && typeName)
224
+ env.set(varName, typeName);
225
+ };
226
+ // Kotlin: val user = User() -- infer type from call_expression when callee is a known class
227
+ // Kotlin constructors are syntactically identical to function calls, so we verify
228
+ // against classNames (which may include cross-file SymbolTable lookups)
229
+ const extractKotlinInitializer = (node, env, classNames) => {
230
+ if (node.type !== 'property_declaration')
231
+ return;
232
+ // Skip if there's an explicit type annotation -- Tier 0 already handled it
233
+ const varDecl = findChildByType(node, 'variable_declaration');
234
+ if (varDecl && findChildByType(varDecl, 'user_type'))
235
+ return;
236
+ // Get the initializer value -- the call_expression after '='
237
+ const value = node.childForFieldName('value')
238
+ ?? findChildByType(node, 'call_expression');
239
+ if (!value || value.type !== 'call_expression')
240
+ return;
241
+ // The callee is the first child of call_expression (simple_identifier for direct calls)
242
+ const callee = value.firstNamedChild;
243
+ if (!callee || callee.type !== 'simple_identifier')
244
+ return;
245
+ const calleeName = callee.text;
246
+ if (!calleeName || !classNames.has(calleeName))
247
+ return;
248
+ // Extract the variable name from the variable_declaration inside property_declaration
249
+ const nameNode = varDecl
250
+ ? findChildByType(varDecl, 'simple_identifier')
251
+ : findChildByType(node, 'simple_identifier');
252
+ if (!nameNode)
253
+ return;
254
+ const varName = extractVarName(nameNode);
255
+ if (varName)
256
+ env.set(varName, calleeName);
257
+ };
258
+ // Kotlin: val x = User(...) -- constructor binding for property_declaration with call_expression
259
+ const scanKotlinConstructorBinding = (node) => {
260
+ if (node.type !== 'property_declaration')
261
+ return undefined;
262
+ const varDecl = findChildByType(node, 'variable_declaration');
263
+ if (!varDecl)
264
+ return undefined;
265
+ if (findChildByType(varDecl, 'user_type'))
266
+ return undefined;
267
+ const callExpr = findChildByType(node, 'call_expression');
268
+ if (!callExpr)
269
+ return undefined;
270
+ const callee = callExpr.firstNamedChild;
271
+ if (!callee)
272
+ return undefined;
273
+ let calleeName;
274
+ if (callee.type === 'simple_identifier') {
275
+ calleeName = callee.text;
276
+ }
277
+ else if (callee.type === 'navigation_expression') {
278
+ // Extract method name from qualified call: service.getUser() -> getUser
279
+ const suffix = callee.lastNamedChild;
280
+ if (suffix?.type === 'navigation_suffix') {
281
+ const methodName = suffix.lastNamedChild;
282
+ if (methodName?.type === 'simple_identifier') {
283
+ calleeName = methodName.text;
284
+ }
285
+ }
286
+ }
287
+ if (!calleeName)
288
+ return undefined;
289
+ const nameNode = findChildByType(varDecl, 'simple_identifier');
290
+ if (!nameNode)
291
+ return undefined;
292
+ return { varName: nameNode.text, calleeName };
293
+ };
294
+ const KOTLIN_FOR_LOOP_NODE_TYPES = new Set([
295
+ 'for_statement',
296
+ ]);
297
+ // Kotlin: for (user: User in users) -- extract loop variable binding with explicit type annotation
298
+ const extractKotlinForLoopBinding = (node, scopeEnv) => {
299
+ // Kotlin loop variable: variable_declaration child with optional user_type annotation
300
+ const varDecl = findChildByType(node, 'variable_declaration');
301
+ if (!varDecl)
302
+ return;
303
+ // Only extract when there is an explicit type annotation (user_type node)
304
+ const typeNode = findChildByType(varDecl, 'user_type');
305
+ if (!typeNode)
306
+ return;
307
+ const nameNode = findChildByType(varDecl, 'simple_identifier');
308
+ if (!nameNode)
309
+ return;
310
+ const typeName = extractSimpleTypeName(typeNode);
311
+ const varName = extractVarName(nameNode);
312
+ if (typeName && varName)
313
+ scopeEnv.set(varName, typeName);
314
+ };
315
+ // Kotlin: val alias = u -> property_declaration or variable_declaration
316
+ // property_declaration has: binding_pattern_kind("val"), variable_declaration("alias"),
317
+ // "=", and the RHS value (simple_identifier "u")
318
+ // variable_declaration appears directly inside functions and has simple_identifier children
319
+ const extractKotlinPendingAssignment = (node, scopeEnv) => {
320
+ if (node.type === 'property_declaration') {
321
+ // Find the variable name from variable_declaration child
322
+ const varDecl = findChildByType(node, 'variable_declaration');
323
+ if (!varDecl)
324
+ return undefined;
325
+ const nameNode = varDecl.firstNamedChild;
326
+ if (!nameNode || nameNode.type !== 'simple_identifier')
327
+ return undefined;
328
+ const lhs = nameNode.text;
329
+ if (scopeEnv.has(lhs))
330
+ return undefined;
331
+ // Find the RHS: a simple_identifier sibling after the "=" token
332
+ let foundEq = false;
333
+ for (let i = 0; i < node.childCount; i++) {
334
+ const child = node.child(i);
335
+ if (!child)
336
+ continue;
337
+ if (child.type === '=') {
338
+ foundEq = true;
339
+ continue;
340
+ }
341
+ if (foundEq && child.type === 'simple_identifier') {
342
+ return { lhs, rhs: child.text };
343
+ }
344
+ }
345
+ return undefined;
346
+ }
347
+ if (node.type === 'variable_declaration') {
348
+ // variable_declaration directly inside functions: simple_identifier children
349
+ const nameNode = findChildByType(node, 'simple_identifier');
350
+ if (!nameNode)
351
+ return undefined;
352
+ const lhs = nameNode.text;
353
+ if (scopeEnv.has(lhs))
354
+ return undefined;
355
+ // Look for RHS simple_identifier after "=" in the parent (property_declaration)
356
+ // variable_declaration itself doesn't contain "=" -- it's in the parent
357
+ const parent = node.parent;
358
+ if (!parent)
359
+ return undefined;
360
+ let foundEq = false;
361
+ for (let i = 0; i < parent.childCount; i++) {
362
+ const child = parent.child(i);
363
+ if (!child)
364
+ continue;
365
+ if (child.type === '=') {
366
+ foundEq = true;
367
+ continue;
368
+ }
369
+ if (foundEq && child.type === 'simple_identifier') {
370
+ return { lhs, rhs: child.text };
371
+ }
372
+ }
373
+ return undefined;
374
+ }
375
+ return undefined;
376
+ };
377
+ export const kotlinTypeConfig = {
378
+ declarationNodeTypes: KOTLIN_DECLARATION_NODE_TYPES,
379
+ forLoopNodeTypes: KOTLIN_FOR_LOOP_NODE_TYPES,
380
+ extractDeclaration: extractKotlinDeclaration,
381
+ extractParameter: extractKotlinParameter,
382
+ extractInitializer: extractKotlinInitializer,
383
+ scanConstructorBinding: scanKotlinConstructorBinding,
384
+ extractForLoopBinding: extractKotlinForLoopBinding,
385
+ extractPendingAssignment: extractKotlinPendingAssignment,
386
+ };
@@ -0,0 +1,4 @@
1
+ /** @file php.ts
2
+ * @description Type extraction for PHP (typed properties, PHPDoc annotations, constructor inference) */
3
+ import type { LanguageTypeConfig } from './types.js';
4
+ export declare const typeConfig: LanguageTypeConfig;
@@ -0,0 +1,280 @@
1
+ // code-mapper/src/core/ingestion/type-extractors/php.ts
2
+ /** @file php.ts
3
+ * @description Type extraction for PHP (typed properties, PHPDoc annotations, constructor inference) */
4
+ import { extractSimpleTypeName, extractVarName, extractCalleeName } from './shared.js';
5
+ const DECLARATION_NODE_TYPES = new Set([
6
+ 'assignment_expression', // For constructor inference: $x = new User()
7
+ 'property_declaration', // PHP 7.4+ typed properties: private UserRepo $repo;
8
+ 'method_declaration', // PHPDoc @param on class methods
9
+ 'function_definition', // PHPDoc @param on top-level functions
10
+ ]);
11
+ // Walk up the AST to find the enclosing class declaration
12
+ const findEnclosingClass = (node) => {
13
+ let current = node.parent;
14
+ while (current) {
15
+ if (current.type === 'class_declaration')
16
+ return current;
17
+ current = current.parent;
18
+ }
19
+ return null;
20
+ };
21
+ // Resolve PHP self/static/parent to the actual class name
22
+ // self/static -> enclosing class name, parent -> superclass from base_clause
23
+ const resolvePhpKeyword = (keyword, node) => {
24
+ if (keyword === 'self' || keyword === 'static') {
25
+ const cls = findEnclosingClass(node);
26
+ if (!cls)
27
+ return undefined;
28
+ const nameNode = cls.childForFieldName('name');
29
+ return nameNode?.text;
30
+ }
31
+ if (keyword === 'parent') {
32
+ const cls = findEnclosingClass(node);
33
+ if (!cls)
34
+ return undefined;
35
+ // base_clause contains the parent class name
36
+ for (let i = 0; i < cls.namedChildCount; i++) {
37
+ const child = cls.namedChild(i);
38
+ if (child?.type === 'base_clause') {
39
+ const parentName = child.firstNamedChild;
40
+ if (parentName)
41
+ return extractSimpleTypeName(parentName);
42
+ }
43
+ }
44
+ return undefined;
45
+ }
46
+ return undefined;
47
+ };
48
+ // Normalize a PHP type string to a simple class name identifier
49
+ const normalizePhpType = (raw) => {
50
+ // Strip nullable prefix: ?User -> User
51
+ let type = raw.startsWith('?') ? raw.slice(1) : raw;
52
+ // Strip array suffix: User[] -> User
53
+ type = type.replace(/\[\]$/, '');
54
+ // Strip union with null/false/void: User|null -> User
55
+ const parts = type.split('|').filter(p => p !== 'null' && p !== 'false' && p !== 'void' && p !== 'mixed');
56
+ if (parts.length !== 1)
57
+ return undefined;
58
+ type = parts[0];
59
+ // Strip namespace: \App\Models\User -> User
60
+ const segments = type.split('\\');
61
+ type = segments[segments.length - 1];
62
+ // Skip uninformative types
63
+ if (type === 'mixed' || type === 'void' || type === 'self' || type === 'static' || type === 'object')
64
+ return undefined;
65
+ if (/^\w+$/.test(type))
66
+ return type;
67
+ return undefined;
68
+ };
69
+ // Node types to skip when walking backwards to find doc-comments
70
+ // PHP 8+ attributes (#[Route(...)]) appear as named siblings between PHPDoc and method
71
+ const SKIP_NODE_TYPES = new Set(['attribute_list', 'attribute']);
72
+ // Regex to extract PHPDoc @param annotations: `@param Type $name` (standard order)
73
+ const PHPDOC_PARAM_RE = /@param\s+(\S+)\s+\$(\w+)/g;
74
+ // Alternate PHPDoc order: `@param $name Type` (name first)
75
+ const PHPDOC_PARAM_ALT_RE = /@param\s+\$(\w+)\s+(\S+)/g;
76
+ /**
77
+ * Collect PHPDoc @param type bindings from comment nodes preceding a method/function
78
+ * @returns Map of paramName -> typeName (without $ prefix)
79
+ */
80
+ const collectPhpDocParams = (methodNode) => {
81
+ const commentTexts = [];
82
+ let sibling = methodNode.previousSibling;
83
+ while (sibling) {
84
+ if (sibling.type === 'comment') {
85
+ commentTexts.unshift(sibling.text);
86
+ }
87
+ else if (sibling.isNamed && !SKIP_NODE_TYPES.has(sibling.type)) {
88
+ break;
89
+ }
90
+ sibling = sibling.previousSibling;
91
+ }
92
+ if (commentTexts.length === 0)
93
+ return new Map();
94
+ const params = new Map();
95
+ const commentBlock = commentTexts.join('\n');
96
+ PHPDOC_PARAM_RE.lastIndex = 0;
97
+ let match;
98
+ while ((match = PHPDOC_PARAM_RE.exec(commentBlock)) !== null) {
99
+ const typeName = normalizePhpType(match[1]);
100
+ const paramName = match[2]; // without $ prefix
101
+ if (typeName) {
102
+ // Store with $ prefix to match how PHP variables appear in the env
103
+ params.set('$' + paramName, typeName);
104
+ }
105
+ }
106
+ // Also check alternate PHPDoc order: @param $name Type
107
+ PHPDOC_PARAM_ALT_RE.lastIndex = 0;
108
+ while ((match = PHPDOC_PARAM_ALT_RE.exec(commentBlock)) !== null) {
109
+ const paramName = match[1];
110
+ if (params.has('$' + paramName))
111
+ continue; // standard format takes priority
112
+ const typeName = normalizePhpType(match[2]);
113
+ if (typeName) {
114
+ params.set('$' + paramName, typeName);
115
+ }
116
+ }
117
+ return params;
118
+ };
119
+ // PHP: typed class properties (PHP 7.4+): private UserRepo $repo;
120
+ // Also: PHPDoc @param annotations on method/function definitions
121
+ const extractDeclaration = (node, env) => {
122
+ // PHPDoc @param on methods/functions -- pre-populate env with param types
123
+ if (node.type === 'method_declaration' || node.type === 'function_definition') {
124
+ const phpDocParams = collectPhpDocParams(node);
125
+ for (const [paramName, typeName] of phpDocParams) {
126
+ if (!env.has(paramName))
127
+ env.set(paramName, typeName);
128
+ }
129
+ return;
130
+ }
131
+ if (node.type !== 'property_declaration')
132
+ return;
133
+ const typeNode = node.childForFieldName('type');
134
+ if (!typeNode)
135
+ return;
136
+ const typeName = extractSimpleTypeName(typeNode);
137
+ if (!typeName)
138
+ return;
139
+ // The variable name is inside property_element > variable_name
140
+ for (let i = 0; i < node.namedChildCount; i++) {
141
+ const child = node.namedChild(i);
142
+ if (child?.type === 'property_element') {
143
+ const varNameNode = child.firstNamedChild; // variable_name
144
+ if (varNameNode) {
145
+ const varName = extractVarName(varNameNode);
146
+ if (varName)
147
+ env.set(varName, typeName);
148
+ }
149
+ break;
150
+ }
151
+ }
152
+ };
153
+ // PHP: $x = new User() -- infer type from object_creation_expression
154
+ const extractInitializer = (node, env, _classNames) => {
155
+ if (node.type !== 'assignment_expression')
156
+ return;
157
+ const left = node.childForFieldName('left');
158
+ const right = node.childForFieldName('right');
159
+ if (!left || !right)
160
+ return;
161
+ if (right.type !== 'object_creation_expression')
162
+ return;
163
+ // The class name is the first named child of object_creation_expression
164
+ // (tree-sitter-php uses 'name' or 'qualified_name' nodes here)
165
+ const ctorType = right.firstNamedChild;
166
+ if (!ctorType)
167
+ return;
168
+ const typeName = extractSimpleTypeName(ctorType);
169
+ if (!typeName)
170
+ return;
171
+ // Resolve PHP self/static/parent to actual class names
172
+ const resolvedType = (typeName === 'self' || typeName === 'static' || typeName === 'parent')
173
+ ? resolvePhpKeyword(typeName, node)
174
+ : typeName;
175
+ if (!resolvedType)
176
+ return;
177
+ const varName = extractVarName(left);
178
+ if (varName)
179
+ env.set(varName, resolvedType);
180
+ };
181
+ // PHP: simple_parameter -> type $name
182
+ const extractParameter = (node, env) => {
183
+ let nameNode = null;
184
+ let typeNode = null;
185
+ if (node.type === 'simple_parameter') {
186
+ typeNode = node.childForFieldName('type');
187
+ nameNode = node.childForFieldName('name');
188
+ }
189
+ else {
190
+ nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
191
+ typeNode = node.childForFieldName('type');
192
+ }
193
+ if (!nameNode || !typeNode)
194
+ return;
195
+ const varName = extractVarName(nameNode);
196
+ const typeName = extractSimpleTypeName(typeNode);
197
+ if (varName && typeName)
198
+ env.set(varName, typeName);
199
+ };
200
+ // PHP: $x = SomeFactory() or $x = $this->getUser() -- bind variable to call return type
201
+ const scanConstructorBinding = (node) => {
202
+ if (node.type !== 'assignment_expression')
203
+ return undefined;
204
+ const left = node.childForFieldName('left');
205
+ const right = node.childForFieldName('right');
206
+ if (!left || !right)
207
+ return undefined;
208
+ if (left.type !== 'variable_name')
209
+ return undefined;
210
+ // Skip object_creation_expression (new User()) -- handled by extractInitializer
211
+ if (right.type === 'object_creation_expression')
212
+ return undefined;
213
+ // Handle both standalone function calls and method calls ($this->getUser())
214
+ if (right.type === 'function_call_expression') {
215
+ const calleeName = extractCalleeName(right);
216
+ if (!calleeName)
217
+ return undefined;
218
+ return { varName: left.text, calleeName };
219
+ }
220
+ if (right.type === 'member_call_expression') {
221
+ const methodName = right.childForFieldName('name');
222
+ if (!methodName)
223
+ return undefined;
224
+ // When receiver is $this/self/static, qualify with enclosing class for disambiguation
225
+ const receiver = right.childForFieldName('object');
226
+ const receiverText = receiver?.text;
227
+ let receiverClassName;
228
+ if (receiverText === '$this' || receiverText === 'self' || receiverText === 'static') {
229
+ const cls = findEnclosingClass(node);
230
+ const clsName = cls?.childForFieldName('name');
231
+ if (clsName)
232
+ receiverClassName = clsName.text;
233
+ }
234
+ return { varName: left.text, calleeName: methodName.text, receiverClassName };
235
+ }
236
+ return undefined;
237
+ };
238
+ // Regex to extract PHPDoc @return annotations: `@return User`
239
+ const PHPDOC_RETURN_RE = /@return\s+(\S+)/;
240
+ // Extract return type from PHPDoc `@return Type` annotation preceding a method
241
+ const extractReturnType = (node) => {
242
+ let sibling = node.previousSibling;
243
+ while (sibling) {
244
+ if (sibling.type === 'comment') {
245
+ const match = PHPDOC_RETURN_RE.exec(sibling.text);
246
+ if (match)
247
+ return normalizePhpType(match[1]);
248
+ }
249
+ else if (sibling.isNamed && !SKIP_NODE_TYPES.has(sibling.type))
250
+ break;
251
+ sibling = sibling.previousSibling;
252
+ }
253
+ return undefined;
254
+ };
255
+ // PHP: $alias = $user -> assignment_expression with variable_name left/right
256
+ // PHP TypeEnv stores variables WITH $ prefix ($user -> User), so we keep $ in lhs/rhs
257
+ const extractPendingAssignment = (node, scopeEnv) => {
258
+ if (node.type !== 'assignment_expression')
259
+ return undefined;
260
+ const left = node.childForFieldName('left');
261
+ const right = node.childForFieldName('right');
262
+ if (!left || !right)
263
+ return undefined;
264
+ if (left.type !== 'variable_name' || right.type !== 'variable_name')
265
+ return undefined;
266
+ const lhs = left.text;
267
+ const rhs = right.text;
268
+ if (!lhs || !rhs || scopeEnv.has(lhs))
269
+ return undefined;
270
+ return { lhs, rhs };
271
+ };
272
+ export const typeConfig = {
273
+ declarationNodeTypes: DECLARATION_NODE_TYPES,
274
+ extractDeclaration,
275
+ extractParameter,
276
+ extractInitializer,
277
+ scanConstructorBinding,
278
+ extractReturnType,
279
+ extractPendingAssignment,
280
+ };
@@ -0,0 +1,4 @@
1
+ /** @file python.ts
2
+ * @description Type extraction for Python (PEP 484/526 annotations and constructor inference) */
3
+ import type { LanguageTypeConfig } from './types.js';
4
+ export declare const typeConfig: LanguageTypeConfig;