@duytransipher/gitnexus 1.4.6-sipher.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 (224) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +261 -0
  3. package/dist/cli/ai-context.d.ts +23 -0
  4. package/dist/cli/ai-context.js +265 -0
  5. package/dist/cli/analyze.d.ts +12 -0
  6. package/dist/cli/analyze.js +345 -0
  7. package/dist/cli/augment.d.ts +13 -0
  8. package/dist/cli/augment.js +33 -0
  9. package/dist/cli/clean.d.ts +10 -0
  10. package/dist/cli/clean.js +60 -0
  11. package/dist/cli/eval-server.d.ts +37 -0
  12. package/dist/cli/eval-server.js +389 -0
  13. package/dist/cli/index.d.ts +2 -0
  14. package/dist/cli/index.js +137 -0
  15. package/dist/cli/lazy-action.d.ts +6 -0
  16. package/dist/cli/lazy-action.js +18 -0
  17. package/dist/cli/list.d.ts +6 -0
  18. package/dist/cli/list.js +30 -0
  19. package/dist/cli/mcp.d.ts +8 -0
  20. package/dist/cli/mcp.js +36 -0
  21. package/dist/cli/serve.d.ts +4 -0
  22. package/dist/cli/serve.js +6 -0
  23. package/dist/cli/setup.d.ts +8 -0
  24. package/dist/cli/setup.js +367 -0
  25. package/dist/cli/sipher-patched.d.ts +2 -0
  26. package/dist/cli/sipher-patched.js +77 -0
  27. package/dist/cli/skill-gen.d.ts +26 -0
  28. package/dist/cli/skill-gen.js +549 -0
  29. package/dist/cli/status.d.ts +6 -0
  30. package/dist/cli/status.js +36 -0
  31. package/dist/cli/tool.d.ts +60 -0
  32. package/dist/cli/tool.js +180 -0
  33. package/dist/cli/wiki.d.ts +15 -0
  34. package/dist/cli/wiki.js +365 -0
  35. package/dist/config/ignore-service.d.ts +26 -0
  36. package/dist/config/ignore-service.js +284 -0
  37. package/dist/config/supported-languages.d.ts +15 -0
  38. package/dist/config/supported-languages.js +16 -0
  39. package/dist/core/augmentation/engine.d.ts +26 -0
  40. package/dist/core/augmentation/engine.js +240 -0
  41. package/dist/core/embeddings/embedder.d.ts +60 -0
  42. package/dist/core/embeddings/embedder.js +251 -0
  43. package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
  44. package/dist/core/embeddings/embedding-pipeline.js +356 -0
  45. package/dist/core/embeddings/index.d.ts +9 -0
  46. package/dist/core/embeddings/index.js +9 -0
  47. package/dist/core/embeddings/text-generator.d.ts +24 -0
  48. package/dist/core/embeddings/text-generator.js +182 -0
  49. package/dist/core/embeddings/types.d.ts +87 -0
  50. package/dist/core/embeddings/types.js +32 -0
  51. package/dist/core/graph/graph.d.ts +2 -0
  52. package/dist/core/graph/graph.js +66 -0
  53. package/dist/core/graph/types.d.ts +66 -0
  54. package/dist/core/graph/types.js +1 -0
  55. package/dist/core/ingestion/ast-cache.d.ts +11 -0
  56. package/dist/core/ingestion/ast-cache.js +35 -0
  57. package/dist/core/ingestion/call-processor.d.ts +23 -0
  58. package/dist/core/ingestion/call-processor.js +793 -0
  59. package/dist/core/ingestion/call-routing.d.ts +68 -0
  60. package/dist/core/ingestion/call-routing.js +129 -0
  61. package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
  62. package/dist/core/ingestion/cluster-enricher.js +170 -0
  63. package/dist/core/ingestion/community-processor.d.ts +39 -0
  64. package/dist/core/ingestion/community-processor.js +312 -0
  65. package/dist/core/ingestion/constants.d.ts +16 -0
  66. package/dist/core/ingestion/constants.js +16 -0
  67. package/dist/core/ingestion/entry-point-scoring.d.ts +40 -0
  68. package/dist/core/ingestion/entry-point-scoring.js +353 -0
  69. package/dist/core/ingestion/export-detection.d.ts +18 -0
  70. package/dist/core/ingestion/export-detection.js +231 -0
  71. package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
  72. package/dist/core/ingestion/filesystem-walker.js +81 -0
  73. package/dist/core/ingestion/framework-detection.d.ts +54 -0
  74. package/dist/core/ingestion/framework-detection.js +411 -0
  75. package/dist/core/ingestion/heritage-processor.d.ts +28 -0
  76. package/dist/core/ingestion/heritage-processor.js +251 -0
  77. package/dist/core/ingestion/import-processor.d.ts +34 -0
  78. package/dist/core/ingestion/import-processor.js +398 -0
  79. package/dist/core/ingestion/language-config.d.ts +46 -0
  80. package/dist/core/ingestion/language-config.js +167 -0
  81. package/dist/core/ingestion/mro-processor.d.ts +45 -0
  82. package/dist/core/ingestion/mro-processor.js +369 -0
  83. package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
  84. package/dist/core/ingestion/named-binding-extraction.js +363 -0
  85. package/dist/core/ingestion/parsing-processor.d.ts +19 -0
  86. package/dist/core/ingestion/parsing-processor.js +315 -0
  87. package/dist/core/ingestion/pipeline.d.ts +6 -0
  88. package/dist/core/ingestion/pipeline.js +401 -0
  89. package/dist/core/ingestion/process-processor.d.ts +51 -0
  90. package/dist/core/ingestion/process-processor.js +315 -0
  91. package/dist/core/ingestion/resolution-context.d.ts +53 -0
  92. package/dist/core/ingestion/resolution-context.js +132 -0
  93. package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
  94. package/dist/core/ingestion/resolvers/csharp.js +109 -0
  95. package/dist/core/ingestion/resolvers/go.d.ts +19 -0
  96. package/dist/core/ingestion/resolvers/go.js +42 -0
  97. package/dist/core/ingestion/resolvers/index.d.ts +18 -0
  98. package/dist/core/ingestion/resolvers/index.js +13 -0
  99. package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
  100. package/dist/core/ingestion/resolvers/jvm.js +87 -0
  101. package/dist/core/ingestion/resolvers/php.d.ts +15 -0
  102. package/dist/core/ingestion/resolvers/php.js +35 -0
  103. package/dist/core/ingestion/resolvers/python.d.ts +19 -0
  104. package/dist/core/ingestion/resolvers/python.js +52 -0
  105. package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
  106. package/dist/core/ingestion/resolvers/ruby.js +15 -0
  107. package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
  108. package/dist/core/ingestion/resolvers/rust.js +73 -0
  109. package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
  110. package/dist/core/ingestion/resolvers/standard.js +123 -0
  111. package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
  112. package/dist/core/ingestion/resolvers/utils.js +122 -0
  113. package/dist/core/ingestion/structure-processor.d.ts +2 -0
  114. package/dist/core/ingestion/structure-processor.js +36 -0
  115. package/dist/core/ingestion/symbol-table.d.ts +63 -0
  116. package/dist/core/ingestion/symbol-table.js +85 -0
  117. package/dist/core/ingestion/tree-sitter-queries.d.ts +15 -0
  118. package/dist/core/ingestion/tree-sitter-queries.js +888 -0
  119. package/dist/core/ingestion/type-env.d.ts +49 -0
  120. package/dist/core/ingestion/type-env.js +613 -0
  121. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
  123. package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
  124. package/dist/core/ingestion/type-extractors/csharp.js +383 -0
  125. package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
  126. package/dist/core/ingestion/type-extractors/go.js +467 -0
  127. package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
  128. package/dist/core/ingestion/type-extractors/index.js +31 -0
  129. package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
  130. package/dist/core/ingestion/type-extractors/jvm.js +681 -0
  131. package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
  132. package/dist/core/ingestion/type-extractors/php.js +549 -0
  133. package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
  134. package/dist/core/ingestion/type-extractors/python.js +455 -0
  135. package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
  136. package/dist/core/ingestion/type-extractors/ruby.js +389 -0
  137. package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
  138. package/dist/core/ingestion/type-extractors/rust.js +456 -0
  139. package/dist/core/ingestion/type-extractors/shared.d.ts +145 -0
  140. package/dist/core/ingestion/type-extractors/shared.js +810 -0
  141. package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
  142. package/dist/core/ingestion/type-extractors/swift.js +137 -0
  143. package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
  144. package/dist/core/ingestion/type-extractors/types.js +1 -0
  145. package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
  146. package/dist/core/ingestion/type-extractors/typescript.js +494 -0
  147. package/dist/core/ingestion/utils.d.ts +138 -0
  148. package/dist/core/ingestion/utils.js +1290 -0
  149. package/dist/core/ingestion/workers/parse-worker.d.ts +122 -0
  150. package/dist/core/ingestion/workers/parse-worker.js +1126 -0
  151. package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
  152. package/dist/core/ingestion/workers/worker-pool.js +128 -0
  153. package/dist/core/lbug/csv-generator.d.ts +33 -0
  154. package/dist/core/lbug/csv-generator.js +366 -0
  155. package/dist/core/lbug/lbug-adapter.d.ts +103 -0
  156. package/dist/core/lbug/lbug-adapter.js +769 -0
  157. package/dist/core/lbug/schema.d.ts +53 -0
  158. package/dist/core/lbug/schema.js +430 -0
  159. package/dist/core/search/bm25-index.d.ts +23 -0
  160. package/dist/core/search/bm25-index.js +96 -0
  161. package/dist/core/search/hybrid-search.d.ts +49 -0
  162. package/dist/core/search/hybrid-search.js +118 -0
  163. package/dist/core/tree-sitter/parser-loader.d.ts +5 -0
  164. package/dist/core/tree-sitter/parser-loader.js +63 -0
  165. package/dist/core/wiki/generator.d.ts +120 -0
  166. package/dist/core/wiki/generator.js +939 -0
  167. package/dist/core/wiki/graph-queries.d.ts +80 -0
  168. package/dist/core/wiki/graph-queries.js +238 -0
  169. package/dist/core/wiki/html-viewer.d.ts +10 -0
  170. package/dist/core/wiki/html-viewer.js +297 -0
  171. package/dist/core/wiki/llm-client.d.ts +43 -0
  172. package/dist/core/wiki/llm-client.js +186 -0
  173. package/dist/core/wiki/prompts.d.ts +53 -0
  174. package/dist/core/wiki/prompts.js +174 -0
  175. package/dist/lib/utils.d.ts +1 -0
  176. package/dist/lib/utils.js +3 -0
  177. package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
  178. package/dist/mcp/compatible-stdio-transport.js +200 -0
  179. package/dist/mcp/core/embedder.d.ts +27 -0
  180. package/dist/mcp/core/embedder.js +108 -0
  181. package/dist/mcp/core/lbug-adapter.d.ts +57 -0
  182. package/dist/mcp/core/lbug-adapter.js +455 -0
  183. package/dist/mcp/local/local-backend.d.ts +181 -0
  184. package/dist/mcp/local/local-backend.js +1722 -0
  185. package/dist/mcp/resources.d.ts +31 -0
  186. package/dist/mcp/resources.js +411 -0
  187. package/dist/mcp/server.d.ts +23 -0
  188. package/dist/mcp/server.js +296 -0
  189. package/dist/mcp/staleness.d.ts +15 -0
  190. package/dist/mcp/staleness.js +29 -0
  191. package/dist/mcp/tools.d.ts +24 -0
  192. package/dist/mcp/tools.js +292 -0
  193. package/dist/server/api.d.ts +10 -0
  194. package/dist/server/api.js +344 -0
  195. package/dist/server/mcp-http.d.ts +13 -0
  196. package/dist/server/mcp-http.js +100 -0
  197. package/dist/storage/git.d.ts +6 -0
  198. package/dist/storage/git.js +35 -0
  199. package/dist/storage/repo-manager.d.ts +138 -0
  200. package/dist/storage/repo-manager.js +299 -0
  201. package/dist/types/pipeline.d.ts +32 -0
  202. package/dist/types/pipeline.js +18 -0
  203. package/dist/unreal/bridge.d.ts +4 -0
  204. package/dist/unreal/bridge.js +113 -0
  205. package/dist/unreal/config.d.ts +6 -0
  206. package/dist/unreal/config.js +55 -0
  207. package/dist/unreal/types.d.ts +105 -0
  208. package/dist/unreal/types.js +1 -0
  209. package/hooks/claude/gitnexus-hook.cjs +238 -0
  210. package/hooks/claude/pre-tool-use.sh +79 -0
  211. package/hooks/claude/session-start.sh +42 -0
  212. package/package.json +100 -0
  213. package/scripts/ensure-cli-executable.cjs +21 -0
  214. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  215. package/scripts/setup-unreal-gitnexus.ps1 +191 -0
  216. package/skills/gitnexus-cli.md +82 -0
  217. package/skills/gitnexus-debugging.md +89 -0
  218. package/skills/gitnexus-exploring.md +78 -0
  219. package/skills/gitnexus-guide.md +64 -0
  220. package/skills/gitnexus-impact-analysis.md +97 -0
  221. package/skills/gitnexus-pr-review.md +163 -0
  222. package/skills/gitnexus-refactoring.md +121 -0
  223. package/vendor/leiden/index.cjs +355 -0
  224. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,467 @@
