@openrewrite/rewrite 8.92.16 → 8.92.18

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 (254) hide show
  1. package/README.md +48 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/java/formatting-utils.d.ts +2 -1
  6. package/dist/java/formatting-utils.d.ts.map +1 -1
  7. package/dist/java/formatting-utils.js +4 -3
  8. package/dist/java/formatting-utils.js.map +1 -1
  9. package/dist/java/rpc.d.ts.map +1 -1
  10. package/dist/java/rpc.js +2 -0
  11. package/dist/java/rpc.js.map +1 -1
  12. package/dist/java/tree.d.ts +8 -0
  13. package/dist/java/tree.d.ts.map +1 -1
  14. package/dist/java/tree.js +11 -1
  15. package/dist/java/tree.js.map +1 -1
  16. package/dist/java/type.d.ts +7 -1
  17. package/dist/java/type.d.ts.map +1 -1
  18. package/dist/java/type.js +16 -1
  19. package/dist/java/type.js.map +1 -1
  20. package/dist/javascript/add-import.d.ts +27 -21
  21. package/dist/javascript/add-import.d.ts.map +1 -1
  22. package/dist/javascript/add-import.js +303 -143
  23. package/dist/javascript/add-import.js.map +1 -1
  24. package/dist/javascript/amd.d.ts.map +1 -1
  25. package/dist/javascript/amd.js +25 -10
  26. package/dist/javascript/amd.js.map +1 -1
  27. package/dist/javascript/autodetect.js +36 -45
  28. package/dist/javascript/autodetect.js.map +1 -1
  29. package/dist/javascript/binding.d.ts +6 -4
  30. package/dist/javascript/binding.d.ts.map +1 -1
  31. package/dist/javascript/binding.js +54 -18
  32. package/dist/javascript/binding.js.map +1 -1
  33. package/dist/javascript/comparator.d.ts +22 -5
  34. package/dist/javascript/comparator.d.ts.map +1 -1
  35. package/dist/javascript/comparator.js +120 -38
  36. package/dist/javascript/comparator.js.map +1 -1
  37. package/dist/javascript/format/format.d.ts +2 -0
  38. package/dist/javascript/format/format.d.ts.map +1 -1
  39. package/dist/javascript/format/format.js +11 -1
  40. package/dist/javascript/format/format.js.map +1 -1
  41. package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
  42. package/dist/javascript/format/tabs-and-indents-visitor.js +31 -4
  43. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  44. package/dist/javascript/index.d.ts +4 -2
  45. package/dist/javascript/index.d.ts.map +1 -1
  46. package/dist/javascript/index.js +10 -1
  47. package/dist/javascript/index.js.map +1 -1
  48. package/dist/javascript/markers.d.ts +12 -0
  49. package/dist/javascript/markers.d.ts.map +1 -1
  50. package/dist/javascript/markers.js +81 -2
  51. package/dist/javascript/markers.js.map +1 -1
  52. package/dist/javascript/method-matcher.d.ts +13 -2
  53. package/dist/javascript/method-matcher.d.ts.map +1 -1
  54. package/dist/javascript/method-matcher.js +32 -19
  55. package/dist/javascript/method-matcher.js.map +1 -1
  56. package/dist/javascript/node-resolution-result.js +3 -2
  57. package/dist/javascript/node-resolution-result.js.map +1 -1
  58. package/dist/javascript/package-name.d.ts +6 -0
  59. package/dist/javascript/package-name.d.ts.map +1 -0
  60. package/dist/javascript/package-name.js +47 -0
  61. package/dist/javascript/package-name.js.map +1 -0
  62. package/dist/javascript/parser.d.ts +9 -0
  63. package/dist/javascript/parser.d.ts.map +1 -1
  64. package/dist/javascript/parser.js +185 -88
  65. package/dist/javascript/parser.js.map +1 -1
  66. package/dist/javascript/preconditions.d.ts +4 -1
  67. package/dist/javascript/preconditions.d.ts.map +1 -1
  68. package/dist/javascript/preconditions.js +7 -4
  69. package/dist/javascript/preconditions.js.map +1 -1
  70. package/dist/javascript/print.d.ts +10 -1
  71. package/dist/javascript/print.d.ts.map +1 -1
  72. package/dist/javascript/print.js +120 -77
  73. package/dist/javascript/print.js.map +1 -1
  74. package/dist/javascript/recipes/change-method-target-to-import.d.ts +29 -0
  75. package/dist/javascript/recipes/change-method-target-to-import.d.ts.map +1 -0
  76. package/dist/javascript/recipes/change-method-target-to-import.js +164 -0
  77. package/dist/javascript/recipes/change-method-target-to-import.js.map +1 -0
  78. package/dist/javascript/recipes/index.d.ts +1 -0
  79. package/dist/javascript/recipes/index.d.ts.map +1 -1
  80. package/dist/javascript/recipes/index.js +1 -0
  81. package/dist/javascript/recipes/index.js.map +1 -1
  82. package/dist/javascript/scope.d.ts +60 -16
  83. package/dist/javascript/scope.d.ts.map +1 -1
  84. package/dist/javascript/scope.js +596 -131
  85. package/dist/javascript/scope.js.map +1 -1
  86. package/dist/javascript/search/uses-method.d.ts +1 -1
  87. package/dist/javascript/search/uses-method.d.ts.map +1 -1
  88. package/dist/javascript/search/uses-method.js +2 -2
  89. package/dist/javascript/search/uses-method.js.map +1 -1
  90. package/dist/javascript/search/uses-type.d.ts +14 -1
  91. package/dist/javascript/search/uses-type.d.ts.map +1 -1
  92. package/dist/javascript/search/uses-type.js +24 -9
  93. package/dist/javascript/search/uses-type.js.map +1 -1
  94. package/dist/javascript/templating/bindings.d.ts +1 -1
  95. package/dist/javascript/templating/bindings.d.ts.map +1 -1
  96. package/dist/javascript/templating/bindings.js +10 -50
  97. package/dist/javascript/templating/bindings.js.map +1 -1
  98. package/dist/javascript/templating/comparator.d.ts +8 -11
  99. package/dist/javascript/templating/comparator.d.ts.map +1 -1
  100. package/dist/javascript/templating/comparator.js +12 -110
  101. package/dist/javascript/templating/comparator.js.map +1 -1
  102. package/dist/javascript/templating/engine.d.ts +34 -24
  103. package/dist/javascript/templating/engine.d.ts.map +1 -1
  104. package/dist/javascript/templating/engine.js +208 -115
  105. package/dist/javascript/templating/engine.js.map +1 -1
  106. package/dist/javascript/templating/pattern.d.ts +11 -5
  107. package/dist/javascript/templating/pattern.d.ts.map +1 -1
  108. package/dist/javascript/templating/pattern.js +86 -20
  109. package/dist/javascript/templating/pattern.js.map +1 -1
  110. package/dist/javascript/templating/placeholder-replacement.d.ts +34 -3
  111. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
  112. package/dist/javascript/templating/placeholder-replacement.js +126 -60
  113. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  114. package/dist/javascript/templating/precedence.d.ts +3 -1
  115. package/dist/javascript/templating/precedence.d.ts.map +1 -1
  116. package/dist/javascript/templating/precedence.js +28 -8
  117. package/dist/javascript/templating/precedence.js.map +1 -1
  118. package/dist/javascript/templating/template.d.ts +7 -6
  119. package/dist/javascript/templating/template.d.ts.map +1 -1
  120. package/dist/javascript/templating/template.js +31 -28
  121. package/dist/javascript/templating/template.js.map +1 -1
  122. package/dist/javascript/templating/types.d.ts +6 -3
  123. package/dist/javascript/templating/types.d.ts.map +1 -1
  124. package/dist/javascript/templating/utils.d.ts +10 -1
  125. package/dist/javascript/templating/utils.d.ts.map +1 -1
  126. package/dist/javascript/templating/utils.js +22 -3
  127. package/dist/javascript/templating/utils.js.map +1 -1
  128. package/dist/javascript/tree-debug.d.ts +2 -0
  129. package/dist/javascript/tree-debug.d.ts.map +1 -1
  130. package/dist/javascript/tree-debug.js +6 -0
  131. package/dist/javascript/tree-debug.js.map +1 -1
  132. package/dist/javascript/tsconfig.d.ts.map +1 -1
  133. package/dist/javascript/tsconfig.js +7 -17
  134. package/dist/javascript/tsconfig.js.map +1 -1
  135. package/dist/javascript/type-mapping.d.ts +35 -16
  136. package/dist/javascript/type-mapping.d.ts.map +1 -1
  137. package/dist/javascript/type-mapping.js +271 -252
  138. package/dist/javascript/type-mapping.js.map +1 -1
  139. package/dist/javascript/type-report-cli.d.ts +7 -0
  140. package/dist/javascript/type-report-cli.d.ts.map +1 -0
  141. package/dist/javascript/type-report-cli.js +129 -0
  142. package/dist/javascript/type-report-cli.js.map +1 -0
  143. package/dist/javascript/type-report.d.ts +61 -0
  144. package/dist/javascript/type-report.d.ts.map +1 -0
  145. package/dist/javascript/type-report.js +488 -0
  146. package/dist/javascript/type-report.js.map +1 -0
  147. package/dist/markers.d.ts +4 -0
  148. package/dist/markers.d.ts.map +1 -1
  149. package/dist/markers.js +8 -0
  150. package/dist/markers.js.map +1 -1
  151. package/dist/print.d.ts +6 -1
  152. package/dist/print.d.ts.map +1 -1
  153. package/dist/print.js +21 -7
  154. package/dist/print.js.map +1 -1
  155. package/dist/recipe.d.ts +5 -0
  156. package/dist/recipe.d.ts.map +1 -1
  157. package/dist/recipe.js +5 -0
  158. package/dist/recipe.js.map +1 -1
  159. package/dist/rewrite-javascript-version.txt +1 -1
  160. package/dist/rpc/java-rpc-client.d.ts +2 -0
  161. package/dist/rpc/java-rpc-client.d.ts.map +1 -1
  162. package/dist/rpc/java-rpc-client.js +1 -0
  163. package/dist/rpc/java-rpc-client.js.map +1 -1
  164. package/dist/rpc/queue.d.ts +24 -0
  165. package/dist/rpc/queue.d.ts.map +1 -1
  166. package/dist/rpc/queue.js +71 -11
  167. package/dist/rpc/queue.js.map +1 -1
  168. package/dist/rpc/request/get-object.d.ts +4 -0
  169. package/dist/rpc/request/get-object.d.ts.map +1 -1
  170. package/dist/rpc/request/get-object.js +23 -1
  171. package/dist/rpc/request/get-object.js.map +1 -1
  172. package/dist/rpc/request/parse.d.ts.map +1 -1
  173. package/dist/rpc/request/parse.js +3 -1
  174. package/dist/rpc/request/parse.js.map +1 -1
  175. package/dist/rpc/request/prepare-recipe.d.ts +3 -1
  176. package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
  177. package/dist/rpc/request/prepare-recipe.js +13 -6
  178. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  179. package/dist/rpc/request/print.d.ts +8 -2
  180. package/dist/rpc/request/print.d.ts.map +1 -1
  181. package/dist/rpc/request/print.js +12 -9
  182. package/dist/rpc/request/print.js.map +1 -1
  183. package/dist/rpc/rewrite-rpc.d.ts +3 -2
  184. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  185. package/dist/rpc/rewrite-rpc.js +9 -3
  186. package/dist/rpc/rewrite-rpc.js.map +1 -1
  187. package/dist/rpc/server.d.ts.map +1 -1
  188. package/dist/rpc/server.js +19 -5
  189. package/dist/rpc/server.js.map +1 -1
  190. package/dist/search/is-source-file.d.ts +1 -0
  191. package/dist/search/is-source-file.d.ts.map +1 -1
  192. package/dist/search/is-source-file.js +7 -2
  193. package/dist/search/is-source-file.js.map +1 -1
  194. package/dist/test/java-rpc.d.ts.map +1 -1
  195. package/dist/test/java-rpc.js +3 -0
  196. package/dist/test/java-rpc.js.map +1 -1
  197. package/dist/test/rewrite-test.d.ts +5 -0
  198. package/dist/test/rewrite-test.d.ts.map +1 -1
  199. package/dist/test/rewrite-test.js +14 -3
  200. package/dist/test/rewrite-test.js.map +1 -1
  201. package/package.json +4 -3
  202. package/src/index.ts +3 -1
  203. package/src/java/formatting-utils.ts +5 -4
  204. package/src/java/rpc.ts +2 -0
  205. package/src/java/tree.ts +15 -0
  206. package/src/java/type.ts +19 -2
  207. package/src/javascript/add-import.ts +338 -152
  208. package/src/javascript/amd.ts +28 -12
  209. package/src/javascript/autodetect.ts +32 -41
  210. package/src/javascript/binding.ts +64 -22
  211. package/src/javascript/comparator.ts +129 -43
  212. package/src/javascript/format/format.ts +9 -0
  213. package/src/javascript/format/tabs-and-indents-visitor.ts +30 -3
  214. package/src/javascript/index.ts +6 -3
  215. package/src/javascript/markers.ts +77 -5
  216. package/src/javascript/method-matcher.ts +34 -22
  217. package/src/javascript/node-resolution-result.ts +3 -2
  218. package/src/javascript/package-name.ts +45 -0
  219. package/src/javascript/parser.ts +200 -91
  220. package/src/javascript/preconditions.ts +7 -4
  221. package/src/javascript/print.ts +123 -76
  222. package/src/javascript/recipes/change-method-target-to-import.ts +178 -0
  223. package/src/javascript/recipes/index.ts +1 -0
  224. package/src/javascript/scope.ts +705 -169
  225. package/src/javascript/search/uses-method.ts +2 -2
  226. package/src/javascript/search/uses-type.ts +30 -9
  227. package/src/javascript/templating/bindings.ts +13 -38
  228. package/src/javascript/templating/comparator.ts +16 -127
  229. package/src/javascript/templating/engine.ts +236 -129
  230. package/src/javascript/templating/pattern.ts +107 -28
  231. package/src/javascript/templating/placeholder-replacement.ts +154 -62
  232. package/src/javascript/templating/precedence.ts +33 -11
  233. package/src/javascript/templating/template.ts +35 -30
  234. package/src/javascript/templating/types.ts +6 -3
  235. package/src/javascript/templating/utils.ts +24 -2
  236. package/src/javascript/tree-debug.ts +9 -0
  237. package/src/javascript/tsconfig.ts +7 -17
  238. package/src/javascript/type-mapping.ts +277 -255
  239. package/src/javascript/type-report-cli.ts +96 -0
  240. package/src/javascript/type-report.ts +575 -0
  241. package/src/markers.ts +8 -0
  242. package/src/print.ts +23 -8
  243. package/src/recipe.ts +6 -0
  244. package/src/rpc/java-rpc-client.ts +3 -0
  245. package/src/rpc/queue.ts +80 -7
  246. package/src/rpc/request/get-object.ts +24 -0
  247. package/src/rpc/request/parse.ts +4 -1
  248. package/src/rpc/request/prepare-recipe.ts +16 -6
  249. package/src/rpc/request/print.ts +12 -8
  250. package/src/rpc/rewrite-rpc.ts +16 -5
  251. package/src/rpc/server.ts +18 -6
  252. package/src/search/is-source-file.ts +8 -3
  253. package/src/test/java-rpc.ts +3 -0
  254. package/src/test/rewrite-test.ts +14 -3
