gitnexus 1.4.7 → 1.4.9

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 (242) hide show
  1. package/README.md +29 -1
  2. package/dist/cli/ai-context.d.ts +1 -1
  3. package/dist/cli/ai-context.js +1 -1
  4. package/dist/cli/analyze.d.ts +2 -0
  5. package/dist/cli/analyze.js +54 -21
  6. package/dist/cli/index-repo.d.ts +15 -0
  7. package/dist/cli/index-repo.js +115 -0
  8. package/dist/cli/index.js +13 -3
  9. package/dist/cli/setup.js +90 -10
  10. package/dist/cli/wiki.d.ts +4 -0
  11. package/dist/cli/wiki.js +174 -53
  12. package/dist/config/supported-languages.d.ts +33 -1
  13. package/dist/config/supported-languages.js +32 -0
  14. package/dist/core/embeddings/embedder.d.ts +6 -1
  15. package/dist/core/embeddings/embedder.js +65 -5
  16. package/dist/core/embeddings/embedding-pipeline.js +11 -9
  17. package/dist/core/embeddings/http-client.d.ts +31 -0
  18. package/dist/core/embeddings/http-client.js +179 -0
  19. package/dist/core/embeddings/index.d.ts +1 -0
  20. package/dist/core/embeddings/index.js +1 -0
  21. package/dist/core/embeddings/types.d.ts +1 -1
  22. package/dist/core/graph/graph.js +9 -1
  23. package/dist/core/graph/types.d.ts +11 -2
  24. package/dist/core/ingestion/call-processor.d.ts +66 -2
  25. package/dist/core/ingestion/call-processor.js +650 -30
  26. package/dist/core/ingestion/call-routing.d.ts +9 -18
  27. package/dist/core/ingestion/call-routing.js +0 -19
  28. package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
  29. package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
  30. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
  31. package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
  32. package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
  33. package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
  34. package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
  35. package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
  36. package/dist/core/ingestion/cobol-processor.d.ts +54 -0
  37. package/dist/core/ingestion/cobol-processor.js +1186 -0
  38. package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
  39. package/dist/core/ingestion/entry-point-scoring.js +52 -28
  40. package/dist/core/ingestion/export-detection.d.ts +47 -8
  41. package/dist/core/ingestion/export-detection.js +29 -50
  42. package/dist/core/ingestion/field-extractor.d.ts +29 -0
  43. package/dist/core/ingestion/field-extractor.js +25 -0
  44. package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
  45. package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
  46. package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
  47. package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
  48. package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
  49. package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
  50. package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
  51. package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
  52. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
  53. package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
  54. package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
  55. package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
  56. package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
  57. package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
  58. package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
  59. package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
  60. package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
  61. package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
  62. package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
  63. package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
  64. package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
  65. package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
  66. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
  67. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
  68. package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
  69. package/dist/core/ingestion/field-extractors/generic.js +111 -0
  70. package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
  71. package/dist/core/ingestion/field-extractors/typescript.js +291 -0
  72. package/dist/core/ingestion/field-types.d.ts +59 -0
  73. package/dist/core/ingestion/field-types.js +2 -0
  74. package/dist/core/ingestion/framework-detection.d.ts +97 -2
  75. package/dist/core/ingestion/framework-detection.js +114 -14
  76. package/dist/core/ingestion/heritage-processor.js +62 -66
  77. package/dist/core/ingestion/import-processor.d.ts +9 -10
  78. package/dist/core/ingestion/import-processor.js +150 -196
  79. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
  80. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
  81. package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
  82. package/dist/core/ingestion/import-resolvers/dart.js +44 -0
  83. package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
  84. package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
  85. package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +10 -1
  86. package/dist/core/ingestion/import-resolvers/jvm.js +159 -0
  87. package/dist/core/ingestion/import-resolvers/php.d.ts +25 -0
  88. package/dist/core/ingestion/import-resolvers/php.js +80 -0
  89. package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
  90. package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
  91. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
  92. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
  93. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
  94. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
  95. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
  96. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
  97. package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
  98. package/dist/core/ingestion/import-resolvers/swift.js +23 -0
  99. package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
  100. package/dist/core/ingestion/import-resolvers/types.js +6 -0
  101. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +2 -0
  102. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +7 -0
  103. package/dist/core/ingestion/language-config.d.ts +6 -0
  104. package/dist/core/ingestion/language-config.js +13 -0
  105. package/dist/core/ingestion/language-provider.d.ts +121 -0
  106. package/dist/core/ingestion/language-provider.js +24 -0
  107. package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
  108. package/dist/core/ingestion/languages/c-cpp.js +71 -0
  109. package/dist/core/ingestion/languages/cobol.d.ts +1 -0
  110. package/dist/core/ingestion/languages/cobol.js +26 -0
  111. package/dist/core/ingestion/languages/csharp.d.ts +8 -0
  112. package/dist/core/ingestion/languages/csharp.js +49 -0
  113. package/dist/core/ingestion/languages/dart.d.ts +12 -0
  114. package/dist/core/ingestion/languages/dart.js +58 -0
  115. package/dist/core/ingestion/languages/go.d.ts +11 -0
  116. package/dist/core/ingestion/languages/go.js +28 -0
  117. package/dist/core/ingestion/languages/index.d.ts +38 -0
  118. package/dist/core/ingestion/languages/index.js +63 -0
  119. package/dist/core/ingestion/languages/java.d.ts +9 -0
  120. package/dist/core/ingestion/languages/java.js +29 -0
  121. package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
  122. package/dist/core/ingestion/languages/kotlin.js +53 -0
  123. package/dist/core/ingestion/languages/php.d.ts +8 -0
  124. package/dist/core/ingestion/languages/php.js +145 -0
  125. package/dist/core/ingestion/languages/python.d.ts +12 -0
  126. package/dist/core/ingestion/languages/python.js +39 -0
  127. package/dist/core/ingestion/languages/ruby.d.ts +9 -0
  128. package/dist/core/ingestion/languages/ruby.js +44 -0
  129. package/dist/core/ingestion/languages/rust.d.ts +12 -0
  130. package/dist/core/ingestion/languages/rust.js +44 -0
  131. package/dist/core/ingestion/languages/swift.d.ts +12 -0
  132. package/dist/core/ingestion/languages/swift.js +133 -0
  133. package/dist/core/ingestion/languages/typescript.d.ts +10 -0
  134. package/dist/core/ingestion/languages/typescript.js +60 -0
  135. package/dist/core/ingestion/markdown-processor.d.ts +17 -0
  136. package/dist/core/ingestion/markdown-processor.js +124 -0
  137. package/dist/core/ingestion/mro-processor.js +22 -18
  138. package/dist/core/ingestion/named-binding-processor.d.ts +18 -0
  139. package/dist/core/ingestion/named-binding-processor.js +42 -0
  140. package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
  141. package/dist/core/ingestion/named-bindings/csharp.js +37 -0
  142. package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
  143. package/dist/core/ingestion/named-bindings/java.js +29 -0
  144. package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
  145. package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
  146. package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
  147. package/dist/core/ingestion/named-bindings/php.js +61 -0
  148. package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
  149. package/dist/core/ingestion/named-bindings/python.js +49 -0
  150. package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
  151. package/dist/core/ingestion/named-bindings/rust.js +64 -0
  152. package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
  153. package/dist/core/ingestion/named-bindings/types.js +6 -0
  154. package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
  155. package/dist/core/ingestion/named-bindings/typescript.js +58 -0
  156. package/dist/core/ingestion/parsing-processor.d.ts +6 -2
  157. package/dist/core/ingestion/parsing-processor.js +125 -85
  158. package/dist/core/ingestion/pipeline.d.ts +10 -0
  159. package/dist/core/ingestion/pipeline.js +1235 -317
  160. package/dist/core/ingestion/resolution-context.d.ts +5 -0
  161. package/dist/core/ingestion/resolution-context.js +8 -5
  162. package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
  163. package/dist/core/ingestion/route-extractors/expo.js +36 -0
  164. package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
  165. package/dist/core/ingestion/route-extractors/middleware.js +143 -0
  166. package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
  167. package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
  168. package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
  169. package/dist/core/ingestion/route-extractors/php.js +21 -0
  170. package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
  171. package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
  172. package/dist/core/ingestion/symbol-table.d.ts +16 -0
  173. package/dist/core/ingestion/symbol-table.js +20 -6
  174. package/dist/core/ingestion/tree-sitter-queries.d.ts +10 -9
  175. package/dist/core/ingestion/tree-sitter-queries.js +274 -11
  176. package/dist/core/ingestion/type-env.d.ts +42 -18
  177. package/dist/core/ingestion/type-env.js +481 -106
  178. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +5 -0
  179. package/dist/core/ingestion/type-extractors/c-cpp.js +119 -0
  180. package/dist/core/ingestion/type-extractors/csharp.js +149 -16
  181. package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
  182. package/dist/core/ingestion/type-extractors/dart.js +371 -0
  183. package/dist/core/ingestion/type-extractors/jvm.js +169 -66
  184. package/dist/core/ingestion/type-extractors/rust.js +35 -1
  185. package/dist/core/ingestion/type-extractors/shared.d.ts +1 -15
  186. package/dist/core/ingestion/type-extractors/shared.js +14 -112
  187. package/dist/core/ingestion/type-extractors/swift.js +338 -7
  188. package/dist/core/ingestion/type-extractors/types.d.ts +40 -8
  189. package/dist/core/ingestion/type-extractors/typescript.js +141 -9
  190. package/dist/core/ingestion/utils/ast-helpers.d.ts +83 -0
  191. package/dist/core/ingestion/utils/ast-helpers.js +817 -0
  192. package/dist/core/ingestion/utils/call-analysis.d.ts +73 -0
  193. package/dist/core/ingestion/utils/call-analysis.js +527 -0
  194. package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
  195. package/dist/core/ingestion/utils/event-loop.js +5 -0
  196. package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
  197. package/dist/core/ingestion/utils/language-detection.js +70 -0
  198. package/dist/core/ingestion/utils/verbose.d.ts +1 -0
  199. package/dist/core/ingestion/utils/verbose.js +7 -0
  200. package/dist/core/ingestion/workers/parse-worker.d.ts +55 -5
  201. package/dist/core/ingestion/workers/parse-worker.js +415 -225
  202. package/dist/core/lbug/csv-generator.js +51 -1
  203. package/dist/core/lbug/lbug-adapter.d.ts +10 -0
  204. package/dist/core/lbug/lbug-adapter.js +75 -4
  205. package/dist/core/lbug/schema.d.ts +8 -4
  206. package/dist/core/lbug/schema.js +65 -4
  207. package/dist/core/tree-sitter/parser-loader.js +7 -1
  208. package/dist/core/wiki/cursor-client.d.ts +31 -0
  209. package/dist/core/wiki/cursor-client.js +127 -0
  210. package/dist/core/wiki/generator.d.ts +28 -9
  211. package/dist/core/wiki/generator.js +115 -18
  212. package/dist/core/wiki/graph-queries.d.ts +4 -0
  213. package/dist/core/wiki/graph-queries.js +7 -1
  214. package/dist/core/wiki/llm-client.d.ts +2 -0
  215. package/dist/core/wiki/llm-client.js +8 -4
  216. package/dist/core/wiki/prompts.d.ts +3 -3
  217. package/dist/core/wiki/prompts.js +6 -0
  218. package/dist/mcp/core/embedder.js +11 -3
  219. package/dist/mcp/core/lbug-adapter.d.ts +5 -0
  220. package/dist/mcp/core/lbug-adapter.js +23 -2
  221. package/dist/mcp/local/local-backend.d.ts +38 -5
  222. package/dist/mcp/local/local-backend.js +804 -63
  223. package/dist/mcp/resources.js +2 -0
  224. package/dist/mcp/tools.js +73 -4
  225. package/dist/server/api.d.ts +19 -1
  226. package/dist/server/api.js +66 -6
  227. package/dist/storage/git.d.ts +12 -0
  228. package/dist/storage/git.js +21 -0
  229. package/dist/storage/repo-manager.d.ts +3 -0
  230. package/package.json +25 -16
  231. package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
  232. package/dist/core/ingestion/named-binding-extraction.js +0 -363
  233. package/dist/core/ingestion/resolvers/index.d.ts +0 -18
  234. package/dist/core/ingestion/resolvers/index.js +0 -13
  235. package/dist/core/ingestion/resolvers/jvm.js +0 -87
  236. package/dist/core/ingestion/resolvers/php.d.ts +0 -15
  237. package/dist/core/ingestion/resolvers/php.js +0 -35
  238. package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
  239. package/dist/core/ingestion/type-extractors/index.js +0 -31
  240. package/dist/core/ingestion/utils.d.ts +0 -138
  241. package/dist/core/ingestion/utils.js +0 -1290
  242. package/scripts/patch-tree-sitter-swift.cjs +0 -74