1
+ import { extractSimpleTypeName, extractVarName, extractElementTypeFromString, extractGenericTypeArgs, resolveIterableElementType, methodToTypeArgPosition } from './shared.js';
2
+ const DECLARATION_NODE_TYPES = new Set([
3
+ 'var_declaration',
4
+ 'var_spec',
5
+ 'short_var_declaration',
6
+ ]);
7
+ /** Go: var x Foo */
8
+ const extractGoVarDeclaration = (node, env) => {
9
+ // Go var_declaration contains var_spec children
10
+ if (node.type === 'var_declaration') {
11
+ for (let i = 0; i < node.namedChildCount; i++) {
12
+ const spec = node.namedChild(i);
13
+ if (spec?.type === 'var_spec')
14
+ extractGoVarDeclaration(spec, env);
15
+ }
16
+ return;
17
+ }
18
+ // var_spec: name type [= value]
19
+ const nameNode = node.childForFieldName('name');
20
+ const typeNode = node.childForFieldName('type');
21
+ if (!nameNode || !typeNode)
22
+ return;
23
+ const varName = extractVarName(nameNode);
24
+ const typeName = extractSimpleTypeName(typeNode);
25
+ if (varName && typeName)
26
+ env.set(varName, typeName);
27
+ };
28
+ /** Go: x := Foo{...} — infer type from composite literal (handles multi-assignment) */
29
+ const extractGoShortVarDeclaration = (node, env) => {
30
+ const left = node.childForFieldName('left');
31
+ const right = node.childForFieldName('right');
32
+ if (!left || !right)
33
+ return;
34
+ // Collect LHS names and RHS values (may be expression_lists for multi-assignment)
35
+ const lhsNodes = [];
36
+ const rhsNodes = [];
37
+ if (left.type === 'expression_list') {
38
+ for (let i = 0; i < left.namedChildCount; i++) {
39
+ const c = left.namedChild(i);
40
+ if (c)
41
+ lhsNodes.push(c);
42
+ }
43
+ }
44
+ else {
45
+ lhsNodes.push(left);
46
+ }
47
+ if (right.type === 'expression_list') {
48
+ for (let i = 0; i < right.namedChildCount; i++) {
49
+ const c = right.namedChild(i);
50
+ if (c)
51
+ rhsNodes.push(c);
52
+ }
53
+ }
54
+ else {
55
+ rhsNodes.push(right);
56
+ }
57
+ // Pair each LHS name with its corresponding RHS value
58
+ const count = Math.min(lhsNodes.length, rhsNodes.length);
59
+ for (let i = 0; i < count; i++) {
60
+ let valueNode = rhsNodes[i];
61
+ // Unwrap &User{} — unary_expression (address-of) wrapping composite_literal
62
+ if (valueNode.type === 'unary_expression' && valueNode.firstNamedChild?.type === 'composite_literal') {
63
+ valueNode = valueNode.firstNamedChild;
64
+ }
65
+ // Go built-in new(User) — call_expression with 'new' callee and type argument
66
+ // Go built-in make([]User, 0) / make(map[string]User) — extract element/value type
67
+ if (valueNode.type === 'call_expression') {
68
+ const funcNode = valueNode.childForFieldName('function');
69
+ if (funcNode?.text === 'new') {
70
+ const args = valueNode.childForFieldName('arguments');
71
+ if (args?.firstNamedChild) {
72
+ const typeName = extractSimpleTypeName(args.firstNamedChild);
73
+ const varName = extractVarName(lhsNodes[i]);
74
+ if (varName && typeName)
75
+ env.set(varName, typeName);
76
+ }
77
+ }
78
+ else if (funcNode?.text === 'make') {
79
+ const args = valueNode.childForFieldName('arguments');
80
+ const firstArg = args?.firstNamedChild;
81
+ if (firstArg) {
82
+ let innerType = null;
83
+ if (firstArg.type === 'slice_type') {
84
+ innerType = firstArg.childForFieldName('element');
85
+ }
86
+ else if (firstArg.type === 'map_type') {
87
+ innerType = firstArg.childForFieldName('value');
88
+ }
89
+ if (innerType) {
90
+ const typeName = extractSimpleTypeName(innerType);
91
+ const varName = extractVarName(lhsNodes[i]);
92
+ if (varName && typeName)
93
+ env.set(varName, typeName);
94
+ }
95
+ }
96
+ }
97
+ continue;
98
+ }
99
+ // Go type assertion: user := iface.(User) — type_assertion_expression with 'type' field
100
+ if (valueNode.type === 'type_assertion_expression') {
101
+ const typeNode = valueNode.childForFieldName('type');
102
+ if (typeNode) {
103
+ const typeName = extractSimpleTypeName(typeNode);
104
+ const varName = extractVarName(lhsNodes[i]);
105
+ if (varName && typeName)
106
+ env.set(varName, typeName);
107
+ }
108
+ continue;
109
+ }
110
+ if (valueNode.type !== 'composite_literal')
111
+ continue;
112
+ const typeNode = valueNode.childForFieldName('type');
113
+ if (!typeNode)
114
+ continue;
115
+ const typeName = extractSimpleTypeName(typeNode);
116
+ if (!typeName)
117
+ continue;
118
+ const varName = extractVarName(lhsNodes[i]);
119
+ if (varName)
120
+ env.set(varName, typeName);
121
+ }
122
+ };
123
+ const extractDeclaration = (node, env) => {
124
+ if (node.type === 'var_declaration' || node.type === 'var_spec') {
125
+ extractGoVarDeclaration(node, env);
126
+ }
127
+ else if (node.type === 'short_var_declaration') {
128
+ extractGoShortVarDeclaration(node, env);
129
+ }
130
+ };
131
+ /** Go: parameter → name type */
132
+ const extractParameter = (node, env) => {
133
+ let nameNode = null;
134
+ let typeNode = null;
135
+ if (node.type === 'parameter') {
136
+ nameNode = node.childForFieldName('name');
137
+ typeNode = node.childForFieldName('type');
138
+ }
139
+ else {
140
+ nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
141
+ typeNode = node.childForFieldName('type');
142
+ }
143
+ if (!nameNode || !typeNode)
144
+ return;
145
+ const varName = extractVarName(nameNode);
146
+ const typeName = extractSimpleTypeName(typeNode);
147
+ if (varName && typeName)
148
+ env.set(varName, typeName);
149
+ };
150
+ /** Go: user := NewUser(...) — infer type from single-assignment call expression */
151
+ const scanConstructorBinding = (node) => {
152
+ if (node.type !== 'short_var_declaration')
153
+ return undefined;
154
+ const left = node.childForFieldName('left');
155
+ const right = node.childForFieldName('right');
156
+ if (!left || !right)
157
+ return undefined;
158
+ const leftIds = left.type === 'expression_list' ? left.namedChildren : [left];
159
+ const rightExprs = right.type === 'expression_list' ? right.namedChildren : [right];
160
+ // Multi-return: user, err := NewUser() — bind first var when second is err/ok/_
161
+ if (leftIds.length === 2 && rightExprs.length === 1) {
162
+ const secondVar = leftIds[1];
163
+ const isErrorOrDiscard = secondVar.text === '_' ||
164
+ secondVar.text === 'err' ||
165
+ secondVar.text === 'ok' ||
166
+ secondVar.text === 'error';
167
+ if (isErrorOrDiscard && leftIds[0].type === 'identifier') {
168
+ if (rightExprs[0].type !== 'call_expression')
169
+ return undefined;
170
+ const func = rightExprs[0].childForFieldName('function');
171
+ if (!func)
172
+ return undefined;
173
+ if (func.text === 'new' || func.text === 'make')
174
+ return undefined;
175
+ const calleeName = extractSimpleTypeName(func);
176
+ if (!calleeName)
177
+ return undefined;
178
+ return { varName: leftIds[0].text, calleeName };
179
+ }
180
+ }
181
+ // Single assignment only
182
+ if (leftIds.length !== 1 || leftIds[0].type !== 'identifier')
183
+ return undefined;
184
+ if (rightExprs.length !== 1 || rightExprs[0].type !== 'call_expression')
185
+ return undefined;
186
+ const func = rightExprs[0].childForFieldName('function');
187
+ if (!func)
188
+ return undefined;
189
+ // Skip new() and make() — already handled by extractDeclaration
190
+ if (func.text === 'new' || func.text === 'make')
191
+ return undefined;
192
+ const calleeName = extractSimpleTypeName(func);
193
+ if (!calleeName)
194
+ return undefined;
195
+ return { varName: leftIds[0].text, calleeName };
196
+ };
197
+ const FOR_LOOP_NODE_TYPES = new Set([
198
+ 'for_statement',
199
+ ]);
200
+ /** Go function/method node types that carry a parameter list. */
201
+ const GO_FUNCTION_NODE_TYPES = new Set([
202
+ 'function_declaration', 'method_declaration', 'func_literal',
203
+ ]);
204
+ /**
205
+ * Extract element type from a Go type annotation AST node.
206
+ * Handles:
207
+ * slice_type "[]User" → element field → type_identifier "User"
208
+ * array_type "[10]User" → element field → type_identifier "User"
209
+ * Falls back to text-based extraction via extractElementTypeFromString.
210
+ */
211
+ const extractGoElementTypeFromTypeNode = (typeNode, pos = 'last') => {
212
+ // slice_type: []User — element field is the element type
213
+ if (typeNode.type === 'slice_type' || typeNode.type === 'array_type') {
214
+ const elemNode = typeNode.childForFieldName('element');
215
+ if (elemNode)
216
+ return extractSimpleTypeName(elemNode);
217
+ }
218
+ // map_type: map[string]User — value field is the element type (for range, second var gets value)
219
+ if (typeNode.type === 'map_type') {
220
+ const valueNode = typeNode.childForFieldName('value');
221
+ if (valueNode)
222
+ return extractSimpleTypeName(valueNode);
223
+ }
224
+ // channel_type: chan User — the type argument is the element type
225
+ if (typeNode.type === 'channel_type') {
226
+ const valueNode = typeNode.childForFieldName('value') ?? typeNode.lastNamedChild;
227
+ if (valueNode)
228
+ return extractSimpleTypeName(valueNode);
229
+ }
230
+ // generic_type: Go 1.18+ generics (e.g., MySlice[User], Cache[string, User])
231
+ // Use position-aware arg selection: 'first' for keys, 'last' for values.
232
+ if (typeNode.type === 'generic_type') {
233
+ const args = extractGenericTypeArgs(typeNode);
234
+ if (args.length >= 1)
235
+ return pos === 'first' ? args[0] : args[args.length - 1];
236
+ }
237
+ // Fallback: text-based extraction ([]User → User, User[] → User)
238
+ return extractElementTypeFromString(typeNode.text, pos);
239
+ };
240
+ /** Check if a Go type node represents a channel type. Used to determine
241
+ * whether single-var range yields the element (channels) vs index (slices/maps). */
242
+ const isChannelType = (iterableName, scopeEnv, declarationTypeNodes, scope) => {
243
+ if (declarationTypeNodes && scope) {
244
+ const typeNode = declarationTypeNodes.get(`${scope}\0${iterableName}`);
245
+ if (typeNode)
246
+ return typeNode.type === 'channel_type';
247
+ }
248
+ const t = scopeEnv.get(iterableName);
249
+ return !!t && t.startsWith('chan ');
250
+ };
251
+ /**
252
+ * Walk up the AST from a for-statement to find the enclosing function declaration,
253
+ * then search its parameters for one named `iterableName`.
254
+ * Returns the element type extracted from its type annotation, or undefined.
255
+ *
256
+ * Go parameter_declaration has:
257
+ * name field: identifier (the parameter name)
258
+ * type field: the type node (slice_type for []User)
259
+ */
260
+ const findGoParamElementType = (iterableName, startNode, pos = 'last') => {
261
+ let current = startNode.parent;
262
+ while (current) {
263
+ if (GO_FUNCTION_NODE_TYPES.has(current.type)) {
264
+ const paramsNode = current.childForFieldName('parameters');
265
+ if (paramsNode) {
266
+ for (let i = 0; i < paramsNode.namedChildCount; i++) {
267
+ const paramDecl = paramsNode.namedChild(i);
268
+ if (!paramDecl || paramDecl.type !== 'parameter_declaration')
269
+ continue;
270
+ // parameter_declaration: name type — name field is the identifier
271
+ const nameNode = paramDecl.childForFieldName('name');
272
+ if (nameNode?.text === iterableName) {
273
+ const typeNode = paramDecl.childForFieldName('type');
274
+ if (typeNode)
275
+ return extractGoElementTypeFromTypeNode(typeNode, pos);
276
+ }
277
+ }
278
+ }
279
+ break;
280
+ }
281
+ current = current.parent;
282
+ }
283
+ return undefined;
284
+ };
285
+ /**
286
+ * Go: for _, user := range users where users has a known slice type.
287
+ *
288
+ * Go uses a single `for_statement` node for all for-loop forms. We detect
289
+ * range-based loops by looking for a `range_clause` child node. C-style for
290
+ * loops (with `for_clause`) and infinite loops (no clause) are ignored.
291
+ *
292
+ * Tier 1c: resolves the element type via three strategies in priority order:
293
+ * 1. declarationTypeNodes — raw type annotation AST node
294
+ * 2. scopeEnv string — extractElementTypeFromString on the stored type
295
+ * 3. AST walk — walks up to the enclosing function's parameters to read []User directly
296
+ * For `_, user := range users`, the loop variable is the second identifier in
297
+ * the `left` expression_list (index is discarded, value is the element).
298
+ */
299
+ const extractForLoopBinding = (node, { scopeEnv, declarationTypeNodes, scope, returnTypeLookup }) => {
300
+ if (node.type !== 'for_statement')
301
+ return;
302
+ // Find the range_clause child — this distinguishes range loops from other for forms.
303
+ let rangeClause = null;
304
+ for (let i = 0; i < node.namedChildCount; i++) {
305
+ const child = node.namedChild(i);
306
+ if (child?.type === 'range_clause') {
307
+ rangeClause = child;
308
+ break;
309
+ }
310
+ }
311
+ if (!rangeClause)
312
+ return;
313
+ // The iterable is the `right` field of the range_clause.
314
+ const rightNode = rangeClause.childForFieldName('right');
315
+ let iterableName;
316
+ let callExprElementType;
317
+ if (rightNode?.type === 'identifier') {
318
+ iterableName = rightNode.text;
319
+ }
320
+ else if (rightNode?.type === 'selector_expression') {
321
+ const field = rightNode.childForFieldName('field');
322
+ if (field)
323
+ iterableName = field.text;
324
+ }
325
+ else if (rightNode?.type === 'call_expression') {
326
+ // Range over a call result: `for _, v := range getItems()` or `for _, v := range repo.All()`
327
+ const funcNode = rightNode.childForFieldName('function');
328
+ let callee;
329
+ if (funcNode?.type === 'identifier') {
330
+ callee = funcNode.text;
331
+ }
332
+ else if (funcNode?.type === 'selector_expression') {
333
+ const field = funcNode.childForFieldName('field');
334
+ if (field)
335
+ callee = field.text;
336
+ }
337
+ if (callee) {
338
+ const rawReturn = returnTypeLookup.lookupRawReturnType(callee);
339
+ if (rawReturn)
340
+ callExprElementType = extractElementTypeFromString(rawReturn);
341
+ }
342
+ }
343
+ if (!iterableName && !callExprElementType)
344
+ return;
345
+ let elementType;
346
+ if (callExprElementType) {
347
+ elementType = callExprElementType;
348
+ }
349
+ else {
350
+ const containerTypeName = scopeEnv.get(iterableName);
351
+ const typeArgPos = methodToTypeArgPosition(undefined, containerTypeName);
352
+ elementType = resolveIterableElementType(iterableName, node, scopeEnv, declarationTypeNodes, scope, extractGoElementTypeFromTypeNode, findGoParamElementType, typeArgPos);
353
+ }
354
+ if (!elementType)
355
+ return;
356
+ // The loop variable(s) are in the `left` field.
357
+ // Go range semantics:
358
+ // Slice/Array/String: single-var → INDEX (int); two-var → (index, element)
359
+ // Map: single-var → KEY; two-var → (key, value)
360
+ // Channel: single-var → ELEMENT (channels have no index)
361
+ const leftNode = rangeClause.childForFieldName('left');
362
+ if (!leftNode)
363
+ return;
364
+ let loopVarNode = null;
365
+ if (leftNode.type === 'expression_list') {
366
+ if (leftNode.namedChildCount >= 2) {
367
+ // Two-var form: `_, user` or `i, user` — second variable gets element/value type
368
+ loopVarNode = leftNode.namedChild(1);
369
+ }
370
+ else {
371
+ // Single-var in expression_list — yields INDEX for slices/maps, ELEMENT for channels.
372
+ // For call-expression iterables (iterableName undefined), conservative: treat as non-channel.
373
+ // Channels are rarely returned from function calls, and even if they were, skipping here
374
+ // just means we miss a binding rather than create an incorrect one.
375
+ if (iterableName && isChannelType(iterableName, scopeEnv, declarationTypeNodes, scope)) {
376
+ loopVarNode = leftNode.namedChild(0);
377
+ }
378
+ else {
379
+ return; // index-only range on slice/map — skip
380
+ }
381
+ }
382
+ }
383
+ else {
384
+ // Plain identifier (single-var form without expression_list)
385
+ // For call-expression iterables (iterableName undefined), conservative: treat as non-channel.
386
+ // Channels are rarely returned from function calls, and even if they were, skipping here
387
+ // just means we miss a binding rather than create an incorrect one.
388
+ if (iterableName && isChannelType(iterableName, scopeEnv, declarationTypeNodes, scope)) {
389
+ loopVarNode = leftNode;
390
+ }
391
+ else {
392
+ return; // index-only range on slice/map — skip
393
+ }
394
+ }
395
+ if (!loopVarNode)
396
+ return;
397
+ // Skip the blank identifier `_`
398
+ if (loopVarNode.text === '_')
399
+ return;
400
+ const loopVarName = extractVarName(loopVarNode);
401
+ if (loopVarName)
402
+ scopeEnv.set(loopVarName, elementType);
403
+ };
404
+ /** Go: alias := u (short_var_declaration) or var b = u (var_spec) */
405
+ const extractPendingAssignment = (node, scopeEnv) => {
406
+ if (node.type === 'short_var_declaration') {
407
+ const left = node.childForFieldName('left');
408
+ const right = node.childForFieldName('right');
409
+ if (!left || !right)
410
+ return undefined;
411
+ const lhsNode = left.type === 'expression_list' ? left.firstNamedChild : left;
412
+ const rhsNode = right.type === 'expression_list' ? right.firstNamedChild : right;
413
+ if (!lhsNode || !rhsNode)
414
+ return undefined;
415
+ if (lhsNode.type !== 'identifier')
416
+ return undefined;
417
+ const lhs = lhsNode.text;
418
+ if (scopeEnv.has(lhs))
419
+ return undefined;
420
+ if (rhsNode.type === 'identifier')
421
+ return { kind: 'copy', lhs, rhs: rhsNode.text };
422
+ return undefined;
423
+ }
424
+ if (node.type === 'var_spec' || node.type === 'var_declaration') {
425
+ // var_declaration contains var_spec children; var_spec has name + expression_list value
426
+ const specs = [];
427
+ if (node.type === 'var_declaration') {
428
+ for (let i = 0; i < node.namedChildCount; i++) {
429
+ const c = node.namedChild(i);
430
+ if (c?.type === 'var_spec')
431
+ specs.push(c);
432
+ }
433
+ }
434
+ else {
435
+ specs.push(node);
436
+ }
437
+ for (const spec of specs) {
438
+ const nameNode = spec.childForFieldName('name');
439
+ if (!nameNode || nameNode.type !== 'identifier')
440
+ continue;
441
+ const lhs = nameNode.text;
442
+ if (scopeEnv.has(lhs))
443
+ continue;
444
+ // Check if the last named child is a bare identifier (no type annotation between name and value)
445
+ let exprList = null;
446
+ for (let i = 0; i < spec.childCount; i++) {
447
+ if (spec.child(i)?.type === 'expression_list') {
448
+ exprList = spec.child(i);
449
+ break;
450
+ }
451
+ }
452
+ const rhsNode = exprList?.firstNamedChild;
453
+ if (rhsNode?.type === 'identifier')
454
+ return { kind: 'copy', lhs, rhs: rhsNode.text };
455
+ }
456
+ }
457
+ return undefined;
458
+ };
459
+ export const typeConfig = {
460
+ declarationNodeTypes: DECLARATION_NODE_TYPES,
461
+ forLoopNodeTypes: FOR_LOOP_NODE_TYPES,
462
+ extractDeclaration,
463
+ extractParameter,
464
+ scanConstructorBinding,
465
+ extractForLoopBinding,
466
+ extractPendingAssignment,
467
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Per-language type extraction configurations.
3
+ * Assembled here into a dispatch map keyed by SupportedLanguages.
4
+ */
5
+ import type { LanguageTypeConfig } from './types.js';
6
+ export declare const typeConfigs: {
7
+ javascript: LanguageTypeConfig;
8
+ typescript: LanguageTypeConfig;
9
+ java: LanguageTypeConfig;
10
+ kotlin: LanguageTypeConfig;
11
+ csharp: LanguageTypeConfig;
12
+ go: LanguageTypeConfig;
13
+ rust: LanguageTypeConfig;
14
+ python: LanguageTypeConfig;
15
+ swift: LanguageTypeConfig;
16
+ c: LanguageTypeConfig;
17
+ cpp: LanguageTypeConfig;
18
+ php: LanguageTypeConfig;
19
+ ruby: LanguageTypeConfig;
20
+ };
21
+ export type { LanguageTypeConfig, TypeBindingExtractor, ParameterExtractor, ConstructorBindingScanner, ForLoopExtractor, PendingAssignmentExtractor, PatternBindingExtractor, } from './types.js';
22
+ export { TYPED_PARAMETER_TYPES, extractSimpleTypeName, extractGenericTypeArgs, extractVarName, findChildByType, extractRubyConstructorAssignment } from './shared.js';
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Per-language type extraction configurations.
3
+ * Assembled here into a dispatch map keyed by SupportedLanguages.
4
+ */
5
+ import { SupportedLanguages } from '../../../config/supported-languages.js';
6
+ import { typeConfig as typescriptConfig } from './typescript.js';
7
+ import { javaTypeConfig, kotlinTypeConfig } from './jvm.js';
8
+ import { typeConfig as csharpConfig } from './csharp.js';
9
+ import { typeConfig as goConfig } from './go.js';
10
+ import { typeConfig as rustConfig } from './rust.js';
11
+ import { typeConfig as pythonConfig } from './python.js';
12
+ import { typeConfig as swiftConfig } from './swift.js';
13
+ import { typeConfig as cCppConfig } from './c-cpp.js';
14
+ import { typeConfig as phpConfig } from './php.js';
15
+ import { typeConfig as rubyConfig } from './ruby.js';
16
+ export const typeConfigs = {
17
+ [SupportedLanguages.JavaScript]: typescriptConfig,
18
+ [SupportedLanguages.TypeScript]: typescriptConfig,
19
+ [SupportedLanguages.Java]: javaTypeConfig,
20
+ [SupportedLanguages.Kotlin]: kotlinTypeConfig,
21
+ [SupportedLanguages.CSharp]: csharpConfig,
22
+ [SupportedLanguages.Go]: goConfig,
23
+ [SupportedLanguages.Rust]: rustConfig,
24
+ [SupportedLanguages.Python]: pythonConfig,
25
+ [SupportedLanguages.Swift]: swiftConfig,
26
+ [SupportedLanguages.C]: cCppConfig,
27
+ [SupportedLanguages.CPlusPlus]: cCppConfig,
28
+ [SupportedLanguages.PHP]: phpConfig,
29
+ [SupportedLanguages.Ruby]: rubyConfig,
30
+ };
31
+ export { TYPED_PARAMETER_TYPES, extractSimpleTypeName, extractGenericTypeArgs, extractVarName, findChildByType, extractRubyConstructorAssignment } from './shared.js';
@@ -0,0 +1,3 @@
1
+ import type { LanguageTypeConfig } from './types.js';
2
+ export declare const javaTypeConfig: LanguageTypeConfig;
3
+ export declare const kotlinTypeConfig: LanguageTypeConfig;