@@ -54,7 +54,9 @@ exports.JavaScriptTypeMapping = void 0;
54
54
  */
55
55
  const typescript_1 = __importDefault(require("typescript"));
56
56
  const path = __importStar(require("path"));
57
+ const module_1 = require("module");
57
58
  const java_1 = require("../java");
59
+ const package_name_1 = require("./package-name");
58
60
  var FUNCTION_TYPE_NAME = java_1.Type.FUNCTION_TYPE_NAME;
59
61
  var OBJECT_TYPE_NAME = java_1.Type.OBJECT_TYPE_NAME;
60
62
  /**
@@ -73,6 +75,18 @@ function sortBySignature(bounds) {
73
75
  function typeSignatureToJSON() {
74
76
  return java_1.Type.signature(this);
75
77
  }
78
+ /**
79
+ * A module specifier with a redundant `node:` scheme removed.
80
+ * `node:url` and `url` import the same built-in, which is named without the scheme.
81
+ * A built-in such as `node:test` has no bare form, and `test` is another package, so it keeps it.
82
+ */
83
+ function moduleName(specifier) {
84
+ const bare = specifier.substring('node:'.length);
85
+ return specifier.startsWith('node:') && (0, module_1.isBuiltin)(bare) ? bare : specifier;
86
+ }
87
+ function isGlobalAugmentation(declaration) {
88
+ return typescript_1.default.isModuleDeclaration(declaration) && (declaration.flags & typescript_1.default.NodeFlags.GlobalAugmentation) !== 0;
89
+ }
76
90
  class JavaScriptTypeMapping {
77
91
  constructor(checker, sourceRoot) {
78
92
  this.checker = checker;
@@ -81,11 +95,16 @@ class JavaScriptTypeMapping {
81
95
  // TypeScript assigns stable IDs to all types, so we don't need secondary caches
82
96
  this.typeCache = new Map();
83
97
  this.methodCache = new Map();
98
+ // The declarations of function types being populated. An instantiation of one of these is
99
+ // unknown, since `type Rec<T> = (x: T) => Rec<T[]>` instantiates without end and each
100
+ // instantiation has a type id of its own that the type cache cannot match.
101
+ this.functionTypesInProgress = new Set();
84
102
  this.regExpSymbol = checker.resolveName("RegExp", undefined, typescript_1.default.SymbolFlags.Type, false);
85
103
  // Resolve global wrapper types for primitives from TypeScript's lib
86
104
  const stringSymbol = checker.resolveName("String", undefined, typescript_1.default.SymbolFlags.Type, false);
87
105
  const numberSymbol = checker.resolveName("Number", undefined, typescript_1.default.SymbolFlags.Type, false);
88
106
  const booleanSymbol = checker.resolveName("Boolean", undefined, typescript_1.default.SymbolFlags.Type, false);
107
+ const symbolSymbol = checker.resolveName("Symbol", undefined, typescript_1.default.SymbolFlags.Type, false);
89
108
  // Store the TypeScript types; conversion to Type happens on-demand
90
109
  if (stringSymbol) {
91
110
  this.stringWrapperType = checker.getDeclaredTypeOfSymbol(stringSymbol);
@@ -96,6 +115,9 @@ class JavaScriptTypeMapping {
96
115
  if (booleanSymbol) {
97
116
  this.booleanWrapperType = checker.getDeclaredTypeOfSymbol(booleanSymbol);
98
117
  }
118
+ if (symbolSymbol) {
119
+ this.symbolWrapperType = checker.getDeclaredTypeOfSymbol(symbolSymbol);
120
+ }
99
121
  }
100
122
  type(node) {
101
123
  // For identifiers, check if this references a variable
@@ -302,10 +324,13 @@ class JavaScriptTypeMapping {
302
324
  }
303
325
  // Skip instantiated types ONLY if they're not type references
304
326
  // Type references like Array<string>, Promise<T> are instantiated but should be mapped
327
+ // Function types, such as a generic method's callback parameter, are mapped too
305
328
  // Other instantiated types (like object literals) should return unknown
306
329
  if (objectFlags & typescript_1.default.ObjectFlags.Instantiated) {
307
330
  const isTypeReference = objectFlags & typescript_1.default.ObjectFlags.Reference;
308
- if (!isTypeReference) {
331
+ const isFunctionType = type.getCallSignatures().length > 0 &&
332
+ !this.functionTypesInProgress.has(type.symbol);
333
+ if (!isTypeReference && !isFunctionType) {
309
334
  return java_1.Type.unknownType;
310
335
  }
311
336
  }
@@ -388,22 +413,14 @@ class JavaScriptTypeMapping {
388
413
  if (symbol.flags & typescript_1.default.SymbolFlags.Function) {
389
414
  const callSignatures = type.getCallSignatures();
390
415
  if (callSignatures.length > 0) {
391
- // Shell-cache: Create stub, cache it, then populate (prevents cycles)
392
- const functionType = this.createEmptyFunctionType();
393
- this.typeCache.set(signature, functionType);
394
- this.populateFunctionType(functionType, callSignatures[0]);
395
- return functionType;
416
+ return this.createFunctionType(type, callSignatures[0], signature);
396
417
  }
397
418
  }
398
419
  // Check for function-scoped or block-scoped variables that might be functions
399
420
  if (symbol.flags & (typescript_1.default.SymbolFlags.FunctionScopedVariable | typescript_1.default.SymbolFlags.BlockScopedVariable)) {
400
421
  const callSignatures = type.getCallSignatures();
401
422
  if (callSignatures.length > 0) {
402
- // Shell-cache: Create stub, cache it, then populate (prevents cycles)
403
- const functionType = this.createEmptyFunctionType();
404
- this.typeCache.set(signature, functionType);
405
- this.populateFunctionType(functionType, callSignatures[0]);
406
- return functionType;
423
+ return this.createFunctionType(type, callSignatures[0], signature);
407
424
  }
408
425
  }
409
426
  if (symbol.flags & typescript_1.default.SymbolFlags.ValueModule) {
@@ -450,11 +467,7 @@ class JavaScriptTypeMapping {
450
467
  // Check for function types without symbols (anonymous functions, function types)
451
468
  const callSignatures = type.getCallSignatures();
452
469
  if (callSignatures && callSignatures.length > 0) {
453
- // Shell-cache: Create stub, cache it, then populate (prevents cycles)
454
- const functionType = this.createEmptyFunctionType();
455
- this.typeCache.set(signature, functionType);
456
- this.populateFunctionType(functionType, callSignatures[0]);
457
- return functionType;
470
+ return this.createFunctionType(type, callSignatures[0], signature);
458
471
  }
459
472
  // A structural type has no nominal name, so every object literal `{a: 1}` and type
460
473
  // literal `{a: number}` shares the synthetic FQN `{}`, with `members` carrying the shape.
@@ -513,6 +526,7 @@ class JavaScriptTypeMapping {
513
526
  return java_1.Type.isPrimitive(type) ? type : java_1.Type.Primitive.None;
514
527
  }
515
528
  variableType(node) {
529
+ var _a;
516
530
  let symbol;
517
531
  let location = node;
518
532
  // Get the symbol depending on node type
@@ -571,32 +585,20 @@ class JavaScriptTypeMapping {
571
585
  // Check if the variable is imported
572
586
  if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
573
587
  // For imported variables, find the module specifier
574
- const declarations = symbol.declarations;
575
- if (declarations && declarations.length > 0) {
576
- let importNode = declarations[0];
577
- // Traverse up to find the ImportDeclaration
578
- while (importNode && !typescript_1.default.isImportDeclaration(importNode)) {
579
- importNode = importNode.parent;
580
- }
581
- if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
582
- const importDecl = importNode;
583
- if (typescript_1.default.isStringLiteral(importDecl.moduleSpecifier)) {
584
- const moduleSpecifier = importDecl.moduleSpecifier.text;
585
- // Create a Type.Class representing the module
586
- ownerType = {
587
- kind: java_1.Type.Kind.Class,
588
- flags: 0,
589
- classKind: java_1.Type.Class.Kind.Interface,
590
- fullyQualifiedName: moduleSpecifier,
591
- typeParameters: [],
592
- annotations: [],
593
- interfaces: [],
594
- members: [],
595
- methods: [],
596
- toJSON: typeSignatureToJSON
597
- };
598
- }
599
- }
588
+ const moduleSpecifier = this.importedModule((_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a[0]);
589
+ if (moduleSpecifier) {
590
+ ownerType = {
591
+ kind: java_1.Type.Kind.Class,
592
+ flags: 0,
593
+ classKind: java_1.Type.Class.Kind.Interface,
594
+ fullyQualifiedName: moduleSpecifier,
595
+ typeParameters: [],
596
+ annotations: [],
597
+ interfaces: [],
598
+ members: [],
599
+ methods: [],
600
+ toJSON: typeSignatureToJSON
601
+ };
600
602
  }
601
603
  }
602
604
  else {
@@ -647,6 +649,7 @@ class JavaScriptTypeMapping {
647
649
  // Create the Type.Variable
648
650
  const variable = {
649
651
  kind: java_1.Type.Kind.Variable,
652
+ flags: 0,
650
653
  name: actualSymbol.getName(),
651
654
  owner: ownerType,
652
655
  type: mappedType,
@@ -667,7 +670,7 @@ class JavaScriptTypeMapping {
667
670
  return undefined;
668
671
  }
669
672
  const moduleArg = node.arguments[0];
670
- return typescript_1.default.isStringLiteral(moduleArg) ? moduleArg.text : undefined;
673
+ return typescript_1.default.isStringLiteral(moduleArg) ? moduleName(moduleArg.text) : undefined;
671
674
  }
672
675
  /**
673
676
  * The module an expression evaluates to where that is a `require()` result — either the call
@@ -704,14 +707,10 @@ class JavaScriptTypeMapping {
704
707
  if (!declaration) {
705
708
  return undefined;
706
709
  }
707
- let importDecl = declaration;
708
- while (importDecl && !typescript_1.default.isImportDeclaration(importDecl)) {
709
- importDecl = importDecl.parent;
710
- }
711
- if (!importDecl || !typescript_1.default.isStringLiteral(importDecl.moduleSpecifier)) {
710
+ const module = this.importedModule(declaration);
711
+ if (!module) {
712
712
  return undefined;
713
713
  }
714
- const module = importDecl.moduleSpecifier.text;
715
714
  if (typescript_1.default.isNamespaceImport(declaration)) {
716
715
  return { module, namespace: true };
717
716
  }
@@ -735,6 +734,37 @@ class JavaScriptTypeMapping {
735
734
  const binding = this.importBinding(node);
736
735
  return binding && binding.exportName === undefined ? binding.module : undefined;
737
736
  }
737
+ /**
738
+ * The module an import declaration containing `node` imports, or undefined when `node` is not
739
+ * part of one or its specifier is not a string literal.
740
+ */
741
+ importedModule(node) {
742
+ while (node && !typescript_1.default.isImportDeclaration(node)) {
743
+ node = node.parent;
744
+ }
745
+ return node && typescript_1.default.isStringLiteral(node.moduleSpecifier) ? moduleName(node.moduleSpecifier.text) : undefined;
746
+ }
747
+ /**
748
+ * A parsed file's module, named after its path relative to the source root without its extension,
749
+ * as TypeScript names the module of an export. A function declared in the file is declared on it.
750
+ */
751
+ sourceModuleType(sourceFile) {
752
+ return this.moduleType(this.sourceModuleName(sourceFile));
753
+ }
754
+ sourceModuleName(sourceFile) {
755
+ const fileName = sourceFile.fileName;
756
+ const relative = this.sourceRoot && path.isAbsolute(fileName) ? path.relative(this.sourceRoot, fileName) : fileName;
757
+ return relative.replace(/\.[^/.]+$/, '');
758
+ }
759
+ /**
760
+ * The declaration of a function in a parsed source file. A `.d.ts` file is not parsed, so a
761
+ * function such as `parseInt` has none.
762
+ */
763
+ parsedFunctionDeclaration(symbol) {
764
+ const declaration = symbol.valueDeclaration;
765
+ return declaration && typescript_1.default.isFunctionDeclaration(declaration) && !declaration.getSourceFile().isDeclarationFile ?
766
+ declaration : undefined;
767
+ }
738
768
  moduleType(module) {
739
769
  return {
740
770
  kind: java_1.Type.Kind.Class,
@@ -761,54 +791,13 @@ class JavaScriptTypeMapping {
761
791
  // This also correctly handles pnpm's .pnpm structure
762
792
  const lastNodeModulesIndex = fileName.lastIndexOf('node_modules/');
763
793
  const afterNodeModules = fileName.substring(lastNodeModulesIndex + 'node_modules/'.length);
764
- // Split by '/' to get path segments
765
- const segments = afterNodeModules.split('/');
766
- if (segments.length === 0) {
767
- return undefined;
768
- }
769
- let moduleName;
770
- // Handle scoped packages (@scope/package)
771
- if (segments[0].startsWith('@') && segments.length > 1) {
772
- moduleName = `${segments[0]}/${segments[1]}`;
773
- }
774
- else {
775
- moduleName = segments[0];
776
- }
777
794
  // Skip pnpm's .pnpm directory - it contains versioned package paths
778
795
  // In pnpm, the actual package is in: .pnpm/pkg@version/node_modules/pkg
779
796
  // So we already handled this by using lastIndexOf above
780
- if (moduleName === '.pnpm') {
797
+ if (afterNodeModules.split('/')[0] === '.pnpm') {
781
798
  return undefined;
782
799
  }
783
- return this.normalizePackageName(moduleName);
784
- }
785
- /**
786
- * Normalize a node_modules package name to the specifier consumers actually import.
787
- *
788
- * DefinitelyTyped packages (`@types/<pkg>`) are never importable under that name — the
789
- * importable specifier is `<pkg>`, with DefinitelyTyped's `__` scoped-package encoding
790
- * decoded back to a `@scope/name` form. Using the importable specifier keeps attributed
791
- * fully qualified names consistent regardless of whether a type is reached through a direct
792
- * import (which already resolves via the module specifier) or transitively (e.g. a call's
793
- * return type), which falls back to the declaration file's `node_modules` path.
794
- *
795
- * Examples:
796
- * - `@types/express-serve-static-core` -> `express-serve-static-core`
797
- * - `@types/node` -> `node`
798
- * - `@types/testing-library__react` -> `@testing-library/react`
799
- */
800
- normalizePackageName(packageName) {
801
- if (packageName.startsWith('@types/')) {
802
- packageName = packageName.substring('@types/'.length);
803
- // Decode __ encoding for scoped packages: testing-library__react -> @testing-library/react
804
- if (packageName.includes('__')) {
805
- const parts = packageName.split('__');
806
- if (parts.length === 2) {
807
- packageName = `@${parts[0]}/${parts[1]}`;
808
- }
809
- }
810
- }
811
- return packageName;
800
+ return (0, package_name_1.packageNameOf)(afterNodeModules);
812
801
  }
813
802
  /**
814
803
  * Helper to create a Type.Method object from common parameters
@@ -851,6 +840,42 @@ class JavaScriptTypeMapping {
851
840
  this.methodCache.set(cacheKey, method);
852
841
  return method;
853
842
  }
843
+ // A method is declared by one class, which an object literal that spreads a union, for one, is not.
844
+ declaringType(type) {
845
+ const mapped = this.getType(type);
846
+ switch (mapped.kind) {
847
+ case java_1.Type.Kind.Class:
848
+ case java_1.Type.Kind.Annotation:
849
+ case java_1.Type.Kind.ShallowClass:
850
+ case java_1.Type.Kind.Parameterized:
851
+ return mapped;
852
+ case java_1.Type.Kind.Primitive:
853
+ return this.wrapperType(mapped);
854
+ default:
855
+ return java_1.Type.unknownType;
856
+ }
857
+ }
858
+ /**
859
+ * The class or interface that declares a member, which is a call's declaring type, as in Java.
860
+ * A union's member has one only when every member type inherits it from the same class.
861
+ */
862
+ declaringClassOf(member) {
863
+ var _a;
864
+ let owner;
865
+ for (const declaration of (_a = member.declarations) !== null && _a !== void 0 ? _a : []) {
866
+ const parent = declaration.parent;
867
+ if (!typescript_1.default.isClassLike(parent) && !typescript_1.default.isInterfaceDeclaration(parent)) {
868
+ return undefined;
869
+ }
870
+ const type = this.checker.getTypeAtLocation(parent);
871
+ if (owner && owner.symbol !== type.symbol) {
872
+ return undefined;
873
+ }
874
+ owner = type;
875
+ }
876
+ const declaringType = owner && this.declaringType(owner);
877
+ return declaringType === java_1.Type.unknownType ? undefined : declaringType;
878
+ }
854
879
  wrapperType(declaringType) {
855
880
  if (declaringType === java_1.Type.Primitive.String && this.stringWrapperType) {
856
881
  return this.getType(this.stringWrapperType);
@@ -867,7 +892,7 @@ class JavaScriptTypeMapping {
867
892
  }
868
893
  }
869
894
  methodType(node) {
870
- var _a, _b, _c, _d, _e, _f, _g;
895
+ var _a, _b, _c, _d, _e, _f, _g, _h;
871
896
  // An object literal is a `J.NewClass`, and `J.NewClass.getType()` reads
872
897
  // `constructorType.returnType`, as it does for a Java anonymous class.
873
898
  if (typescript_1.default.isObjectLiteralExpression(node)) {
@@ -957,8 +982,11 @@ class JavaScriptTypeMapping {
957
982
  const receiverBinding = isImport ? this.importBinding(node.expression.expression) : undefined;
958
983
  const anonymous = !mappedType || mappedType.kind !== java_1.Type.Kind.Class ||
959
984
  mappedType.fullyQualifiedName.startsWith('{');
960
- // Handle different types
961
- if ((receiverBinding === null || receiverBinding === void 0 ? void 0 : receiverBinding.namespace) && anonymous) {
985
+ const declaringClass = this.declaringClassOf(symbol);
986
+ if (declaringClass) {
987
+ declaringType = declaringClass;
988
+ }
989
+ else if ((receiverBinding === null || receiverBinding === void 0 ? void 0 : receiverBinding.namespace) && anonymous) {
962
990
  declaringType = this.moduleType(receiverBinding.module);
963
991
  if (methodName === 'default') {
964
992
  methodName = '<default>';
@@ -1033,56 +1061,36 @@ class JavaScriptTypeMapping {
1033
1061
  moduleSpecifier = aliasedParentSymbol.name;
1034
1062
  }
1035
1063
  else {
1036
- // Now find the import declaration to get the module specifier
1037
- if (exprSymbol.declarations && exprSymbol.declarations.length > 0) {
1038
- let importNode = exprSymbol.declarations[0];
1039
- // Traverse up to find the ImportDeclaration
1040
- while (importNode && !typescript_1.default.isImportDeclaration(importNode)) {
1041
- importNode = importNode.parent;
1042
- }
1043
- if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
1044
- const importDeclNode = importNode;
1045
- if (typescript_1.default.isStringLiteral(importDeclNode.moduleSpecifier)) {
1046
- moduleSpecifier = importDeclNode.moduleSpecifier.text;
1047
- }
1048
- }
1049
- }
1064
+ moduleSpecifier = this.importedModule((_b = exprSymbol.declarations) === null || _b === void 0 ? void 0 : _b[0]);
1050
1065
  }
1051
1066
  }
1052
1067
  }
1053
- if (moduleSpecifier) {
1068
+ const declared = this.parsedFunctionDeclaration(aliasedSymbol !== null && aliasedSymbol !== void 0 ? aliasedSymbol : symbol);
1069
+ if (declared) {
1070
+ declaringType = this.sourceModuleType(declared.getSourceFile());
1071
+ methodName = declared.name ? declared.name.text : "<anonymous>";
1072
+ }
1073
+ else if (moduleSpecifier) {
1054
1074
  // This is an imported function - use the module specifier as declaring type
1055
- if (moduleSpecifier.startsWith('node:')) {
1056
- // Node.js built-in module
1057
- declaringType = {
1058
- kind: java_1.Type.Kind.Class,
1059
- flags: 0, // TODO - determine flags
1060
- fullyQualifiedName: 'node'
1061
- };
1062
- methodName = moduleSpecifier.substring(5); // Remove 'node:' prefix
1075
+ declaringType = {
1076
+ kind: java_1.Type.Kind.Class,
1077
+ flags: 0, // TODO - determine flags
1078
+ fullyQualifiedName: moduleSpecifier
1079
+ };
1080
+ // A default import binds an `ImportClause`; its aliased symbol carries the internal
1081
+ // name of the default export (e.g. `e` for express), so represent it as `<default>`.
1082
+ // Named imports (`ImportSpecifier`) keep the original exported name.
1083
+ const isDefaultImport = (_d = (_c = exprSymbol === null || exprSymbol === void 0 ? void 0 : exprSymbol.declarations) === null || _c === void 0 ? void 0 : _c.some(typescript_1.default.isImportClause)) !== null && _d !== void 0 ? _d : false;
1084
+ if (isDefaultImport) {
1085
+ methodName = '<default>';
1086
+ }
1087
+ else if ((_e = aliasedSymbol === null || aliasedSymbol === void 0 ? void 0 : aliasedSymbol.declarations) === null || _e === void 0 ? void 0 : _e.length) {
1088
+ methodName = aliasedSymbol.name;
1063
1089
  }
1064
1090
  else {
1065
- // Regular module import
1066
- declaringType = {
1067
- kind: java_1.Type.Kind.Class,
1068
- flags: 0, // TODO - determine flags
1069
- fullyQualifiedName: moduleSpecifier
1070
- };
1071
- // A default import binds an `ImportClause`; its aliased symbol carries the internal
1072
- // name of the default export (e.g. `e` for express), so represent it as `<default>`.
1073
- // Named imports (`ImportSpecifier`) keep the original exported name.
1074
- const isDefaultImport = (_c = (_b = exprSymbol === null || exprSymbol === void 0 ? void 0 : exprSymbol.declarations) === null || _b === void 0 ? void 0 : _b.some(typescript_1.default.isImportClause)) !== null && _c !== void 0 ? _c : false;
1075
- if (isDefaultImport) {
1076
- methodName = '<default>';
1077
- }
1078
- else if ((_d = aliasedSymbol === null || aliasedSymbol === void 0 ? void 0 : aliasedSymbol.declarations) === null || _d === void 0 ? void 0 : _d.length) {
1079
- methodName = aliasedSymbol.name;
1080
- }
1081
- else {
1082
- // A package without type declarations resolves the import to the checker's
1083
- // `unknown` symbol, so the exported name comes from the import itself.
1084
- methodName = (_g = (_f = (_e = this.importBinding(node.expression)) === null || _e === void 0 ? void 0 : _e.exportName) !== null && _f !== void 0 ? _f : aliasedSymbol === null || aliasedSymbol === void 0 ? void 0 : aliasedSymbol.name) !== null && _g !== void 0 ? _g : methodName;
1085
- }
1091
+ // A package without type declarations resolves the import to the checker's
1092
+ // `unknown` symbol, so the exported name comes from the import itself.
1093
+ methodName = (_h = (_g = (_f = this.importBinding(node.expression)) === null || _f === void 0 ? void 0 : _f.exportName) !== null && _g !== void 0 ? _g : aliasedSymbol === null || aliasedSymbol === void 0 ? void 0 : aliasedSymbol.name) !== null && _h !== void 0 ? _h : methodName;
1086
1094
  }
1087
1095
  }
1088
1096
  else if (this.requiredModuleOfExpression(node.expression)) {
@@ -1115,7 +1123,7 @@ class JavaScriptTypeMapping {
1115
1123
  const parent = symbol.parent;
1116
1124
  if (parent) {
1117
1125
  const parentType = this.checker.getDeclaredTypeOfSymbol(parent);
1118
- declaringType = this.getType(parentType);
1126
+ declaringType = this.declaringType(parentType);
1119
1127
  }
1120
1128
  else {
1121
1129
  declaringType = java_1.Type.unknownType;
@@ -1150,7 +1158,7 @@ class JavaScriptTypeMapping {
1150
1158
  const parent = node.parent;
1151
1159
  if (typescript_1.default.isClassDeclaration(parent) || typescript_1.default.isInterfaceDeclaration(parent) || typescript_1.default.isObjectLiteralExpression(parent)) {
1152
1160
  const parentType = this.checker.getTypeAtLocation(parent);
1153
- declaringType = this.getType(parentType);
1161
+ declaringType = this.declaringType(parentType);
1154
1162
  }
1155
1163
  else {
1156
1164
  declaringType = java_1.Type.unknownType;
@@ -1172,7 +1180,7 @@ class JavaScriptTypeMapping {
1172
1180
  const parent = node.parent;
1173
1181
  if (typescript_1.default.isClassDeclaration(parent) || typescript_1.default.isClassExpression(parent)) {
1174
1182
  const parentType = this.checker.getTypeAtLocation(parent);
1175
- declaringType = this.getType(parentType);
1183
+ declaringType = this.declaringType(parentType);
1176
1184
  }
1177
1185
  else {
1178
1186
  declaringType = java_1.Type.unknownType;
@@ -1185,24 +1193,7 @@ class JavaScriptTypeMapping {
1185
1193
  return undefined;
1186
1194
  }
1187
1195
  methodName = node.name ? node.name.getText() : "<anonymous>";
1188
- // Derive declaring type from source file module path (like Go's type_mapper.go).
1189
- // Use the same relativization as getFullyQualifiedName() so that declarations
1190
- // and invocations produce matching FQNs.
1191
- let moduleFqn;
1192
- const fileName = node.getSourceFile().fileName;
1193
- if (this.sourceRoot && path.isAbsolute(fileName)) {
1194
- moduleFqn = path.relative(this.sourceRoot, fileName);
1195
- }
1196
- else {
1197
- moduleFqn = fileName;
1198
- }
1199
- // Strip file extension to get the module name
1200
- moduleFqn = moduleFqn.replace(/\.[^/.]+$/, '');
1201
- declaringType = {
1202
- kind: java_1.Type.Kind.Class,
1203
- flags: 0,
1204
- fullyQualifiedName: moduleFqn
1205
- };
1196
+ declaringType = this.sourceModuleType(node.getSourceFile());
1206
1197
  // Get type parameters from node
1207
1198
  if (node.typeParameters) {
1208
1199
  for (const tp of node.typeParameters) {
@@ -1238,33 +1229,7 @@ class JavaScriptTypeMapping {
1238
1229
  if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
1239
1230
  const aliasedSymbol = this.checker.getAliasedSymbol(symbol);
1240
1231
  if (aliasedSymbol && aliasedSymbol !== symbol && symbol.declarations && symbol.declarations.length > 0) {
1241
- // Try to find the import declaration to get the module specifier
1242
- let importNode = symbol.declarations[0];
1243
- // Traverse up to find the ImportDeclaration or ImportSpecifier
1244
- while (importNode && importNode.parent && !typescript_1.default.isImportDeclaration(importNode) && !typescript_1.default.isImportSpecifier(importNode)) {
1245
- importNode = importNode.parent;
1246
- }
1247
- let moduleSpecifier;
1248
- if (importNode && typescript_1.default.isImportSpecifier(importNode)) {
1249
- // Named import like: import { ClipLoader } from 'react-spinners'
1250
- // ImportSpecifier -> NamedImports -> ImportClause -> ImportDeclaration
1251
- const namedImports = importNode.parent; // NamedImports
1252
- if (namedImports && typescript_1.default.isNamedImports(namedImports)) {
1253
- const importClause = namedImports.parent; // ImportClause
1254
- if (importClause && typescript_1.default.isImportClause(importClause)) {
1255
- const importDecl = importClause.parent; // ImportDeclaration
1256
- if (importDecl && typescript_1.default.isImportDeclaration(importDecl) && typescript_1.default.isStringLiteral(importDecl.moduleSpecifier)) {
1257
- moduleSpecifier = importDecl.moduleSpecifier.text;
1258
- }
1259
- }
1260
- }
1261
- }
1262
- else if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
1263
- // Default or namespace import
1264
- if (typescript_1.default.isStringLiteral(importNode.moduleSpecifier)) {
1265
- moduleSpecifier = importNode.moduleSpecifier.text;
1266
- }
1267
- }
1232
+ const moduleSpecifier = this.importedModule(symbol.declarations[0]);
1268
1233
  if (moduleSpecifier) {
1269
1234
  // Build the fully qualified name from module specifier + symbol name
1270
1235
  const symbolName = symbol.getName();
@@ -1276,42 +1241,34 @@ class JavaScriptTypeMapping {
1276
1241
  // This returns names with quotes that we need to clean up
1277
1242
  // e.g., '"React"."Component"' -> 'React.Component'
1278
1243
  const tsQualifiedName = this.checker.getFullyQualifiedName(symbol);
1279
- let cleanedName = tsQualifiedName.replace(/"/g, '');
1280
- // Check if this is a file path from node_modules (happens with some packages)
1281
- // TypeScript sometimes returns full paths instead of module names
1282
- if (cleanedName.includes('node_modules/')) {
1244
+ let cleanedName = moduleName(tsQualifiedName.replace(/"/g, ''));
1245
+ const outermost = this.outermostDeclaration(symbol);
1246
+ const sourceModule = outermost && this.sourceModuleOf(outermost);
1247
+ if (sourceModule) {
1248
+ cleanedName = `${sourceModule}.${cleanedName}`;
1249
+ }
1250
+ else if (cleanedName.includes('node_modules/')) {
1251
+ // Check if this is a file path from node_modules (happens with some packages)
1252
+ // TypeScript sometimes returns full paths instead of module names
1283
1253
  // Extract the module name from the path
1284
1254
  // Example: /private/var/.../node_modules/react-spinners/src/index.ClipLoader
1285
1255
  // Should become: react-spinners.ClipLoader
1286
1256
  const nodeModulesIndex = cleanedName.indexOf('node_modules/');
1287
1257
  const afterNodeModules = cleanedName.substring(nodeModulesIndex + 'node_modules/'.length);
1288
- // Split by '/' to get parts of the path
1289
- const pathParts = afterNodeModules.split('/');
1290
- if (pathParts.length > 0) {
1291
- // First part is the package name (might be scoped like @types)
1292
- let packageName = pathParts[0];
1293
- // Handle scoped packages
1294
- if (packageName.startsWith('@') && pathParts.length > 1) {
1295
- packageName = `${packageName}/${pathParts[1]}`;
1296
- }
1297
- // Normalize `@types/<pkg>` to the importable specifier `<pkg>` so that types
1298
- // reached transitively (e.g. a call's return type, resolved via the declaration
1299
- // file's node_modules path) match the names used for directly imported types.
1300
- packageName = this.normalizePackageName(packageName);
1301
- // The symbol name is appended to the declaration file's path, so it is whatever
1302
- // follows the last dot of the final path segment. Directory names carry dots of
1303
- // their own — `.pnpm`, `.yarn`, a hidden parent such as `.claude`, a versioned
1304
- // pnpm directory — so a search over the whole path would split there instead and
1305
- // fold most of the path into the name.
1306
- const lastSegmentIndex = cleanedName.lastIndexOf('/') + 1;
1307
- const lastDotIndex = cleanedName.lastIndexOf('.');
1308
- if (lastDotIndex > lastSegmentIndex) {
1309
- const symbolName = cleanedName.substring(lastDotIndex + 1);
1310
- cleanedName = `${packageName}.${symbolName}`;
1311
- }
1312
- else {
1313
- cleanedName = packageName;
1314
- }
1258
+ const packageName = (0, package_name_1.packageNameOf)(afterNodeModules);
1259
+ // The symbol name is appended to the declaration file's path, so it is whatever
1260
+ // follows the last dot of the final path segment. Directory names carry dots of
1261
+ // their own — `.pnpm`, `.yarn`, a hidden parent such as `.claude`, a versioned
1262
+ // pnpm directory — so a search over the whole path would split there instead and
1263
+ // fold most of the path into the name.
1264
+ const lastSegmentIndex = cleanedName.lastIndexOf('/') + 1;
1265
+ const lastDotIndex = cleanedName.lastIndexOf('.');
1266
+ if (lastDotIndex > lastSegmentIndex) {
1267
+ const symbolName = cleanedName.substring(lastDotIndex + 1);
1268
+ cleanedName = `${packageName}.${symbolName}`;
1269
+ }
1270
+ else {
1271
+ cleanedName = packageName;
1315
1272
  }
1316
1273
  }
1317
1274
  else if (path.isAbsolute(cleanedName)) {
@@ -1351,7 +1308,7 @@ class JavaScriptTypeMapping {
1351
1308
  // Preserved as-is:
1352
1309
  // - UMD globals (`export as namespace X`, e.g. React, lodash `_`, jQuery `$`): the
1353
1310
  // namespace name is the conventional public identifier;
1354
- // - `global.*` (TypeScript's marker for ambient globals);
1311
+ // - `global.*`, a `declare global` augmentation, whose prefix is dropped below;
1355
1312
  // - namespaces that already match the package name, and any non-node_modules type.
1356
1313
  const namespaceName = cleanedName.substring(0, cleanedName.indexOf('.'));
1357
1314
  if (namespaceName !== 'global') {
@@ -1365,10 +1322,37 @@ class JavaScriptTypeMapping {
1365
1322
  }
1366
1323
  }
1367
1324
  }
1325
+ // A `declare global` augmentation is in the same global scope as the built-ins, which have no prefix.
1326
+ if (outermost && isGlobalAugmentation(outermost) && cleanedName.startsWith('global.')) {
1327
+ cleanedName = cleanedName.substring('global.'.length);
1328
+ }
1368
1329
  return cleanedName.endsWith('Constructor') ?
1369
1330
  cleanedName.substring(0, cleanedName.length - 'Constructor'.length) :
1370
1331
  cleanedName;
1371
1332
  }
1333
+ /**
1334
+ * The project module whose top level holds a declaration local to it, such as a class it does not
1335
+ * export. TypeScript names that as bare as a global, so a module's own `class Array` needs the module.
1336
+ */
1337
+ sourceModuleOf(declaration) {
1338
+ if (!declaration.parent || !typescript_1.default.isSourceFile(declaration.parent) || isGlobalAugmentation(declaration) ||
1339
+ typescript_1.default.isModuleDeclaration(declaration) && typescript_1.default.isStringLiteral(declaration.name)) {
1340
+ return undefined;
1341
+ }
1342
+ const sourceFile = declaration.parent;
1343
+ const isModule = typescript_1.default.isExternalModule(sourceFile) || sourceFile.commonJsModuleIndicator !== undefined;
1344
+ return isModule && !sourceFile.isDeclarationFile && !sourceFile.fileName.includes('node_modules/') ?
1345
+ this.sourceModuleName(sourceFile) : undefined;
1346
+ }
1347
+ /** The declaration of the symbol a qualified name starts from, such as a class's namespace. */
1348
+ outermostDeclaration(symbol) {
1349
+ var _a;
1350
+ let outermost = symbol;
1351
+ while (outermost.parent) {
1352
+ outermost = outermost.parent;
1353
+ }
1354
+ return (_a = outermost.declarations) === null || _a === void 0 ? void 0 : _a[0];
1355
+ }
1372
1356
  /**
1373
1357
  * Whether {@code namespaceName} is exposed as a UMD global from the given declaration file
1374
1358
  * (e.g. `export as namespace React`). The namespace name of a UMD global is the conventional
@@ -1419,13 +1403,40 @@ class JavaScriptTypeMapping {
1419
1403
  toJSON: typeSignatureToJSON
1420
1404
  };
1421
1405
  }
1406
+ baseClass(classType, baseType) {
1407
+ const mapped = this.getType(baseType);
1408
+ const base = java_1.Type.isParameterized(mapped) ? mapped.type : mapped;
1409
+ // TypeScript accepts heritage cycles (`class A implements A`). Whichever edge closes one,
1410
+ // in mapping order, is dropped.
1411
+ return java_1.Type.isClass(base) && !this.inheritsFrom(base, classType, new Set()) ? base : undefined;
1412
+ }
1413
+ inheritsFrom(type, ancestor, seen) {
1414
+ if (type === ancestor) {
1415
+ return true;
1416
+ }
1417
+ if (seen.has(type)) {
1418
+ return false;
1419
+ }
1420
+ seen.add(type);
1421
+ return (type.supertype !== undefined && this.inheritsFrom(type.supertype, ancestor, seen)) ||
1422
+ type.interfaces.some(i => this.inheritsFrom(i, ancestor, seen));
1423
+ }
1424
+ addInterface(classType, baseType) {
1425
+ const iface = this.baseClass(classType, baseType);
1426
+ if (iface && !classType.interfaces.includes(iface)) {
1427
+ classType.interfaces.push(iface);
1428
+ }
1429
+ }
1422
1430
  /**
1423
1431
  * Populates the class type with members, methods, heritage, and type parameters
1424
1432
  * Since the shell is already in the cache, any recursive references will find it
1425
1433
  */
1426
1434
  populateClassType(classType, type) {
1427
- var _a, _b, _c, _d, _e, _f, _g, _h;
1435
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
1428
1436
  const symbol = (_a = type.getSymbol) === null || _a === void 0 ? void 0 : _a.call(type);
1437
+ const classSymbol = symbol && symbol.flags & typescript_1.default.SymbolFlags.Alias ?
1438
+ this.checker.getAliasedSymbol(symbol) : symbol;
1439
+ const classDeclaration = (_b = classSymbol === null || classSymbol === void 0 ? void 0 : classSymbol.declarations) === null || _b === void 0 ? void 0 : _b.find(typescript_1.default.isClassLike);
1429
1440
  // Try to get base types using TypeScript's getBaseTypes API
1430
1441
  // This works for both local and external types (from node_modules)
1431
1442
  if (type.flags & typescript_1.default.TypeFlags.Object) {
@@ -1434,7 +1445,7 @@ class JavaScriptTypeMapping {
1434
1445
  const objectType = type;
1435
1446
  if (objectType.objectFlags & (typescript_1.default.ObjectFlags.Class | typescript_1.default.ObjectFlags.Interface)) {
1436
1447
  try {
1437
- baseTypes = (_c = (_b = this.checker).getBaseTypes) === null || _c === void 0 ? void 0 : _c.call(_b, type);
1448
+ baseTypes = (_d = (_c = this.checker).getBaseTypes) === null || _d === void 0 ? void 0 : _d.call(_c, type);
1438
1449
  }
1439
1450
  catch (e) {
1440
1451
  // getBaseTypes might fail for some types, fall back to declaration-based extraction
@@ -1443,14 +1454,12 @@ class JavaScriptTypeMapping {
1443
1454
  else if (symbol) {
1444
1455
  // For constructor functions or type references, we need to get the actual class type
1445
1456
  // Try to get the type of the class itself (not the constructor or instance)
1446
- const classSymbol = symbol.flags & typescript_1.default.SymbolFlags.Alias ?
1447
- this.checker.getAliasedSymbol(symbol) : symbol;
1448
1457
  if (classSymbol && classSymbol.flags & (typescript_1.default.SymbolFlags.Class | typescript_1.default.SymbolFlags.Interface)) {
1449
1458
  // Get the type of the class declaration itself
1450
1459
  const declaredType = this.checker.getDeclaredTypeOfSymbol(classSymbol);
1451
1460
  if (declaredType && declaredType !== type) {
1452
1461
  try {
1453
- baseTypes = (_e = (_d = this.checker).getBaseTypes) === null || _e === void 0 ? void 0 : _e.call(_d, declaredType);
1462
+ baseTypes = (_f = (_e = this.checker).getBaseTypes) === null || _f === void 0 ? void 0 : _f.call(_e, declaredType);
1454
1463
  }
1455
1464
  catch (e) {
1456
1465
  // getBaseTypes might fail, fall back to declaration-based extraction
@@ -1463,7 +1472,7 @@ class JavaScriptTypeMapping {
1463
1472
  const instanceType = this.checker.getDeclaredTypeOfSymbol(classSymbol);
1464
1473
  if (instanceType && instanceType !== type) {
1465
1474
  try {
1466
- baseTypes = (_g = (_f = this.checker).getBaseTypes) === null || _g === void 0 ? void 0 : _g.call(_f, instanceType);
1475
+ baseTypes = (_h = (_g = this.checker).getBaseTypes) === null || _h === void 0 ? void 0 : _h.call(_g, instanceType);
1467
1476
  }
1468
1477
  catch (e) {
1469
1478
  // getBaseTypes might fail, fall back to declaration-based extraction
@@ -1472,34 +1481,26 @@ class JavaScriptTypeMapping {
1472
1481
  }
1473
1482
  }
1474
1483
  if (baseTypes && baseTypes.length > 0) {
1475
- // For classes, the first base type is usually the superclass
1476
- // Additional base types are interfaces
1477
- if (classType.classKind === java_1.Type.Class.Kind.Class) {
1478
- const firstBase = this.getType(baseTypes[0]);
1479
- // Handle both Class and Parameterized (e.g., Component<Props>)
1480
- if (java_1.Type.isClass(firstBase)) {
1481
- classType.supertype = firstBase;
1482
- }
1483
- else if (java_1.Type.isParameterized(firstBase)) {
1484
- // For parameterized types, use the base class as the supertype
1485
- classType.supertype = firstBase.type;
1486
- }
1487
- // Rest are interfaces
1488
- for (let i = 1; i < baseTypes.length; i++) {
1489
- const interfaceType = this.getType(baseTypes[i]);
1490
- if (java_1.Type.isClass(interfaceType)) {
1491
- classType.interfaces.push(interfaceType);
1492
- }
1484
+ // A merged interface's bases follow the class's, so the first is a superclass only beside `extends`
1485
+ let interfaces = baseTypes;
1486
+ if (classType.classKind === java_1.Type.Class.Kind.Class && (!classDeclaration ||
1487
+ ((_j = classDeclaration.heritageClauses) === null || _j === void 0 ? void 0 : _j.some(c => c.token === typescript_1.default.SyntaxKind.ExtendsKeyword)))) {
1488
+ const supertype = this.baseClass(classType, baseTypes[0]);
1489
+ if (supertype) {
1490
+ classType.supertype = supertype;
1493
1491
  }
1492
+ interfaces = baseTypes.slice(1);
1494
1493
  }
1495
- else {
1496
- // For interfaces, all base types are extended interfaces
1497
- for (const baseType of baseTypes) {
1498
- const interfaceType = this.getType(baseType);
1499
- if (java_1.Type.isClass(interfaceType)) {
1500
- classType.interfaces.push(interfaceType);
1501
- }
1502
- }
1494
+ for (const baseType of interfaces) {
1495
+ this.addInterface(classType, baseType);
1496
+ }
1497
+ }
1498
+ }
1499
+ // `getBaseTypes` omits a class's `implements` clause
1500
+ for (const clause of (_k = classDeclaration === null || classDeclaration === void 0 ? void 0 : classDeclaration.heritageClauses) !== null && _k !== void 0 ? _k : []) {
1501
+ if (clause.token === typescript_1.default.SyntaxKind.ImplementsKeyword) {
1502
+ for (const implemented of clause.types) {
1503
+ this.addInterface(classType, this.checker.getTypeAtLocation(implemented));
1503
1504
  }
1504
1505
  }
1505
1506
  }
@@ -1521,7 +1522,7 @@ class JavaScriptTypeMapping {
1521
1522
  // Get properties and methods
1522
1523
  const properties = this.checker.getPropertiesOfType(type);
1523
1524
  for (const prop of properties) {
1524
- const declaration = prop.valueDeclaration || ((_h = prop.declarations) === null || _h === void 0 ? void 0 : _h[0]);
1525
+ const declaration = prop.valueDeclaration || ((_l = prop.declarations) === null || _l === void 0 ? void 0 : _l[0]);
1525
1526
  if (!declaration) {
1526
1527
  // Skip properties without declarations (synthetic/built-in properties)
1527
1528
  continue;
@@ -1536,6 +1537,7 @@ class JavaScriptTypeMapping {
1536
1537
  const propType = this.checker.getTypeOfSymbolAtLocation(prop, declaration);
1537
1538
  const variable = {
1538
1539
  kind: java_1.Type.Kind.Variable,
1540
+ flags: 0,
1539
1541
  name: prop.getName(),
1540
1542
  owner: classType, // Cyclic reference to the containing class (already in cache)
1541
1543
  type: this.getType(propType), // This will find classType in cache if it's recursive
@@ -1588,6 +1590,10 @@ class JavaScriptTypeMapping {
1588
1590
  else if (type.flags & (typescript_1.default.TypeFlags.Boolean | typescript_1.default.TypeFlags.BooleanLiteral | typescript_1.default.TypeFlags.BooleanLike)) {
1589
1591
  return java_1.Type.Primitive.Boolean;
1590
1592
  }
1593
+ else if (type.flags & typescript_1.default.TypeFlags.ESSymbolLike && this.symbolWrapperType) {
1594
+ // Java has no primitive for a symbol, so it is typed as the class it boxes to.
1595
+ return this.getType(this.symbolWrapperType);
1596
+ }
1591
1597
  // Check for type aliases that may resolve to primitives
1592
1598
  const symbol = (_a = type.getSymbol) === null || _a === void 0 ? void 0 : _a.call(type);
1593
1599
  if (symbol && symbol.flags & typescript_1.default.SymbolFlags.TypeAlias) {
@@ -1687,6 +1693,19 @@ class JavaScriptTypeMapping {
1687
1693
  toJSON: typeSignatureToJSON
1688
1694
  };
1689
1695
  }
1696
+ createFunctionType(type, signature, cacheKey) {
1697
+ // Shell-cache: Create stub, cache it, then populate (prevents cycles)
1698
+ const functionType = this.createEmptyFunctionType();
1699
+ this.typeCache.set(cacheKey, functionType);
1700
+ this.functionTypesInProgress.add(type.symbol);
1701
+ try {
1702
+ this.populateFunctionType(functionType, signature);
1703
+ }
1704
+ finally {
1705
+ this.functionTypesInProgress.delete(type.symbol);
1706
+ }
1707
+ return functionType;
1708
+ }
1690
1709
  /**
1691
1710
  * Create an empty function type shell with FQN 𝑓.
1692
1711
  * The shell will be populated later to handle circular references.