@@ -1,14 +1,35 @@
1
- import { extractSimpleTypeName, extractVarName, findChildByType, hasTypeAnnotation } from './shared.js';
1
+ import { findChild } from '../utils/ast-helpers.js';
2
+ import { extractSimpleTypeName, extractVarName, hasTypeAnnotation, extractElementTypeFromString, resolveIterableElementType } from './shared.js';
2
3
  const DECLARATION_NODE_TYPES = new Set([
3
4
  'property_declaration',
5
+ 'if_statement',
6
+ 'guard_statement',
4
7
  ]);
8
+ const FOR_LOOP_NODE_TYPES = new Set([
9
+ 'for_statement',
10
+ ]);
11
+ /**
12
+ * Unwrap Swift `await_expression` and `try_expression` nodes to find the inner
13
+ * call_expression or other value node. `try` nodes contain a `try_operator` child
14
+ * that must be skipped.
15
+ */
16
+ function unwrapSwiftExpression(node) {
17
+ if (node.type === 'await_expression' || node.type === 'try_expression') {
18
+ for (let i = 0; i < node.namedChildCount; i++) {
19
+ const child = node.namedChild(i);
20
+ if (child && child.type !== 'try_operator')
21
+ return unwrapSwiftExpression(child);
22
+ }
23
+ }
24
+ return node;
25
+ }
5
26
  /** Swift: let x: Foo = ... */
