@openrewrite/rewrite 8.62.3 → 8.62.5

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 (170) hide show
  1. package/dist/execution.d.ts.map +1 -1
  2. package/dist/execution.js.map +1 -1
  3. package/dist/java/rpc.d.ts +1 -0
  4. package/dist/java/rpc.d.ts.map +1 -1
  5. package/dist/java/rpc.js +81 -0
  6. package/dist/java/rpc.js.map +1 -1
  7. package/dist/java/tree.d.ts +12 -6
  8. package/dist/java/tree.d.ts.map +1 -1
  9. package/dist/java/tree.js +12 -92
  10. package/dist/java/tree.js.map +1 -1
  11. package/dist/java/type.d.ts +2 -0
  12. package/dist/java/type.d.ts.map +1 -1
  13. package/dist/java/type.js +12 -0
  14. package/dist/java/type.js.map +1 -1
  15. package/dist/java/visitor.d.ts +12 -4
  16. package/dist/java/visitor.d.ts.map +1 -1
  17. package/dist/java/visitor.js +23 -1
  18. package/dist/java/visitor.js.map +1 -1
  19. package/dist/javascript/format.d.ts +2 -2
  20. package/dist/javascript/format.d.ts.map +1 -1
  21. package/dist/javascript/format.js.map +1 -1
  22. package/dist/javascript/index.d.ts +3 -0
  23. package/dist/javascript/index.d.ts.map +1 -1
  24. package/dist/javascript/index.js +3 -0
  25. package/dist/javascript/index.js.map +1 -1
  26. package/dist/javascript/method-matcher.d.ts +16 -0
  27. package/dist/javascript/method-matcher.d.ts.map +1 -0
  28. package/dist/javascript/method-matcher.js +222 -0
  29. package/dist/javascript/method-matcher.js.map +1 -0
  30. package/dist/javascript/parser.d.ts +1 -1
  31. package/dist/javascript/parser.d.ts.map +1 -1
  32. package/dist/javascript/parser.js +27 -5
  33. package/dist/javascript/parser.js.map +1 -1
  34. package/dist/javascript/preconditions.d.ts +6 -0
  35. package/dist/javascript/preconditions.d.ts.map +1 -0
  36. package/dist/javascript/preconditions.js +58 -0
  37. package/dist/javascript/preconditions.js.map +1 -0
  38. package/dist/javascript/print.d.ts +2 -2
  39. package/dist/javascript/print.d.ts.map +1 -1
  40. package/dist/javascript/print.js.map +1 -1
  41. package/dist/javascript/remove-import.d.ts +56 -0
  42. package/dist/javascript/remove-import.d.ts.map +1 -0
  43. package/dist/javascript/remove-import.js +715 -0
  44. package/dist/javascript/remove-import.js.map +1 -0
  45. package/dist/javascript/rpc.js +3 -18
  46. package/dist/javascript/rpc.js.map +1 -1
  47. package/dist/javascript/search/index.d.ts +3 -0
  48. package/dist/javascript/search/index.d.ts.map +1 -0
  49. package/dist/javascript/search/index.js +19 -0
  50. package/dist/javascript/search/index.js.map +1 -0
  51. package/dist/javascript/search/uses-method.d.ts +8 -0
  52. package/dist/javascript/search/uses-method.d.ts.map +1 -0
  53. package/dist/javascript/search/uses-method.js +35 -0
  54. package/dist/javascript/search/uses-method.js.map +1 -0
  55. package/dist/javascript/search/uses-type.d.ts +8 -0
  56. package/dist/javascript/search/uses-type.d.ts.map +1 -0
  57. package/dist/javascript/search/uses-type.js +71 -0
  58. package/dist/javascript/search/uses-type.js.map +1 -0
  59. package/dist/javascript/templating.d.ts +1 -1
  60. package/dist/javascript/templating.d.ts.map +1 -1
  61. package/dist/javascript/templating.js +1 -1
  62. package/dist/javascript/templating.js.map +1 -1
  63. package/dist/javascript/tree.d.ts +3 -3
  64. package/dist/javascript/tree.d.ts.map +1 -1
  65. package/dist/javascript/tree.js +28 -0
  66. package/dist/javascript/tree.js.map +1 -1
  67. package/dist/javascript/type-mapping.d.ts +7 -18
  68. package/dist/javascript/type-mapping.d.ts.map +1 -1
  69. package/dist/javascript/type-mapping.js +290 -203
  70. package/dist/javascript/type-mapping.js.map +1 -1
  71. package/dist/javascript/visitor.d.ts +1 -1
  72. package/dist/javascript/visitor.d.ts.map +1 -1
  73. package/dist/javascript/visitor.js +1 -1
  74. package/dist/javascript/visitor.js.map +1 -1
  75. package/dist/json/print.js.map +1 -1
  76. package/dist/json/rpc.js +46 -17
  77. package/dist/json/rpc.js.map +1 -1
  78. package/dist/json/visitor.d.ts +2 -2
  79. package/dist/json/visitor.d.ts.map +1 -1
  80. package/dist/json/visitor.js.map +1 -1
  81. package/dist/print.d.ts +1 -0
  82. package/dist/print.d.ts.map +1 -1
  83. package/dist/print.js +6 -0
  84. package/dist/print.js.map +1 -1
  85. package/dist/rpc/queue.d.ts +15 -6
  86. package/dist/rpc/queue.d.ts.map +1 -1
  87. package/dist/rpc/queue.js +37 -13
  88. package/dist/rpc/queue.js.map +1 -1
  89. package/dist/rpc/request/generate.d.ts +4 -0
  90. package/dist/rpc/request/generate.d.ts.map +1 -1
  91. package/dist/rpc/request/generate.js +9 -4
  92. package/dist/rpc/request/generate.js.map +1 -1
  93. package/dist/rpc/request/get-object.d.ts +2 -2
  94. package/dist/rpc/request/get-object.d.ts.map +1 -1
  95. package/dist/rpc/request/get-object.js +4 -12
  96. package/dist/rpc/request/get-object.js.map +1 -1
  97. package/dist/rpc/request/parse.d.ts.map +1 -1
  98. package/dist/rpc/request/parse.js.map +1 -1
  99. package/dist/rpc/request/print.d.ts +1 -1
  100. package/dist/rpc/request/print.d.ts.map +1 -1
  101. package/dist/rpc/request/print.js +1 -1
  102. package/dist/rpc/request/print.js.map +1 -1
  103. package/dist/rpc/request/visit.d.ts +3 -2
  104. package/dist/rpc/request/visit.d.ts.map +1 -1
  105. package/dist/rpc/request/visit.js +5 -4
  106. package/dist/rpc/request/visit.js.map +1 -1
  107. package/dist/rpc/rewrite-rpc.d.ts +4 -4
  108. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  109. package/dist/rpc/rewrite-rpc.js +16 -17
  110. package/dist/rpc/rewrite-rpc.js.map +1 -1
  111. package/dist/search/index.d.ts +2 -0
  112. package/dist/search/index.d.ts.map +1 -0
  113. package/dist/search/index.js +18 -0
  114. package/dist/search/index.js.map +1 -0
  115. package/dist/search/is-source-file.d.ts +8 -0
  116. package/dist/search/is-source-file.d.ts.map +1 -0
  117. package/dist/search/is-source-file.js +70 -0
  118. package/dist/search/is-source-file.js.map +1 -0
  119. package/dist/test/rewrite-test.d.ts.map +1 -1
  120. package/dist/test/rewrite-test.js +3 -0
  121. package/dist/test/rewrite-test.js.map +1 -1
  122. package/dist/text/rpc.js +37 -40
  123. package/dist/text/rpc.js.map +1 -1
  124. package/dist/util.d.ts +1 -0
  125. package/dist/util.d.ts.map +1 -1
  126. package/dist/util.js +13 -0
  127. package/dist/util.js.map +1 -1
  128. package/dist/version.txt +1 -1
  129. package/dist/visitor.d.ts +1 -1
  130. package/dist/visitor.d.ts.map +1 -1
  131. package/dist/visitor.js +3 -2
  132. package/dist/visitor.js.map +1 -1
  133. package/package.json +3 -1
  134. package/src/execution.ts +0 -2
  135. package/src/java/rpc.ts +68 -0
  136. package/src/java/tree.ts +20 -76
  137. package/src/java/type.ts +14 -0
  138. package/src/java/visitor.ts +32 -12
  139. package/src/javascript/format.ts +2 -2
  140. package/src/javascript/index.ts +4 -0
  141. package/src/javascript/method-matcher.ts +250 -0
  142. package/src/javascript/parser.ts +20 -6
  143. package/src/javascript/preconditions.ts +40 -0
  144. package/src/javascript/print.ts +3 -3
  145. package/src/javascript/remove-import.ts +780 -0
  146. package/src/javascript/rpc.ts +6 -19
  147. package/src/javascript/search/index.ts +2 -0
  148. package/src/javascript/search/uses-method.ts +21 -0
  149. package/src/javascript/search/uses-type.ts +27 -0
  150. package/src/javascript/templating.ts +4 -3
  151. package/src/javascript/tree.ts +47 -3
  152. package/src/javascript/type-mapping.ts +320 -214
  153. package/src/javascript/visitor.ts +126 -126
  154. package/src/json/print.ts +1 -1
  155. package/src/json/rpc.ts +40 -19
  156. package/src/json/visitor.ts +2 -2
  157. package/src/print.ts +9 -3
  158. package/src/rpc/queue.ts +36 -12
  159. package/src/rpc/request/generate.ts +18 -6
  160. package/src/rpc/request/get-object.ts +6 -13
  161. package/src/rpc/request/parse.ts +1 -1
  162. package/src/rpc/request/print.ts +2 -2
  163. package/src/rpc/request/visit.ts +6 -5
  164. package/src/rpc/rewrite-rpc.ts +22 -21
  165. package/src/search/index.ts +1 -0
  166. package/src/search/is-source-file.ts +26 -0
  167. package/src/test/rewrite-test.ts +5 -2
  168. package/src/text/rpc.ts +33 -37
  169. package/src/util.ts +19 -4
  170. package/src/visitor.ts +3 -3