6
27
  const extractDeclaration = (node, env) => {
7
28
  // Swift property_declaration has pattern and type_annotation
8
29
  const pattern = node.childForFieldName('pattern')
9
- ?? findChildByType(node, 'pattern');
30
+ ?? findChild(node, 'pattern');
10
31
  const typeAnnotation = node.childForFieldName('type')
11
- ?? findChildByType(node, 'type_annotation');
32
+ ?? findChild(node, 'type_annotation');
12
33
  if (!pattern || !typeAnnotation)
13
34
  return;
14
35
  const varName = extractVarName(pattern) ?? pattern.text;
@@ -43,17 +64,30 @@ const extractInitializer = (node, env, classNames) => {
43
64
  if (node.type !== 'property_declaration')
44
65
  return;
45
66
  // Skip if has type annotation — extractDeclaration handled it
46
- if (node.childForFieldName('type') || findChildByType(node, 'type_annotation'))
67
+ if (node.childForFieldName('type') || findChild(node, 'type_annotation'))
47
68
  return;
48
69
  // Find pattern (variable name)
49
- const pattern = node.childForFieldName('pattern') ?? findChildByType(node, 'pattern');
70
+ const pattern = node.childForFieldName('pattern') ?? findChild(node, 'pattern');
50
71
  if (!pattern)
51
72
  return;
52
73
  const varName = extractVarName(pattern) ?? pattern.text;
53
74
  if (!varName || env.has(varName))
54
75
  return;
55
- // Find call_expression in the value
56
- const callExpr = findChildByType(node, 'call_expression');
76
+ // Find call_expression in the value (unwrap await/try)
77
+ let callExpr = findChild(node, 'call_expression');
78
+ if (!callExpr) {
79
+ // Check for await_expression or try_expression wrapping a call_expression
80
+ for (let i = 0; i < node.namedChildCount; i++) {
81
+ const child = node.namedChild(i);
82
+ if (child && (child.type === 'await_expression' || child.type === 'try_expression')) {
83
+ const unwrapped = unwrapSwiftExpression(child);
84
+ if (unwrapped.type === 'call_expression') {
85
+ callExpr = unwrapped;
86
+ break;
87
+ }
88
+ }
89
+ }
90
+ }
57
91
  if (!callExpr)
58
92
  return;
59
93
  const callee = callExpr.firstNamedChild;
@@ -98,6 +132,14 @@ const scanConstructorBinding = (node) => {
98
132
  callExpr = child;
99
133
  break;
100
134
  }
135
+ // Unwrap await/try to find inner call_expression
136
+ if (child && (child.type === 'await_expression' || child.type === 'try_expression')) {
137
+ const unwrapped = unwrapSwiftExpression(child);
138
+ if (unwrapped.type === 'call_expression') {
139
+ callExpr = unwrapped;
140
+ break;
141
+ }
142
+ }
101
143
  }
102
144
  if (!callExpr)
103
145
  return undefined;
@@ -128,10 +170,299 @@ const scanConstructorBinding = (node) => {
128
170
  }
129
171
  return undefined;
130
172
  };
173
+ /**
174
+ * Extract the variable name from an if_statement or guard_statement with optional binding.
175
+ * Pattern: `if let varName = expr` / `guard let varName = expr`
176
+ * AST: if_statement/guard_statement contains value_binding_pattern, then simple_identifier (varName),
177
+ * then call_expression/simple_identifier/navigation_expression (value).
178
+ */
179
+ function extractIfGuardBinding(node, scopeEnv) {
180
+ // Find value_binding_pattern to confirm this is an optional binding
181
+ let hasValueBinding = false;
182
+ let varName;
183
+ let valueNode = null;
184
+ for (let i = 0; i < node.namedChildCount; i++) {
185
+ const child = node.namedChild(i);
186
+ if (!child)
187
+ continue;
188
+ if (child.type === 'value_binding_pattern') {
189
+ hasValueBinding = true;
190
+ continue;
191
+ }
192
+ if (hasValueBinding && !varName && child.type === 'simple_identifier') {
193
+ varName = child.text;
194
+ continue;
195
+ }
196
+ if (varName && !valueNode) {
197
+ // Skip type annotations and binding operators
198
+ if (child.type === 'type_annotation')
199
+ continue;
200
+ valueNode = child;
201
+ break;
202
+ }
203
+ }
204
+ if (!hasValueBinding || !varName || !valueNode || scopeEnv.has(varName))
205
+ return undefined;
206
+ // Unwrap await/try
207
+ valueNode = unwrapSwiftExpression(valueNode);
208
+ // simple_identifier → copy
209
+ if (valueNode.type === 'simple_identifier') {
210
+ return { kind: 'copy', lhs: varName, rhs: valueNode.text };
211
+ }
212
+ // navigation_expression → fieldAccess
213
+ if (valueNode.type === 'navigation_expression') {
214
+ const receiver = valueNode.firstNamedChild;
215
+ const suffix = valueNode.lastNamedChild;
216
+ if (receiver?.type === 'simple_identifier' && suffix?.type === 'navigation_suffix') {
217
+ const field = suffix.lastNamedChild;
218
+ if (field?.type === 'simple_identifier') {
219
+ return { kind: 'fieldAccess', lhs: varName, receiver: receiver.text, field: field.text };
220
+ }
221
+ }
222
+ return undefined;
223
+ }
224
+ // call_expression → callResult or methodCallResult
225
+ if (valueNode.type === 'call_expression') {
226
+ const callee = valueNode.firstNamedChild;
227
+ if (!callee)
228
+ return undefined;
229
+ if (callee.type === 'simple_identifier') {
230
+ return { kind: 'callResult', lhs: varName, callee: callee.text };
231
+ }
232
+ if (callee.type === 'navigation_expression') {
233
+ const receiver = callee.firstNamedChild;
234
+ const suffix = callee.lastNamedChild;
235
+ if (receiver?.type === 'simple_identifier' && suffix?.type === 'navigation_suffix') {
236
+ const method = suffix.lastNamedChild;
237
+ if (method?.type === 'simple_identifier') {
238
+ return { kind: 'methodCallResult', lhs: varName, receiver: receiver.text, method: method.text };
239
+ }
240
+ }
241
+ }
242
+ }
243
+ return undefined;
244
+ }
245
+ /**
246
+ * Swift: extract pending assignments for Tier 2 return-type propagation.
247
+ * Handles:
248
+ * let user = getUser() → callResult
249
+ * let result = user.save() → methodCallResult
250
+ * let name = user.name → fieldAccess
251
+ * let copy = user → copy
252
+ * let user = await getUser() → callResult (unwrapped)
253
+ * let user = try getUser() → callResult (unwrapped)
254
+ * if let user = getUser() → callResult (optional binding)
255
+ * guard let user = getUser() → callResult (optional binding)
256
+ */
257
+ const extractPendingAssignment = (node, scopeEnv) => {
258
+ // Handle if_statement and guard_statement optional bindings
259
+ if (node.type === 'if_statement' || node.type === 'guard_statement') {
260
+ return extractIfGuardBinding(node, scopeEnv);
261
+ }
262
+ if (node.type !== 'property_declaration')
263
+ return undefined;
264
+ // Skip if type annotation exists — extractDeclaration handles it
265
+ if (hasTypeAnnotation(node))
266
+ return undefined;
267
+ // Find the variable name from the pattern child
268
+ let lhs;
269
+ for (let i = 0; i < node.namedChildCount; i++) {
270
+ const child = node.namedChild(i);
271
+ if (child?.type === 'pattern') {
272
+ lhs = child.text;
273
+ break;
274
+ }
275
+ }
276
+ if (!lhs || scopeEnv.has(lhs))
277
+ return undefined;
278
+ // Find the value expression (last meaningful named child after pattern)
279
+ let valueNode = null;
280
+ for (let i = node.namedChildCount - 1; i >= 0; i--) {
281
+ const child = node.namedChild(i);
282
+ if (!child)
283
+ continue;
284
+ if (child.type === 'pattern' || child.type === 'value_binding_pattern' || child.type === 'type_annotation')
285
+ continue;
286
+ valueNode = child;
287
+ break;
288
+ }
289
+ if (!valueNode)
290
+ return undefined;
291
+ // Unwrap await/try expressions (Feature 2)
292
+ valueNode = unwrapSwiftExpression(valueNode);
293
+ // let copy = user → copy
294
+ if (valueNode.type === 'simple_identifier') {
295
+ return { kind: 'copy', lhs, rhs: valueNode.text };
296
+ }
297
+ // let name = user.name → fieldAccess
298
+ if (valueNode.type === 'navigation_expression') {
299
+ const receiver = valueNode.firstNamedChild;
300
+ const suffix = valueNode.lastNamedChild;
301
+ if (receiver?.type === 'simple_identifier' && suffix?.type === 'navigation_suffix') {
302
+ const field = suffix.lastNamedChild;
303
+ if (field?.type === 'simple_identifier') {
304
+ return { kind: 'fieldAccess', lhs, receiver: receiver.text, field: field.text };
305
+ }
306
+ }
307
+ return undefined;
308
+ }
309
+ // Call expressions
310
+ if (valueNode.type === 'call_expression') {
311
+ const callee = valueNode.firstNamedChild;
312
+ if (!callee)
313
+ return undefined;
314
+ // let user = getUser() → callResult
315
+ if (callee.type === 'simple_identifier') {
316
+ return { kind: 'callResult', lhs, callee: callee.text };
317
+ }
318
+ // let result = user.save() → methodCallResult
319
+ if (callee.type === 'navigation_expression') {
320
+ const receiver = callee.firstNamedChild;
321
+ const suffix = callee.lastNamedChild;
322
+ if (receiver?.type === 'simple_identifier' && suffix?.type === 'navigation_suffix') {
323
+ const method = suffix.lastNamedChild;
324
+ if (method?.type === 'simple_identifier') {
325
+ return { kind: 'methodCallResult', lhs, receiver: receiver.text, method: method.text };
326
+ }
327
+ }
328
+ }
329
+ }
330
+ return undefined;
331
+ };
332
+ /**
333
+ * Swift: extract loop variable type binding from `for item in collection`.
334
+ * AST: for_statement with pattern > simple_identifier (loop var) and
335
+ * a simple_identifier/call_expression (collection).
336
+ */
337
+ const extractForLoopBinding = (node, { scopeEnv, declarationTypeNodes, scope, returnTypeLookup }) => {
338
+ if (node.type !== 'for_statement')
339
+ return;
340
+ // Find the loop variable from the pattern child
341
+ let loopVarName;
342
+ let iterableNode = null;
343
+ // for_statement children: pattern (loop var), then the iterable expression, then the body
344
+ for (let i = 0; i < node.namedChildCount; i++) {
345
+ const child = node.namedChild(i);
346
+ if (!child)
347
+ continue;
348
+ if (child.type === 'pattern' || child.type === 'simple_identifier') {
349
+ if (!loopVarName) {
350
+ // Extract a simple identifier from the pattern. Skip non-trivial patterns
351
+ // (e.g. tuple destructuring `for (a, b) in ...`) to avoid polluting scopeEnv.
352
+ const varName = extractVarName(child) ?? (child.type === 'simple_identifier' ? child.text : undefined);
353
+ if (!varName)
354
+ return; // Non-simple pattern — bail out
355
+ loopVarName = varName;
356
+ continue;
357
+ }
358
+ }
359
+ // After we found the loop var, the next expression-like node is the iterable
360
+ if (loopVarName && !iterableNode) {
361
+ if (child.type === 'simple_identifier' || child.type === 'call_expression' ||
362
+ child.type === 'navigation_expression') {
363
+ iterableNode = child;
364
+ break;
365
+ }
366
+ }
367
+ }
368
+ if (!loopVarName || !iterableNode)
369
+ return;
370
+ let iterableName;
371
+ let callExprElementType;
372
+ if (iterableNode.type === 'simple_identifier') {
373
+ iterableName = iterableNode.text;
374
+ }
375
+ else if (iterableNode.type === 'navigation_expression') {
376
+ // collection.property
377
+ const suffix = iterableNode.lastNamedChild;
378
+ if (suffix?.type === 'navigation_suffix') {
379
+ const prop = suffix.lastNamedChild;
380
+ if (prop?.type === 'simple_identifier')
381
+ iterableName = prop.text;
382
+ }
383
+ else if (suffix?.type === 'simple_identifier') {
384
+ iterableName = suffix.text;
385
+ }
386
+ }
387
+ else if (iterableNode.type === 'call_expression') {
388
+ // getItems() or collection.values()
389
+ const fn = iterableNode.firstNamedChild;
390
+ let callee;
391
+ if (fn?.type === 'simple_identifier') {
392
+ callee = fn.text;
393
+ }
394
+ else if (fn?.type === 'navigation_expression') {
395
+ const obj = fn.firstNamedChild;
396
+ const suffix = fn.lastNamedChild;
397
+ if (obj?.type === 'simple_identifier')
398
+ iterableName = obj.text;
399
+ if (suffix?.type === 'navigation_suffix') {
400
+ const m = suffix.lastNamedChild;
401
+ if (m?.type === 'simple_identifier')
402
+ callee = m.text;
403
+ }
404
+ else if (suffix?.type === 'simple_identifier') {
405
+ callee = suffix.text;
406
+ }
407
+ }
408
+ if (callee) {
409
+ const rawReturn = returnTypeLookup.lookupRawReturnType(callee);
410
+ if (rawReturn)
411
+ callExprElementType = extractElementTypeFromString(rawReturn);
412
+ }
413
+ }
414
+ if (!iterableName && !callExprElementType)
415
+ return;
416
+ let elementType;
417
+ if (callExprElementType) {
418
+ elementType = callExprElementType;
419
+ }
420
+ else if (iterableName) {
421
+ // Try to resolve element type from the iterable's declared type
422
+ elementType = resolveIterableElementType(iterableName, node, scopeEnv, declarationTypeNodes, scope, extractSwiftElementTypeFromTypeNode);
423
+ }
424
+ if (elementType && !scopeEnv.has(loopVarName)) {
425
+ scopeEnv.set(loopVarName, elementType);
426
+ }
427
+ };
428
+ /**
429
+ * Extract element type from a Swift type annotation AST node.
430
+ * Handles: [User] (array sugar), Array<User>, Set<User>, etc.
431
+ */
432
+ function extractSwiftElementTypeFromTypeNode(typeNode) {
433
+ // Swift array sugar: [User] — parsed as array_type > user_type > type_identifier
434
+ if (typeNode.type === 'array_type') {
435
+ const inner = typeNode.firstNamedChild;
436
+ if (inner)
437
+ return extractSimpleTypeName(inner);
438
+ }
439
+ // Generic type: Array<User>, Set<User>
440
+ if (typeNode.type === 'user_type') {
441
+ // Check for generic args: user_type > type_identifier + type_arguments
442
+ for (let i = 0; i < typeNode.namedChildCount; i++) {
443
+ const child = typeNode.namedChild(i);
444
+ if (child?.type === 'type_arguments') {
445
+ const lastArg = child.lastNamedChild;
446
+ if (lastArg)
447
+ return extractSimpleTypeName(lastArg);
448
+ }
449
+ }
450
+ }
451
+ // type_annotation wrapping
452
+ if (typeNode.type === 'type_annotation') {
453
+ const inner = typeNode.firstNamedChild;
454
+ if (inner)
455
+ return extractSwiftElementTypeFromTypeNode(inner);
456
+ }
457
+ return undefined;
458
+ }
131
459
  export const typeConfig = {
132
460
  declarationNodeTypes: DECLARATION_NODE_TYPES,
461
+ forLoopNodeTypes: FOR_LOOP_NODE_TYPES,
133
462
  extractDeclaration,
134
463
  extractParameter,
135
464
  extractInitializer,
136
465
  scanConstructorBinding,
466
+ extractPendingAssignment,
467
+ extractForLoopBinding,
137
468
  };