@@ -30,16 +30,9 @@ class NonDraftableType {
30
30
  }
31
31
  }
32
32
  _a = immer_1.immerable;
33
- const builtInTypes = new Set([
34
- 'Array', 'Object', 'Function', 'String', 'Number', 'Boolean',
35
- 'Date', 'RegExp', 'Error', 'Promise', 'Map', 'Set', 'WeakMap',
36
- 'WeakSet', 'Symbol', 'BigInt', 'HTMLElement', 'Document',
37
- 'Window', 'Console', 'JSON', 'Math', 'Reflect', 'Proxy'
38
- ]);
39
33
  class JavaScriptTypeMapping {
40
- constructor(checker, projectRoot = process.cwd()) {
34
+ constructor(checker) {
41
35
  this.checker = checker;
42
- this.projectRoot = projectRoot;
43
36
  this.typeCache = new Map();
44
37
  this.regExpSymbol = checker.resolveName("RegExp", undefined, typescript_1.default.SymbolFlags.Type, false);
45
38
  }
@@ -60,14 +53,8 @@ class JavaScriptTypeMapping {
60
53
  if (existing) {
61
54
  return existing;
62
55
  }
63
- // Check if this is an array type BEFORE checking for classes
64
- // TypeScript represents Array<T> as a reference to the Array interface
65
- if (this.checker.isArrayType(type)) {
66
- const arrayType = this.createArrayType(type);
67
- this.typeCache.set(signature, arrayType);
68
- return arrayType;
69
- }
70
- // Check for class/interface/enum types (but not arrays)
56
+ // Check for class/interface/enum types (including arrays)
57
+ // Arrays in JavaScript are objects with methods, so we treat them as class types
71
58
  const symbol = (_b = type.getSymbol) === null || _b === void 0 ? void 0 : _b.call(type);
72
59
  if (symbol) {
73
60
  if (symbol.flags & (typescript_1.default.SymbolFlags.Class | typescript_1.default.SymbolFlags.Interface | typescript_1.default.SymbolFlags.Enum | typescript_1.default.SymbolFlags.TypeAlias)) {
@@ -120,7 +107,7 @@ class JavaScriptTypeMapping {
120
107
  }
121
108
  primitiveType(node) {
122
109
  const type = this.type(node);
123
- if (java_1.Type.isClass(type) && type.fullyQualifiedName === 'lib.RegExp') {
110
+ if (java_1.Type.isClass(type) && type.fullyQualifiedName === 'RegExp') {
124
111
  return java_1.Type.Primitive.String;
125
112
  }
126
113
  return java_1.Type.isPrimitive(type) ? type : java_1.Type.Primitive.None;
@@ -136,6 +123,36 @@ class JavaScriptTypeMapping {
136
123
  }
137
124
  return undefined;
138
125
  }
126
+ /**
127
+ * Helper to create a Type.Method object from common parameters
128
+ */
129
+ createMethodType(signature, node, declaringType, name, declaredFormalTypeNames = []) {
130
+ const returnType = signature.getReturnType();
131
+ const parameters = signature.getParameters();
132
+ const parameterTypes = [];
133
+ const parameterNames = [];
134
+ for (const param of parameters) {
135
+ parameterNames.push(param.getName());
136
+ const paramType = this.checker.getTypeOfSymbolAtLocation(param, node);
137
+ parameterTypes.push(this.getType(paramType));
138
+ }
139
+ // Create the Type.Method object
140
+ return Object.assign(new NonDraftableType(), {
141
+ kind: java_1.Type.Kind.Method,
142
+ declaringType: declaringType,
143
+ name: name,
144
+ returnType: this.getType(returnType),
145
+ parameterNames: parameterNames,
146
+ parameterTypes: parameterTypes,
147
+ thrownExceptions: [], // JavaScript doesn't have checked exceptions
148
+ annotations: [],
149
+ defaultValue: undefined,
150
+ declaredFormalTypeNames: declaredFormalTypeNames,
151
+ toJSON: function () {
152
+ return java_1.Type.signature(this);
153
+ }
154
+ });
155
+ }
139
156
  methodType(node) {
140
157
  let signature;
141
158
  let methodName;
@@ -148,29 +165,136 @@ class JavaScriptTypeMapping {
148
165
  if (!signature) {
149
166
  return undefined;
150
167
  }
151
- const symbol = this.checker.getSymbolAtLocation(node.expression);
168
+ let symbol = this.checker.getSymbolAtLocation(node.expression);
169
+ if (!symbol && typescript_1.default.isPropertyAccessExpression(node.expression)) {
170
+ // For property access expressions where we couldn't get a symbol,
171
+ // try to get the symbol from the signature's declaration
172
+ const declaration = signature === null || signature === void 0 ? void 0 : signature.getDeclaration();
173
+ if (declaration) {
174
+ symbol = this.checker.getSymbolAtLocation(declaration);
175
+ }
176
+ // If still no symbol but we have a signature, we can proceed with limited info
177
+ if (!symbol && signature) {
178
+ // For cases like util.isArray where the module is 'any' type
179
+ // We'll construct a basic method type from the signature
180
+ methodName = node.expression.name.getText();
181
+ // When there's no symbol but we have a signature, we need to work harder
182
+ // to find the declaring type. This happens with CommonJS require() calls
183
+ // where the module is typed as 'any' but methods still have signatures
184
+ // Try to trace back through the AST to find the require() call
185
+ let inferredDeclaringType;
186
+ const objExpr = node.expression.expression;
187
+ if (typescript_1.default.isIdentifier(objExpr)) {
188
+ // Look for the variable declaration that assigns the require() result
189
+ const objSymbol = this.checker.getSymbolAtLocation(objExpr);
190
+ if (objSymbol && objSymbol.valueDeclaration) {
191
+ const valueDecl = objSymbol.valueDeclaration;
192
+ if (typescript_1.default.isVariableDeclaration(valueDecl) && valueDecl.initializer) {
193
+ // Check if it's a require() call
194
+ if (typescript_1.default.isCallExpression(valueDecl.initializer)) {
195
+ const callExpr = valueDecl.initializer;
196
+ if (typescript_1.default.isIdentifier(callExpr.expression) &&
197
+ callExpr.expression.getText() === 'require' &&
198
+ callExpr.arguments.length > 0) {
199
+ // Extract the module name from require('module-name')
200
+ const moduleArg = callExpr.arguments[0];
201
+ if (typescript_1.default.isStringLiteral(moduleArg)) {
202
+ const moduleName = moduleArg.text;
203
+ inferredDeclaringType = {
204
+ kind: java_1.Type.Kind.Class,
205
+ fullyQualifiedName: moduleName
206
+ };
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ // Use the inferred type or fall back to unknown
214
+ declaringType = inferredDeclaringType || java_1.Type.unknownType;
215
+ // Create the method type using the helper
216
+ return this.createMethodType(signature, node, declaringType, methodName);
217
+ }
218
+ }
152
219
  if (!symbol) {
153
220
  return undefined;
154
221
  }
155
222
  // Get the method name
156
223
  if (typescript_1.default.isPropertyAccessExpression(node.expression)) {
157
224
  methodName = node.expression.name.getText();
225
+ // Check if the object is an imported symbol
226
+ const objSymbol = this.checker.getSymbolAtLocation(node.expression.expression);
227
+ let isImport = false;
228
+ if (objSymbol) {
229
+ // Only call getAliasedSymbol if the symbol is actually an alias
230
+ if (objSymbol.flags & typescript_1.default.SymbolFlags.Alias) {
231
+ const aliasedSymbol = this.checker.getAliasedSymbol(objSymbol);
232
+ isImport = aliasedSymbol && aliasedSymbol !== objSymbol;
233
+ }
234
+ }
158
235
  const exprType = this.checker.getTypeAtLocation(node.expression.expression);
159
236
  const mappedType = this.getType(exprType);
160
- // For string methods like 'hello'.split(), ensure we have a proper declaring type
161
- if (!mappedType || mappedType.kind !== java_1.Type.Kind.Class) {
162
- // If the expression type is a primitive string, use lib.String as declaring type
237
+ // Handle different types
238
+ if (mappedType && mappedType.kind === java_1.Type.Kind.Class) {
239
+ // Update the declaring type with the corrected FQN
240
+ if (isImport && objSymbol) {
241
+ const importName = objSymbol.getName();
242
+ const origFqn = mappedType.fullyQualifiedName;
243
+ const lastDot = origFqn.lastIndexOf('.');
244
+ if (lastDot > 0) {
245
+ const typeName = origFqn.substring(lastDot + 1);
246
+ declaringType = {
247
+ kind: java_1.Type.Kind.Class,
248
+ fullyQualifiedName: `${importName}.${typeName}`
249
+ };
250
+ }
251
+ else {
252
+ declaringType = mappedType;
253
+ }
254
+ }
255
+ else {
256
+ declaringType = mappedType;
257
+ }
258
+ }
259
+ else {
260
+ // Handle primitive types and other non-class types
261
+ if (mappedType) {
262
+ if (mappedType.keyword === 'String') {
263
+ declaringType = {
264
+ kind: java_1.Type.Kind.Class,
265
+ fullyQualifiedName: 'String'
266
+ };
267
+ }
268
+ else if (mappedType.keyword === 'Number') {
269
+ declaringType = {
270
+ kind: java_1.Type.Kind.Class,
271
+ fullyQualifiedName: 'Number'
272
+ };
273
+ }
274
+ else {
275
+ // Fallback for other types
276
+ declaringType = mappedType;
277
+ }
278
+ }
279
+ else {
280
+ // Default to unknown if we can't determine the type
281
+ declaringType = java_1.Type.unknownType;
282
+ }
283
+ }
284
+ // For string methods like 'hello'.split(), ensure we have a proper declaring type for primitives
285
+ if (!isImport && declaringType === java_1.Type.unknownType) {
286
+ // If the expression type is a primitive string, use String as declaring type
163
287
  const typeString = this.checker.typeToString(exprType);
164
288
  if (typeString === 'string' || exprType.flags & typescript_1.default.TypeFlags.String || exprType.flags & typescript_1.default.TypeFlags.StringLiteral) {
165
289
  declaringType = {
166
290
  kind: java_1.Type.Kind.Class,
167
- fullyQualifiedName: 'lib.String'
291
+ fullyQualifiedName: 'string'
168
292
  };
169
293
  }
170
294
  else if (typeString === 'number' || exprType.flags & typescript_1.default.TypeFlags.Number || exprType.flags & typescript_1.default.TypeFlags.NumberLiteral) {
171
295
  declaringType = {
172
296
  kind: java_1.Type.Kind.Class,
173
- fullyQualifiedName: 'lib.Number'
297
+ fullyQualifiedName: 'number'
174
298
  };
175
299
  }
176
300
  else {
@@ -178,44 +302,85 @@ class JavaScriptTypeMapping {
178
302
  declaringType = java_1.Type.unknownType;
179
303
  }
180
304
  }
181
- else {
182
- declaringType = mappedType;
183
- }
184
305
  }
185
306
  else if (typescript_1.default.isIdentifier(node.expression)) {
186
307
  methodName = node.expression.getText();
187
- // For standalone functions, we need to determine the appropriate declaring type
188
- const exprType = this.checker.getTypeAtLocation(node.expression);
189
- const funcType = this.getType(exprType);
190
- if (funcType && funcType.kind === java_1.Type.Kind.Class) {
191
- const fqn = funcType.fullyQualifiedName;
192
- const lastDot = fqn.lastIndexOf('.');
193
- if (lastDot > 0) {
194
- // For functions from modules, use the module part as declaring type
195
- // Examples:
196
- // - "node.assert" -> declaring type: "node"
197
- // - "@types/lodash.map" -> declaring type: "@types/lodash"
198
- // - "@types/express.express" -> declaring type: "@types/express"
308
+ // Check if this is an import first
309
+ const symbol = this.checker.getSymbolAtLocation(node.expression);
310
+ let moduleSpecifier;
311
+ if (symbol) {
312
+ // Check if this is an aliased symbol (i.e., an import)
313
+ let aliasedSymbol;
314
+ if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
315
+ aliasedSymbol = this.checker.getAliasedSymbol(symbol);
316
+ }
317
+ // If getAliasedSymbol returns something different, it's an import
318
+ if (aliasedSymbol && aliasedSymbol !== symbol) {
319
+ // This is definitely an imported symbol
320
+ // Now find the import declaration to get the module specifier
321
+ if (symbol.declarations && symbol.declarations.length > 0) {
322
+ let importNode = symbol.declarations[0];
323
+ // Traverse up to find the ImportDeclaration
324
+ while (importNode && !typescript_1.default.isImportDeclaration(importNode)) {
325
+ importNode = importNode.parent;
326
+ }
327
+ if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
328
+ const importDeclNode = importNode;
329
+ if (typescript_1.default.isStringLiteral(importDeclNode.moduleSpecifier)) {
330
+ moduleSpecifier = importDeclNode.moduleSpecifier.text;
331
+ }
332
+ }
333
+ }
334
+ }
335
+ }
336
+ if (moduleSpecifier) {
337
+ // This is an imported function - use the module specifier as declaring type
338
+ if (moduleSpecifier.startsWith('node:')) {
339
+ // Node.js built-in module
199
340
  declaringType = {
200
341
  kind: java_1.Type.Kind.Class,
201
- fullyQualifiedName: fqn.substring(0, lastDot)
342
+ fullyQualifiedName: 'node'
202
343
  };
344
+ methodName = moduleSpecifier.substring(5); // Remove 'node:' prefix
203
345
  }
204
346
  else {
205
- // No dots in the name - the type IS the module itself
206
- // This handles single-name modules like "axios", "lodash" etc.
207
- declaringType = funcType;
347
+ // Regular module import
348
+ declaringType = {
349
+ kind: java_1.Type.Kind.Class,
350
+ fullyQualifiedName: moduleSpecifier
351
+ };
352
+ methodName = '<default>';
208
353
  }
209
354
  }
210
355
  else {
211
- // Try to use the symbol's parent or module
212
- const parent = symbol.parent;
213
- if (parent) {
214
- const parentType = this.checker.getDeclaredTypeOfSymbol(parent);
215
- declaringType = this.getType(parentType);
356
+ // Fall back to the original logic for non-imported functions
357
+ const exprType = this.checker.getTypeAtLocation(node.expression);
358
+ const funcType = this.getType(exprType);
359
+ if (funcType && funcType.kind === java_1.Type.Kind.Class) {
360
+ const fqn = funcType.fullyQualifiedName;
361
+ const lastDot = fqn.lastIndexOf('.');
362
+ if (lastDot > 0) {
363
+ // For functions from modules, use the module part as declaring type
364
+ declaringType = {
365
+ kind: java_1.Type.Kind.Class,
366
+ fullyQualifiedName: fqn.substring(0, lastDot)
367
+ };
368
+ }
369
+ else {
370
+ // No dots in the name - the type IS the module itself
371
+ declaringType = funcType;
372
+ }
216
373
  }
217
374
  else {
218
- declaringType = java_1.Type.unknownType;
375
+ // Try to use the symbol's parent or module
376
+ const parent = symbol.parent;
377
+ if (parent) {
378
+ const parentType = this.checker.getDeclaredTypeOfSymbol(parent);
379
+ declaringType = this.getType(parentType);
380
+ }
381
+ else {
382
+ declaringType = java_1.Type.unknownType;
383
+ }
219
384
  }
220
385
  }
221
386
  }
@@ -277,140 +442,96 @@ class JavaScriptTypeMapping {
277
442
  // For other node types, return undefined
278
443
  return undefined;
279
444
  }
280
- // Common logic for all method types
281
- const returnType = signature.getReturnType();
282
- const parameters = signature.getParameters();
283
- const parameterTypes = [];
284
- const parameterNames = [];
285
- for (const param of parameters) {
286
- parameterNames.push(param.getName());
287
- const paramType = this.checker.getTypeOfSymbolAtLocation(param, node);
288
- parameterTypes.push(this.getType(paramType));
289
- }
290
- // Create the Type.Method object
291
- return Object.assign(new NonDraftableType(), {
292
- kind: java_1.Type.Kind.Method,
293
- declaringType: declaringType,
294
- name: methodName,
295
- returnType: this.getType(returnType),
296
- parameterNames: parameterNames,
297
- parameterTypes: parameterTypes,
298
- thrownExceptions: [], // JavaScript doesn't have checked exceptions
299
- annotations: [],
300
- defaultValue: undefined,
301
- declaredFormalTypeNames: declaredFormalTypeNames,
302
- toJSON: function () {
303
- return java_1.Type.signature(this);
304
- }
305
- });
306
- }
307
- /**
308
- * Create a JavaType.Array from a TypeScript array type
309
- */
310
- createArrayType(type) {
311
- // Get the element type (type argument of Array<T>)
312
- const typeArgs = this.checker.getTypeArguments(type);
313
- const elemType = typeArgs.length > 0 ? this.getType(typeArgs[0]) : java_1.Type.unknownType;
314
- return Object.assign(new NonDraftableType(), {
315
- kind: java_1.Type.Kind.Array,
316
- elemType: elemType,
317
- annotations: [],
318
- toJSON: function () {
319
- return java_1.Type.signature(this);
320
- }
321
- });
445
+ // Create the method type using the helper
446
+ return this.createMethodType(signature, node, declaringType, methodName, declaredFormalTypeNames);
322
447
  }
323
448
  /**
324
449
  * Get the fully qualified name for a TypeScript type.
325
- * Format: "module-specifier.TypeName" (e.g., "@mui/material.Button", "src/components/Button.Button")
450
+ * Uses TypeScript's built-in resolution which properly handles things like:
451
+ * - React.Component (not @types/react.Component)
452
+ * - _.LoDashStatic (not @types/lodash.LoDashStatic)
326
453
  */
327
454
  getFullyQualifiedName(type) {
328
- var _b, _c;
455
+ var _b;
329
456
  const symbol = (_b = type.getSymbol) === null || _b === void 0 ? void 0 : _b.call(type);
330
457
  if (!symbol) {
331
458
  return "unknown";
332
459
  }
333
- const typeName = symbol.getName();
334
- const declaration = symbol.valueDeclaration || ((_c = symbol.declarations) === null || _c === void 0 ? void 0 : _c[0]);
335
- if (!declaration) {
336
- // No declaration - might be a built-in or synthetic type
337
- if (builtInTypes.has(typeName)) {
338
- return `lib.${typeName}`;
339
- }
340
- return typeName;
341
- }
342
- const sourceFile = declaration.getSourceFile();
343
- const fileName = sourceFile.fileName;
344
- // Check if this is a test file (snowflake ID as filename)
345
- // Test files are generated with numeric IDs like "672087069480189952.ts"
346
- if (/^\d+\.(ts|tsx|js|jsx)$/.test(fileName)) {
347
- // For test files, just return the type name without module prefix
348
- return typeName;
349
- }
350
- // Check if this is from TypeScript's lib files (lib.d.ts, lib.dom.d.ts, etc.)
351
- if (fileName.includes("/typescript/lib/lib.") || fileName.includes("\\typescript\\lib\\lib.")) {
352
- return `lib.${typeName}`;
353
- }
354
- // Check if this is from an external module (node_modules or .d.ts)
355
- if (sourceFile.isDeclarationFile || fileName.includes("node_modules")) {
356
- const packageName = this.extractPackageName(fileName);
357
- if (packageName) {
358
- // Special handling for @types/node - these are Node.js built-in modules
359
- // and should be mapped to "node.*" instead of "@types/node.*"
360
- if (packageName === "@types/node") {
361
- // Extract the module name from the file path
362
- // e.g., /node_modules/@types/node/assert.d.ts -> assert
363
- // e.g., /node_modules/@types/node/fs/promises.d.ts -> fs/promises
364
- const nodeMatch = fileName.match(/node_modules\/@types\/node\/([^.]+)\.d\.ts/);
365
- if (nodeMatch) {
366
- const modulePath = nodeMatch[1];
367
- // For default exports from Node modules, we want the module to be the "class"
368
- // But we still need to include the type name for proper identification
369
- if (typeName === "default" || typeName === modulePath) {
370
- // This is likely the default export, just use the module name
371
- return `node.${modulePath}`;
372
- }
373
- // For named exports, include both module and type name
374
- if (modulePath.includes('/')) {
375
- return `node.${modulePath.replace(/\//g, '.')}.${typeName}`;
460
+ // First, check if this symbol is an import/alias
461
+ // For imported types, we want to use the module specifier instead of the file path
462
+ if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
463
+ const aliasedSymbol = this.checker.getAliasedSymbol(symbol);
464
+ if (aliasedSymbol && aliasedSymbol !== symbol && symbol.declarations && symbol.declarations.length > 0) {
465
+ // Try to find the import declaration to get the module specifier
466
+ let importNode = symbol.declarations[0];
467
+ // Traverse up to find the ImportDeclaration or ImportSpecifier
468
+ while (importNode && importNode.parent && !typescript_1.default.isImportDeclaration(importNode) && !typescript_1.default.isImportSpecifier(importNode)) {
469
+ importNode = importNode.parent;
470
+ }
471
+ let moduleSpecifier;
472
+ if (importNode && typescript_1.default.isImportSpecifier(importNode)) {
473
+ // Named import like: import { ClipLoader } from 'react-spinners'
474
+ // ImportSpecifier -> NamedImports -> ImportClause -> ImportDeclaration
475
+ const namedImports = importNode.parent; // NamedImports
476
+ if (namedImports && typescript_1.default.isNamedImports(namedImports)) {
477
+ const importClause = namedImports.parent; // ImportClause
478
+ if (importClause && typescript_1.default.isImportClause(importClause)) {
479
+ const importDecl = importClause.parent; // ImportDeclaration
480
+ if (importDecl && typescript_1.default.isImportDeclaration(importDecl) && typescript_1.default.isStringLiteral(importDecl.moduleSpecifier)) {
481
+ moduleSpecifier = importDecl.moduleSpecifier.text;
482
+ }
376
483
  }
377
- return `node.${modulePath}.${typeName}`;
378
484
  }
379
- // Fallback for @types/node types that don't match the pattern
380
- return `node.${typeName}`;
381
485
  }
382
- return `${packageName}.${typeName}`;
486
+ else if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
487
+ // Default or namespace import
488
+ if (typescript_1.default.isStringLiteral(importNode.moduleSpecifier)) {
489
+ moduleSpecifier = importNode.moduleSpecifier.text;
490
+ }
491
+ }
492
+ if (moduleSpecifier) {
493
+ // Build the fully qualified name from module specifier + symbol name
494
+ const symbolName = symbol.getName();
495
+ return `${moduleSpecifier}.${symbolName}`;
496
+ }
383
497
  }
384
498
  }
385
- // For local files, use relative path from project root
386
- const relativePath = this.getRelativeModulePath(fileName);
387
- return `${relativePath}.${typeName}`;
388
- }
389
- /**
390
- * Extract package name from a node_modules path.
391
- * Examples:
392
- * - /path/to/project/node_modules/react/index.d.ts -> "react"
393
- * - /path/to/project/node_modules/@mui/material/Button/index.d.ts -> "@mui/material"
394
- */
395
- extractPackageName(fileName) {
396
- const match = fileName.match(/node_modules\/(@[^\/]+\/[^\/]+|[^\/]+)/);
397
- return match ? match[1] : null;
398
- }
399
- /**
400
- * Get relative module path from project root.
401
- * Removes file extension and uses forward slashes.
402
- */
403
- getRelativeModulePath(fileName) {
404
- // Remove project root and normalize path
405
- let relativePath = fileName;
406
- if (fileName.startsWith(this.projectRoot)) {
407
- relativePath = fileName.slice(this.projectRoot.length);
499
+ // Fall back to TypeScript's built-in getFullyQualifiedName
500
+ // This returns names with quotes that we need to clean up
501
+ // e.g., '"React"."Component"' -> 'React.Component'
502
+ const tsQualifiedName = this.checker.getFullyQualifiedName(symbol);
503
+ let cleanedName = tsQualifiedName.replace(/"/g, '');
504
+ // Check if this is a file path from node_modules (happens with some packages)
505
+ // TypeScript sometimes returns full paths instead of module names
506
+ if (cleanedName.includes('node_modules/')) {
507
+ // Extract the module name from the path
508
+ // Example: /private/var/.../node_modules/react-spinners/src/index.ClipLoader
509
+ // Should become: react-spinners.ClipLoader
510
+ const nodeModulesIndex = cleanedName.indexOf('node_modules/');
511
+ const afterNodeModules = cleanedName.substring(nodeModulesIndex + 'node_modules/'.length);
512
+ // Split by '/' to get parts of the path
513
+ const pathParts = afterNodeModules.split('/');
514
+ if (pathParts.length > 0) {
515
+ // First part is the package name (might be scoped like @types)
516
+ let packageName = pathParts[0];
517
+ // Handle scoped packages
518
+ if (packageName.startsWith('@') && pathParts.length > 1) {
519
+ packageName = `${packageName}/${pathParts[1]}`;
520
+ }
521
+ // Find the symbol name (everything after the last dot in the original cleaned name)
522
+ const lastDotIndex = cleanedName.lastIndexOf('.');
523
+ if (lastDotIndex > 0) {
524
+ const symbolName = cleanedName.substring(lastDotIndex + 1);
525
+ cleanedName = `${packageName}.${symbolName}`;
526
+ }
527
+ else {
528
+ cleanedName = packageName;
529
+ }
530
+ }
408
531
  }
409
- // Remove leading slash and file extension
410
- relativePath = relativePath.replace(/^\//, '').replace(/\.[^/.]+$/, '');
411
- // Convert backslashes to forward slashes (for Windows)
412
- relativePath = relativePath.replace(/\\/g, '/');
413
- return relativePath;
532
+ return cleanedName.endsWith('Constructor') ?
533
+ cleanedName.substring(0, cleanedName.length - 'Constructor'.length) :
534
+ cleanedName;
414
535
  }
415
536
  /**
416
537
  * Create an empty JavaType.Class shell from a TypeScript type.
@@ -418,42 +539,8 @@ class JavaScriptTypeMapping {
418
539
  */
419
540
  createEmptyClassType(type) {
420
541
  var _b;
421
- // Use our custom getFullyQualifiedName method for consistent naming
422
- let fullyQualifiedName = this.getFullyQualifiedName(type);
423
- // If getFullyQualifiedName returned unknown, fall back to TypeScript's method
424
- if (fullyQualifiedName === "unknown") {
425
- const symbol = type.symbol;
426
- fullyQualifiedName = symbol ? this.checker.getFullyQualifiedName(symbol) : `<anonymous>${this.checker.typeToString(type)}`;
427
- // Fix FQN for types from @types packages
428
- // TypeScript returns "_.LoDashStatic" but we want "@types/lodash.LoDashStatic"
429
- if (symbol && symbol.declarations && symbol.declarations.length > 0) {
430
- const sourceFile = symbol.declarations[0].getSourceFile();
431
- const fileName = sourceFile.fileName;
432
- // Check if this is from @types package
433
- const typesMatch = fileName.match(/node_modules\/@types\/([^/]+)/);
434
- if (typesMatch) {
435
- const packageName = typesMatch[1];
436
- // Special handling for @types/node - use "node" prefix instead
437
- if (packageName === "node") {
438
- // Extract the module name from the file path if possible
439
- const nodeMatch = fileName.match(/node_modules\/@types\/node\/([^.]+)\.d\.ts/);
440
- if (nodeMatch) {
441
- const modulePath = nodeMatch[1];
442
- // Replace the module specifier with node.module
443
- fullyQualifiedName = fullyQualifiedName.replace(/^[^.]+\./, `node.${modulePath}.`);
444
- }
445
- else {
446
- // Fallback: just use "node" prefix
447
- fullyQualifiedName = fullyQualifiedName.replace(/^[^.]+\./, `node.`);
448
- }
449
- }
450
- else {
451
- // Replace the module specifier part with @types/package
452
- fullyQualifiedName = fullyQualifiedName.replace(/^[^.]+\./, `@types/${packageName}.`);
453
- }
454
- }
455
- }
456
- }
542
+ // Use our getFullyQualifiedName method which uses TypeScript's built-in resolution
543
+ const fullyQualifiedName = this.getFullyQualifiedName(type);
457
544
  // Determine the class kind based on symbol flags
458
545
  let classKind = java_1.Type.Class.Kind.Interface; // Default to interface
459
546
  const symbol = (_b = type.getSymbol) === null || _b === void 0 ? void 0 : _b.call(type);