@@ -1,4 +1,4 @@
1
- import type { SyntaxNode } from '../utils.js';
1
+ import type { SyntaxNode } from '../utils/ast-helpers.js';
2
2
  /** Extracts type bindings from a declaration node into the env map */
3
3
  export type TypeBindingExtractor = (node: SyntaxNode, env: Map<string, string>) => void;
4
4
  /** Extracts type bindings from a parameter node into the env map */
@@ -23,6 +23,20 @@ export type ConstructorBindingScanner = (node: SyntaxNode) => {
23
23
  * Used for languages where return types are expressed in comments (e.g. YARD @return [Type])
24
24
  * rather than in AST fields. Returns undefined if no return type can be determined. */
25
25
  export type ReturnTypeExtractor = (node: SyntaxNode) => string | undefined;
26
+ /** Infer the type name of a literal AST node for overload disambiguation.
27
+ * Returns the canonical type name (e.g. 'int', 'String', 'boolean') or undefined
28
+ * for non-literal nodes. Only used when resolveCallTarget has multiple candidates
29
+ * with parameterTypes — ~1-3% of call sites. */
30
+ export type LiteralTypeInferrer = (node: SyntaxNode) => string | undefined;
31
+ /** Detect constructor-style call expressions that don't use `new` keyword.
32
+ * Returns the constructor class name if the node's initializer is a constructor call,
33
+ * or undefined otherwise. Used for virtual dispatch in languages like Kotlin
34
+ * where constructors are syntactically identical to function calls, and C++
35
+ * where smart pointer factory functions (make_shared/make_unique) wrap constructors. */
36
+ export type ConstructorTypeDetector = (node: SyntaxNode, classNames: ClassNameLookup) => string | undefined;
37
+ /** Unwrap a declared type name to its inner type for virtual dispatch comparison.
38
+ * E.g., C++ shared_ptr<Animal> → Animal. Returns undefined if no unwrapping applies. */
39
+ export type DeclaredTypeUnwrapper = (declaredType: string, typeNode: SyntaxNode) => string | undefined;
26
40
  /** Narrow lookup interface for resolving a callee name → return type name.
27
41
  * Backed by SymbolTable.lookupFuzzyCallable; passed via ForLoopExtractorContext.
28
42
  * Conservative: returns undefined when the callee is ambiguous (0 or 2+ matches). */
@@ -61,6 +75,8 @@ export type PendingAssignment = {
61
75
  kind: 'callResult';
62
76
  lhs: string;
63
77
  callee: string;
78
+ calleeFqn?: string;
79
+ line?: number;
64
80
  } | {
65
81
  kind: 'fieldAccess';
66
82
  lhs: string;
@@ -76,11 +92,27 @@ export type PendingAssignment = {
76
92
  * Returns a PendingAssignment when the RHS is a bare identifier (`copy`), a
77
93
  * call expression (`callResult`), a field access (`fieldAccess`), or a
78
94
  * method call with receiver (`methodCallResult`) and the LHS has no resolved type yet.
95
+ * May return an array of PendingAssignment items for destructuring patterns
96
+ * (e.g., `const { a, b } = obj` emits N fieldAccess items).
79
97
  * Returns undefined if the node is not a matching assignment. */
80
- export type PendingAssignmentExtractor = (node: SyntaxNode, scopeEnv: ReadonlyMap<string, string>) => PendingAssignment | undefined;
98
+ export type PendingAssignmentExtractor = (node: SyntaxNode, scopeEnv: ReadonlyMap<string, string>) => PendingAssignment | PendingAssignment[] | undefined;
99
+ /** Result of a pattern binding extraction. */
100
+ export interface PatternBindingResult {
101
+ varName: string;
102
+ typeName: string;
103
+ /** Optional: AST node whose position range should be used for the patternOverride.
104
+ * When present, the override uses this node's range instead of the auto-detected
105
+ * branch scope. Used by null-check narrowing to target the if-body specifically. */
106
+ narrowingRange?: {
107
+ startIndex: number;
108
+ endIndex: number;
109
+ };
110
+ }
81
111
  /** Extracts a typed variable binding from a pattern-matching construct.
82
- * Returns { varName, typeName } for patterns that introduce NEW variables.
83
- * Examples: `if let Some(user) = opt` (Rust), `x instanceof User user` (Java).
112
+ * Returns { varName, typeName } for patterns that introduce NEW variables
113
+ * or narrow existing variables (null-check narrowing).
114
+ * Examples: `if let Some(user) = opt` (Rust), `x instanceof User user` (Java),
115
+ * `if (x != null)` (null-check narrowing in TS/Kotlin/C#).
84
116
  * Conservative: returns undefined when the source variable's type is unknown.
85
117
  *
86
118
  * @param scopeEnv Read-only view of already-resolved type bindings in the current scope.
@@ -88,10 +120,7 @@ export type PendingAssignmentExtractor = (node: SyntaxNode, scopeEnv: ReadonlyMa
88
120
  * annotation AST node. Allows extracting generic type arguments (e.g., T from Result<T,E>)
89
121
  * that are stripped during normal TypeEnv extraction.
90
122
  * @param scope Current scope key (e.g. `"process@42"`) for declarationTypeNodes lookups. */
91
- export type PatternBindingExtractor = (node: SyntaxNode, scopeEnv: ReadonlyMap<string, string>, declarationTypeNodes: ReadonlyMap<string, SyntaxNode>, scope: string) => {
92
- varName: string;
93
- typeName: string;
94
- } | undefined;
123
+ export type PatternBindingExtractor = (node: SyntaxNode, scopeEnv: ReadonlyMap<string, string>, declarationTypeNodes: ReadonlyMap<string, SyntaxNode>, scope: string) => PatternBindingResult | undefined;
95
124
  /** Per-language type extraction configuration */
96
125
  export interface LanguageTypeConfig {
97
126
  /** Allow pattern binding to overwrite existing scopeEnv entries.
@@ -137,4 +166,7 @@ export interface LanguageTypeConfig {
137
166
  * The extractor receives the current scope's resolved bindings (read-only) to look up the
138
167
  * source variable's type. Returns undefined for non-matching nodes or unknown source types. */
139
168
  extractPatternBinding?: PatternBindingExtractor;
169
+ inferLiteralType?: LiteralTypeInferrer;
170
+ detectConstructorType?: ConstructorTypeDetector;
171
+ unwrapDeclaredType?: DeclaredTypeUnwrapper;
140
172
  }
@@ -444,7 +444,8 @@ const extractForLoopBinding = (node, { scopeEnv, declarationTypeNodes, scope, re
444
444
  if (loopVarName)
445
445
  scopeEnv.set(loopVarName, elementType);
446
446
  };
447
- /** TS/JS: const alias = u → variable_declarator with name/value fields */
447
+ /** TS/JS: const alias = u → variable_declarator with name/value fields.
448
+ * Also handles destructuring: `const { a, b } = obj` → N fieldAccess items. */
448
449
  const extractPendingAssignment = (node, scopeEnv) => {
449
450
  for (let i = 0; i < node.namedChildCount; i++) {
450
451
  const child = node.namedChild(i);
@@ -454,6 +455,39 @@ const extractPendingAssignment = (node, scopeEnv) => {
454
455
  const valueNode = child.childForFieldName('value');
455
456
  if (!nameNode || !valueNode)
456
457
  continue;
458
+ // Object destructuring: `const { address, name } = user`
459
+ // Emits N fieldAccess items — one per destructured binding.
460
+ if (nameNode.type === 'object_pattern' && valueNode.type === 'identifier') {
461
+ const receiver = valueNode.text;
462
+ const items = [];
463
+ for (let j = 0; j < nameNode.namedChildCount; j++) {
464
+ const prop = nameNode.namedChild(j);
465
+ if (!prop)
466
+ continue;
467
+ if (prop.type === 'shorthand_property_identifier_pattern') {
468
+ // `const { name } = user` → shorthand: varName = fieldName
469
+ const varName = prop.text;
470
+ if (!scopeEnv.has(varName)) {
471
+ items.push({ kind: 'fieldAccess', lhs: varName, receiver, field: varName });
472
+ }
473
+ }
474
+ else if (prop.type === 'pair_pattern') {
475
+ // `const { address: addr } = user` → pair_pattern: key=field, value=varName
476
+ const keyNode = prop.childForFieldName('key');
477
+ const valNode = prop.childForFieldName('value');
478
+ if (keyNode && valNode) {
479
+ const fieldName = keyNode.text;
480
+ const varName = valNode.text;
481
+ if (!scopeEnv.has(varName)) {
482
+ items.push({ kind: 'fieldAccess', lhs: varName, receiver, field: fieldName });
483
+ }
484
+ }
485
+ }
486
+ }
487
+ if (items.length > 0)
488
+ return items;
489
+ continue;
490
+ }
457
491
  const lhs = nameNode.text;
458
492
  if (scopeEnv.has(lhs))
459
493
  continue;
@@ -492,22 +526,119 @@ const extractPendingAssignment = (node, scopeEnv) => {
492
526
  }
493
527
  return undefined;
494
528
  };
529
+ /** Null-check keywords that indicate a null-comparison in binary expressions. */
530
+ const NULL_CHECK_KEYWORDS = new Set(['null', 'undefined']);
531
+ /**
532
+ * Find the if-body (consequence) block for a null-check binary_expression.
533
+ * Walks up from the binary_expression through parenthesized_expression to if_statement,
534
+ * then returns the consequence block (statement_block).
535
+ *
536
+ * AST structure: if_statement > parenthesized_expression > binary_expression
537
+ * if_statement > statement_block (consequence)
538
+ */
539
+ const findIfConsequenceBlock = (binaryExpr) => {
540
+ // Walk up to find the if_statement (typically: binary_expression > parenthesized_expression > if_statement)
541
+ let current = binaryExpr.parent;
542
+ while (current) {
543
+ if (current.type === 'if_statement') {
544
+ // The consequence is the first statement_block child of if_statement
545
+ for (let i = 0; i < current.childCount; i++) {
546
+ const child = current.child(i);
547
+ if (child?.type === 'statement_block')
548
+ return child;
549
+ }
550
+ return undefined;
551
+ }
552
+ // Stop climbing at function/block boundaries — don't cross scope
553
+ if (current.type === 'function_declaration' || current.type === 'function_expression'
554
+ || current.type === 'arrow_function' || current.type === 'method_definition')
555
+ return undefined;
556
+ current = current.parent;
557
+ }
558
+ return undefined;
559
+ };
495
560
  /** TS instanceof narrowing: `x instanceof User` → bind x to User.
496
- * Only works when x has no prior type binding (e.g. x: unknown, untyped params).
497
- * Typed params (x: Animal) are blocked by the !scopeEnv.has() guard in buildTypeEnv.
498
- * Uses first-writer-wins, same as Rust match arm bindings. */
499
- const extractPatternBinding = (node) => {
561
+ * Also handles null-check narrowing: `x !== null`, `x != undefined` etc.
562
+ * instanceof: first-writer-wins (no prior type binding).
563
+ * null-check: position-indexed narrowing via narrowingRange. */
564
+ const extractPatternBinding = (node, scopeEnv, declarationTypeNodes, scope) => {
500
565
  if (node.type !== 'binary_expression')
501
566
  return undefined;
502
- const op = node.children.find(c => !c.isNamed && c.text === 'instanceof');
567
+ // Check for instanceof first (existing behavior)
568
+ const instanceofOp = node.children.find(c => !c.isNamed && c.text === 'instanceof');
569
+ if (instanceofOp) {
570
+ const left = node.namedChild(0);
571
+ const right = node.namedChild(1);
572
+ if (left?.type !== 'identifier' || right?.type !== 'identifier')
573
+ return undefined;
574
+ return { varName: left.text, typeName: right.text };
575
+ }
576
+ // Null-check narrowing: x !== null, x != null, x !== undefined, x != undefined
577
+ const op = node.children.find(c => !c.isNamed && (c.text === '!==' || c.text === '!='));
503
578
  if (!op)
504
579
  return undefined;
505
- // binary_expression children are positional — no left/right fields
506
580
  const left = node.namedChild(0);
507
581
  const right = node.namedChild(1);
508
- if (left?.type !== 'identifier' || right?.type !== 'identifier')
582
+ if (!left || !right)
583
+ return undefined;
584
+ // Determine which side is the variable and which is null/undefined
585
+ let varNode;
586
+ let isNullCheck = false;
587
+ if (left.type === 'identifier' && NULL_CHECK_KEYWORDS.has(right.text)) {
588
+ varNode = left;
589
+ isNullCheck = true;
590
+ }
591
+ else if (right.type === 'identifier' && NULL_CHECK_KEYWORDS.has(left.text)) {
592
+ varNode = right;
593
+ isNullCheck = true;
594
+ }
595
+ if (!isNullCheck || !varNode)
509
596
  return undefined;
510
- return { varName: left.text, typeName: right.text };
597
+ const varName = varNode.text;
598
+ // Look up the variable's resolved type (already stripped of nullable by extractSimpleTypeName)
599
+ const resolvedType = scopeEnv.get(varName);
600
+ if (!resolvedType)
601
+ return undefined;
602
+ // Check if the original declaration type was nullable by looking at the raw AST type node.
603
+ // extractSimpleTypeName already strips nullable markers, so we need the original to know
604
+ // if narrowing is meaningful (i.e., the variable was declared as nullable).
605
+ const declTypeNode = declarationTypeNodes.get(`${scope}\0${varName}`);
606
+ if (!declTypeNode)
607
+ return undefined;
608
+ const declText = declTypeNode.text;
609
+ // Only narrow if the original declaration was nullable
610
+ if (!declText.includes('null') && !declText.includes('undefined'))
611
+ return undefined;
612
+ // Find the if-body block to scope the narrowing
613
+ const ifBody = findIfConsequenceBlock(node);
614
+ if (!ifBody)
615
+ return undefined;
616
+ return {
617
+ varName,
618
+ typeName: resolvedType,
619
+ narrowingRange: { startIndex: ifBody.startIndex, endIndex: ifBody.endIndex },
620
+ };
621
+ };
622
+ /** Infer the type of a literal AST node for TypeScript overload disambiguation. */
623
+ const inferTsLiteralType = (node) => {
624
+ switch (node.type) {
625
+ case 'number':
626
+ return 'number';
627
+ case 'string':
628
+ case 'template_string':
629
+ return 'string';
630
+ case 'true':
631
+ case 'false':
632
+ return 'boolean';
633
+ case 'null':
634
+ return 'null';
635
+ case 'undefined':
636
+ return 'undefined';
637
+ case 'regex':
638
+ return 'RegExp';
639
+ default:
640
+ return undefined;
641
+ }
511
642
  };
512
643
  export const typeConfig = {
513
644
  declarationNodeTypes: DECLARATION_NODE_TYPES,
@@ -521,4 +652,5 @@ export const typeConfig = {
521
652
  extractForLoopBinding,
522
653
  extractPendingAssignment,
523
654
  extractPatternBinding,
655
+ inferLiteralType: inferTsLiteralType,
524
656
  };