@openrewrite/rewrite 8.92.17 → 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 (199) 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 +116 -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/index.d.ts +4 -2
  42. package/dist/javascript/index.d.ts.map +1 -1
  43. package/dist/javascript/index.js +10 -1
  44. package/dist/javascript/index.js.map +1 -1
  45. package/dist/javascript/markers.d.ts.map +1 -1
  46. package/dist/javascript/markers.js +64 -0
  47. package/dist/javascript/markers.js.map +1 -1
  48. package/dist/javascript/method-matcher.d.ts +13 -2
  49. package/dist/javascript/method-matcher.d.ts.map +1 -1
  50. package/dist/javascript/method-matcher.js +32 -19
  51. package/dist/javascript/method-matcher.js.map +1 -1
  52. package/dist/javascript/package-name.d.ts +6 -0
  53. package/dist/javascript/package-name.d.ts.map +1 -0
  54. package/dist/javascript/package-name.js +47 -0
  55. package/dist/javascript/package-name.js.map +1 -0
  56. package/dist/javascript/preconditions.d.ts +4 -1
  57. package/dist/javascript/preconditions.d.ts.map +1 -1
  58. package/dist/javascript/preconditions.js +7 -4
  59. package/dist/javascript/preconditions.js.map +1 -1
  60. package/dist/javascript/recipes/change-method-target-to-import.d.ts +29 -0
  61. package/dist/javascript/recipes/change-method-target-to-import.d.ts.map +1 -0
  62. package/dist/javascript/recipes/change-method-target-to-import.js +164 -0
  63. package/dist/javascript/recipes/change-method-target-to-import.js.map +1 -0
  64. package/dist/javascript/recipes/index.d.ts +1 -0
  65. package/dist/javascript/recipes/index.d.ts.map +1 -1
  66. package/dist/javascript/recipes/index.js +1 -0
  67. package/dist/javascript/recipes/index.js.map +1 -1
  68. package/dist/javascript/scope.d.ts +60 -16
  69. package/dist/javascript/scope.d.ts.map +1 -1
  70. package/dist/javascript/scope.js +596 -131
  71. package/dist/javascript/scope.js.map +1 -1
  72. package/dist/javascript/search/uses-method.d.ts +1 -1
  73. package/dist/javascript/search/uses-method.d.ts.map +1 -1
  74. package/dist/javascript/search/uses-method.js +2 -2
  75. package/dist/javascript/search/uses-method.js.map +1 -1
  76. package/dist/javascript/search/uses-type.d.ts +14 -1
  77. package/dist/javascript/search/uses-type.d.ts.map +1 -1
  78. package/dist/javascript/search/uses-type.js +24 -9
  79. package/dist/javascript/search/uses-type.js.map +1 -1
  80. package/dist/javascript/templating/bindings.d.ts +1 -1
  81. package/dist/javascript/templating/bindings.d.ts.map +1 -1
  82. package/dist/javascript/templating/bindings.js +10 -50
  83. package/dist/javascript/templating/bindings.js.map +1 -1
  84. package/dist/javascript/templating/comparator.d.ts +8 -11
  85. package/dist/javascript/templating/comparator.d.ts.map +1 -1
  86. package/dist/javascript/templating/comparator.js +12 -110
  87. package/dist/javascript/templating/comparator.js.map +1 -1
  88. package/dist/javascript/templating/engine.d.ts +34 -24
  89. package/dist/javascript/templating/engine.d.ts.map +1 -1
  90. package/dist/javascript/templating/engine.js +200 -112
  91. package/dist/javascript/templating/engine.js.map +1 -1
  92. package/dist/javascript/templating/pattern.d.ts +11 -5
  93. package/dist/javascript/templating/pattern.d.ts.map +1 -1
  94. package/dist/javascript/templating/pattern.js +86 -20
  95. package/dist/javascript/templating/pattern.js.map +1 -1
  96. package/dist/javascript/templating/placeholder-replacement.d.ts +34 -3
  97. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
  98. package/dist/javascript/templating/placeholder-replacement.js +126 -60
  99. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  100. package/dist/javascript/templating/precedence.d.ts +3 -1
  101. package/dist/javascript/templating/precedence.d.ts.map +1 -1
  102. package/dist/javascript/templating/precedence.js +28 -8
  103. package/dist/javascript/templating/precedence.js.map +1 -1
  104. package/dist/javascript/templating/template.d.ts +7 -6
  105. package/dist/javascript/templating/template.d.ts.map +1 -1
  106. package/dist/javascript/templating/template.js +31 -28
  107. package/dist/javascript/templating/template.js.map +1 -1
  108. package/dist/javascript/templating/types.d.ts +6 -3
  109. package/dist/javascript/templating/types.d.ts.map +1 -1
  110. package/dist/javascript/templating/utils.d.ts +10 -1
  111. package/dist/javascript/templating/utils.d.ts.map +1 -1
  112. package/dist/javascript/templating/utils.js +22 -3
  113. package/dist/javascript/templating/utils.js.map +1 -1
  114. package/dist/javascript/tree-debug.d.ts +2 -0
  115. package/dist/javascript/tree-debug.d.ts.map +1 -1
  116. package/dist/javascript/tree-debug.js +6 -0
  117. package/dist/javascript/tree-debug.js.map +1 -1
  118. package/dist/javascript/tsconfig.d.ts.map +1 -1
  119. package/dist/javascript/tsconfig.js +7 -17
  120. package/dist/javascript/tsconfig.js.map +1 -1
  121. package/dist/javascript/type-mapping.d.ts +34 -16
  122. package/dist/javascript/type-mapping.d.ts.map +1 -1
  123. package/dist/javascript/type-mapping.js +253 -249
  124. package/dist/javascript/type-mapping.js.map +1 -1
  125. package/dist/javascript/type-report-cli.d.ts +7 -0
  126. package/dist/javascript/type-report-cli.d.ts.map +1 -0
  127. package/dist/javascript/type-report-cli.js +129 -0
  128. package/dist/javascript/type-report-cli.js.map +1 -0
  129. package/dist/javascript/type-report.d.ts +61 -0
  130. package/dist/javascript/type-report.d.ts.map +1 -0
  131. package/dist/javascript/type-report.js +488 -0
  132. package/dist/javascript/type-report.js.map +1 -0
  133. package/dist/markers.d.ts +4 -0
  134. package/dist/markers.d.ts.map +1 -1
  135. package/dist/markers.js +8 -0
  136. package/dist/markers.js.map +1 -1
  137. package/dist/recipe.d.ts +5 -0
  138. package/dist/recipe.d.ts.map +1 -1
  139. package/dist/recipe.js +5 -0
  140. package/dist/recipe.js.map +1 -1
  141. package/dist/rewrite-javascript-version.txt +1 -1
  142. package/dist/rpc/queue.d.ts +16 -0
  143. package/dist/rpc/queue.d.ts.map +1 -1
  144. package/dist/rpc/queue.js +27 -9
  145. package/dist/rpc/queue.js.map +1 -1
  146. package/dist/rpc/request/prepare-recipe.d.ts +3 -1
  147. package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
  148. package/dist/rpc/request/prepare-recipe.js +13 -6
  149. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  150. package/dist/search/is-source-file.d.ts +1 -0
  151. package/dist/search/is-source-file.d.ts.map +1 -1
  152. package/dist/search/is-source-file.js +7 -2
  153. package/dist/search/is-source-file.js.map +1 -1
  154. package/dist/test/rewrite-test.d.ts +5 -0
  155. package/dist/test/rewrite-test.d.ts.map +1 -1
  156. package/dist/test/rewrite-test.js +14 -3
  157. package/dist/test/rewrite-test.js.map +1 -1
  158. package/package.json +4 -3
  159. package/src/index.ts +3 -1
  160. package/src/java/formatting-utils.ts +5 -4
  161. package/src/java/rpc.ts +2 -0
  162. package/src/java/tree.ts +15 -0
  163. package/src/java/type.ts +19 -2
  164. package/src/javascript/add-import.ts +338 -152
  165. package/src/javascript/amd.ts +28 -12
  166. package/src/javascript/autodetect.ts +32 -41
  167. package/src/javascript/binding.ts +64 -22
  168. package/src/javascript/comparator.ts +119 -43
  169. package/src/javascript/format/format.ts +9 -0
  170. package/src/javascript/index.ts +6 -3
  171. package/src/javascript/markers.ts +43 -1
  172. package/src/javascript/method-matcher.ts +34 -22
  173. package/src/javascript/package-name.ts +45 -0
  174. package/src/javascript/preconditions.ts +7 -4
  175. package/src/javascript/recipes/change-method-target-to-import.ts +178 -0
  176. package/src/javascript/recipes/index.ts +1 -0
  177. package/src/javascript/scope.ts +705 -169
  178. package/src/javascript/search/uses-method.ts +2 -2
  179. package/src/javascript/search/uses-type.ts +30 -9
  180. package/src/javascript/templating/bindings.ts +13 -38
  181. package/src/javascript/templating/comparator.ts +16 -127
  182. package/src/javascript/templating/engine.ts +229 -127
  183. package/src/javascript/templating/pattern.ts +107 -28
  184. package/src/javascript/templating/placeholder-replacement.ts +154 -62
  185. package/src/javascript/templating/precedence.ts +33 -11
  186. package/src/javascript/templating/template.ts +35 -30
  187. package/src/javascript/templating/types.ts +6 -3
  188. package/src/javascript/templating/utils.ts +24 -2
  189. package/src/javascript/tree-debug.ts +9 -0
  190. package/src/javascript/tsconfig.ts +7 -17
  191. package/src/javascript/type-mapping.ts +258 -252
  192. package/src/javascript/type-report-cli.ts +96 -0
  193. package/src/javascript/type-report.ts +575 -0
  194. package/src/markers.ts +8 -0
  195. package/src/recipe.ts +6 -0
  196. package/src/rpc/queue.ts +44 -5
  197. package/src/rpc/request/prepare-recipe.ts +16 -6
  198. package/src/search/is-source-file.ts +8 -3
  199. 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
@@ -866,6 +855,27 @@ class JavaScriptTypeMapping {
866
855
  return java_1.Type.unknownType;
867
856
  }
868
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
+ }
869
879
  wrapperType(declaringType) {
870
880
  if (declaringType === java_1.Type.Primitive.String && this.stringWrapperType) {
871
881
  return this.getType(this.stringWrapperType);
@@ -882,7 +892,7 @@ class JavaScriptTypeMapping {
882
892
  }
883
893
  }
884
894
  methodType(node) {
885
- var _a, _b, _c, _d, _e, _f, _g;
895
+ var _a, _b, _c, _d, _e, _f, _g, _h;
886
896
  // An object literal is a `J.NewClass`, and `J.NewClass.getType()` reads
887
897
  // `constructorType.returnType`, as it does for a Java anonymous class.
888
898
  if (typescript_1.default.isObjectLiteralExpression(node)) {
@@ -972,8 +982,11 @@ class JavaScriptTypeMapping {
972
982
  const receiverBinding = isImport ? this.importBinding(node.expression.expression) : undefined;
973
983
  const anonymous = !mappedType || mappedType.kind !== java_1.Type.Kind.Class ||
974
984
  mappedType.fullyQualifiedName.startsWith('{');
975
- // Handle different types
976
- 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) {
977
990
  declaringType = this.moduleType(receiverBinding.module);
978
991
  if (methodName === 'default') {
979
992
  methodName = '<default>';
@@ -1048,56 +1061,36 @@ class JavaScriptTypeMapping {
1048
1061
  moduleSpecifier = aliasedParentSymbol.name;
1049
1062
  }
1050
1063
  else {
1051
- // Now find the import declaration to get the module specifier
1052
- if (exprSymbol.declarations && exprSymbol.declarations.length > 0) {
1053
- let importNode = exprSymbol.declarations[0];
1054
- // Traverse up to find the ImportDeclaration
1055
- while (importNode && !typescript_1.default.isImportDeclaration(importNode)) {
1056
- importNode = importNode.parent;
1057
- }
1058
- if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
1059
- const importDeclNode = importNode;
1060
- if (typescript_1.default.isStringLiteral(importDeclNode.moduleSpecifier)) {
1061
- moduleSpecifier = importDeclNode.moduleSpecifier.text;
1062
- }
1063
- }
1064
- }
1064
+ moduleSpecifier = this.importedModule((_b = exprSymbol.declarations) === null || _b === void 0 ? void 0 : _b[0]);
1065
1065
  }
1066
1066
  }
1067
1067
  }
1068
- 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) {
1069
1074
  // This is an imported function - use the module specifier as declaring type
1070
- if (moduleSpecifier.startsWith('node:')) {
1071
- // Node.js built-in module
1072
- declaringType = {
1073
- kind: java_1.Type.Kind.Class,
1074
- flags: 0, // TODO - determine flags
1075
- fullyQualifiedName: 'node'
1076
- };
1077
- 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;
1078
1089
  }
1079
1090
  else {
1080
- // Regular module import
1081
- declaringType = {
1082
- kind: java_1.Type.Kind.Class,
1083
- flags: 0, // TODO - determine flags
1084
- fullyQualifiedName: moduleSpecifier
1085
- };
1086
- // A default import binds an `ImportClause`; its aliased symbol carries the internal
1087
- // name of the default export (e.g. `e` for express), so represent it as `<default>`.
1088
- // Named imports (`ImportSpecifier`) keep the original exported name.
1089
- 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;
1090
- if (isDefaultImport) {
1091
- methodName = '<default>';
1092
- }
1093
- else if ((_d = aliasedSymbol === null || aliasedSymbol === void 0 ? void 0 : aliasedSymbol.declarations) === null || _d === void 0 ? void 0 : _d.length) {
1094
- methodName = aliasedSymbol.name;
1095
- }
1096
- else {
1097
- // A package without type declarations resolves the import to the checker's
1098
- // `unknown` symbol, so the exported name comes from the import itself.
1099
- 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;
1100
- }
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;
1101
1094
  }
1102
1095
  }
1103
1096
  else if (this.requiredModuleOfExpression(node.expression)) {
@@ -1200,24 +1193,7 @@ class JavaScriptTypeMapping {
1200
1193
  return undefined;
1201
1194
  }
1202
1195
  methodName = node.name ? node.name.getText() : "<anonymous>";
1203
- // Derive declaring type from source file module path (like Go's type_mapper.go).
1204
- // Use the same relativization as getFullyQualifiedName() so that declarations
1205
- // and invocations produce matching FQNs.
1206
- let moduleFqn;
1207
- const fileName = node.getSourceFile().fileName;
1208
- if (this.sourceRoot && path.isAbsolute(fileName)) {
1209
- moduleFqn = path.relative(this.sourceRoot, fileName);
1210
- }
1211
- else {
1212
- moduleFqn = fileName;
1213
- }
1214
- // Strip file extension to get the module name
1215
- moduleFqn = moduleFqn.replace(/\.[^/.]+$/, '');
1216
- declaringType = {
1217
- kind: java_1.Type.Kind.Class,
1218
- flags: 0,
1219
- fullyQualifiedName: moduleFqn
1220
- };
1196
+ declaringType = this.sourceModuleType(node.getSourceFile());
1221
1197
  // Get type parameters from node
1222
1198
  if (node.typeParameters) {
1223
1199
  for (const tp of node.typeParameters) {
@@ -1253,33 +1229,7 @@ class JavaScriptTypeMapping {
1253
1229
  if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
1254
1230
  const aliasedSymbol = this.checker.getAliasedSymbol(symbol);
1255
1231
  if (aliasedSymbol && aliasedSymbol !== symbol && symbol.declarations && symbol.declarations.length > 0) {
1256
- // Try to find the import declaration to get the module specifier
1257
- let importNode = symbol.declarations[0];
1258
- // Traverse up to find the ImportDeclaration or ImportSpecifier
1259
- while (importNode && importNode.parent && !typescript_1.default.isImportDeclaration(importNode) && !typescript_1.default.isImportSpecifier(importNode)) {
1260
- importNode = importNode.parent;
1261
- }
1262
- let moduleSpecifier;
1263
- if (importNode && typescript_1.default.isImportSpecifier(importNode)) {
1264
- // Named import like: import { ClipLoader } from 'react-spinners'
1265
- // ImportSpecifier -> NamedImports -> ImportClause -> ImportDeclaration
1266
- const namedImports = importNode.parent; // NamedImports
1267
- if (namedImports && typescript_1.default.isNamedImports(namedImports)) {
1268
- const importClause = namedImports.parent; // ImportClause
1269
- if (importClause && typescript_1.default.isImportClause(importClause)) {
1270
- const importDecl = importClause.parent; // ImportDeclaration
1271
- if (importDecl && typescript_1.default.isImportDeclaration(importDecl) && typescript_1.default.isStringLiteral(importDecl.moduleSpecifier)) {
1272
- moduleSpecifier = importDecl.moduleSpecifier.text;
1273
- }
1274
- }
1275
- }
1276
- }
1277
- else if (importNode && typescript_1.default.isImportDeclaration(importNode)) {
1278
- // Default or namespace import
1279
- if (typescript_1.default.isStringLiteral(importNode.moduleSpecifier)) {
1280
- moduleSpecifier = importNode.moduleSpecifier.text;
1281
- }
1282
- }
1232
+ const moduleSpecifier = this.importedModule(symbol.declarations[0]);
1283
1233
  if (moduleSpecifier) {
1284
1234
  // Build the fully qualified name from module specifier + symbol name
1285
1235
  const symbolName = symbol.getName();
@@ -1291,42 +1241,34 @@ class JavaScriptTypeMapping {
1291
1241
  // This returns names with quotes that we need to clean up
1292
1242
  // e.g., '"React"."Component"' -> 'React.Component'
1293
1243
  const tsQualifiedName = this.checker.getFullyQualifiedName(symbol);
1294
- let cleanedName = tsQualifiedName.replace(/"/g, '');
1295
- // Check if this is a file path from node_modules (happens with some packages)
1296
- // TypeScript sometimes returns full paths instead of module names
1297
- 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
1298
1253
  // Extract the module name from the path
1299
1254
  // Example: /private/var/.../node_modules/react-spinners/src/index.ClipLoader
1300
1255
  // Should become: react-spinners.ClipLoader
1301
1256
  const nodeModulesIndex = cleanedName.indexOf('node_modules/');
1302
1257
  const afterNodeModules = cleanedName.substring(nodeModulesIndex + 'node_modules/'.length);
1303
- // Split by '/' to get parts of the path
1304
- const pathParts = afterNodeModules.split('/');
1305
- if (pathParts.length > 0) {
1306
- // First part is the package name (might be scoped like @types)
1307
- let packageName = pathParts[0];
1308
- // Handle scoped packages
1309
- if (packageName.startsWith('@') && pathParts.length > 1) {
1310
- packageName = `${packageName}/${pathParts[1]}`;
1311
- }
1312
- // Normalize `@types/<pkg>` to the importable specifier `<pkg>` so that types
1313
- // reached transitively (e.g. a call's return type, resolved via the declaration
1314
- // file's node_modules path) match the names used for directly imported types.
1315
- packageName = this.normalizePackageName(packageName);
1316
- // The symbol name is appended to the declaration file's path, so it is whatever
1317
- // follows the last dot of the final path segment. Directory names carry dots of
1318
- // their own — `.pnpm`, `.yarn`, a hidden parent such as `.claude`, a versioned
1319
- // pnpm directory — so a search over the whole path would split there instead and
1320
- // fold most of the path into the name.
1321
- const lastSegmentIndex = cleanedName.lastIndexOf('/') + 1;
1322
- const lastDotIndex = cleanedName.lastIndexOf('.');
1323
- if (lastDotIndex > lastSegmentIndex) {
1324
- const symbolName = cleanedName.substring(lastDotIndex + 1);
1325
- cleanedName = `${packageName}.${symbolName}`;
1326
- }
1327
- else {
1328
- cleanedName = packageName;
1329
- }
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;
1330
1272
  }
1331
1273
  }
1332
1274
  else if (path.isAbsolute(cleanedName)) {
@@ -1366,7 +1308,7 @@ class JavaScriptTypeMapping {
1366
1308
  // Preserved as-is:
1367
1309
  // - UMD globals (`export as namespace X`, e.g. React, lodash `_`, jQuery `$`): the
1368
1310
  // namespace name is the conventional public identifier;
1369
- // - `global.*` (TypeScript's marker for ambient globals);
1311
+ // - `global.*`, a `declare global` augmentation, whose prefix is dropped below;
1370
1312
  // - namespaces that already match the package name, and any non-node_modules type.
1371
1313
  const namespaceName = cleanedName.substring(0, cleanedName.indexOf('.'));
1372
1314
  if (namespaceName !== 'global') {
@@ -1380,10 +1322,37 @@ class JavaScriptTypeMapping {
1380
1322
  }
1381
1323
  }
1382
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
+ }
1383
1329
  return cleanedName.endsWith('Constructor') ?
1384
1330
  cleanedName.substring(0, cleanedName.length - 'Constructor'.length) :
1385
1331
  cleanedName;
1386
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
+ }
1387
1356
  /**
1388
1357
  * Whether {@code namespaceName} is exposed as a UMD global from the given declaration file
1389
1358
  * (e.g. `export as namespace React`). The namespace name of a UMD global is the conventional
@@ -1434,13 +1403,40 @@ class JavaScriptTypeMapping {
1434
1403
  toJSON: typeSignatureToJSON
1435
1404
  };
1436
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
+ }
1437
1430
  /**
1438
1431
  * Populates the class type with members, methods, heritage, and type parameters
1439
1432
  * Since the shell is already in the cache, any recursive references will find it
1440
1433
  */
1441
1434
  populateClassType(classType, type) {
1442
- var _a, _b, _c, _d, _e, _f, _g, _h;
1435
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
1443
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);
1444
1440
  // Try to get base types using TypeScript's getBaseTypes API
1445
1441
  // This works for both local and external types (from node_modules)
1446
1442
  if (type.flags & typescript_1.default.TypeFlags.Object) {
@@ -1449,7 +1445,7 @@ class JavaScriptTypeMapping {
1449
1445
  const objectType = type;
1450
1446
  if (objectType.objectFlags & (typescript_1.default.ObjectFlags.Class | typescript_1.default.ObjectFlags.Interface)) {
1451
1447
  try {
1452
- 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);
1453
1449
  }
1454
1450
  catch (e) {
1455
1451
  // getBaseTypes might fail for some types, fall back to declaration-based extraction
@@ -1458,14 +1454,12 @@ class JavaScriptTypeMapping {
1458
1454
  else if (symbol) {
1459
1455
  // For constructor functions or type references, we need to get the actual class type
1460
1456
  // Try to get the type of the class itself (not the constructor or instance)
1461
- const classSymbol = symbol.flags & typescript_1.default.SymbolFlags.Alias ?
1462
- this.checker.getAliasedSymbol(symbol) : symbol;
1463
1457
  if (classSymbol && classSymbol.flags & (typescript_1.default.SymbolFlags.Class | typescript_1.default.SymbolFlags.Interface)) {
1464
1458
  // Get the type of the class declaration itself
1465
1459
  const declaredType = this.checker.getDeclaredTypeOfSymbol(classSymbol);
1466
1460
  if (declaredType && declaredType !== type) {
1467
1461
  try {
1468
- 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);
1469
1463
  }
1470
1464
  catch (e) {
1471
1465
  // getBaseTypes might fail, fall back to declaration-based extraction
@@ -1478,7 +1472,7 @@ class JavaScriptTypeMapping {
1478
1472
  const instanceType = this.checker.getDeclaredTypeOfSymbol(classSymbol);
1479
1473
  if (instanceType && instanceType !== type) {
1480
1474
  try {
1481
- 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);
1482
1476
  }
1483
1477
  catch (e) {
1484
1478
  // getBaseTypes might fail, fall back to declaration-based extraction
@@ -1487,34 +1481,26 @@ class JavaScriptTypeMapping {
1487
1481
  }
1488
1482
  }
1489
1483
  if (baseTypes && baseTypes.length > 0) {
1490
- // For classes, the first base type is usually the superclass
1491
- // Additional base types are interfaces
1492
- if (classType.classKind === java_1.Type.Class.Kind.Class) {
1493
- const firstBase = this.getType(baseTypes[0]);
1494
- // Handle both Class and Parameterized (e.g., Component<Props>)
1495
- if (java_1.Type.isClass(firstBase)) {
1496
- classType.supertype = firstBase;
1497
- }
1498
- else if (java_1.Type.isParameterized(firstBase)) {
1499
- // For parameterized types, use the base class as the supertype
1500
- classType.supertype = firstBase.type;
1501
- }
1502
- // Rest are interfaces
1503
- for (let i = 1; i < baseTypes.length; i++) {
1504
- const interfaceType = this.getType(baseTypes[i]);
1505
- if (java_1.Type.isClass(interfaceType)) {
1506
- classType.interfaces.push(interfaceType);
1507
- }
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;
1508
1491
  }
1492
+ interfaces = baseTypes.slice(1);
1509
1493
  }
1510
- else {
1511
- // For interfaces, all base types are extended interfaces
1512
- for (const baseType of baseTypes) {
1513
- const interfaceType = this.getType(baseType);
1514
- if (java_1.Type.isClass(interfaceType)) {
1515
- classType.interfaces.push(interfaceType);
1516
- }
1517
- }
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));
1518
1504
  }
1519
1505
  }
1520
1506
  }
@@ -1536,7 +1522,7 @@ class JavaScriptTypeMapping {
1536
1522
  // Get properties and methods
1537
1523
  const properties = this.checker.getPropertiesOfType(type);
1538
1524
  for (const prop of properties) {
1539
- 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]);
1540
1526
  if (!declaration) {
1541
1527
  // Skip properties without declarations (synthetic/built-in properties)
1542
1528
  continue;
@@ -1551,6 +1537,7 @@ class JavaScriptTypeMapping {
1551
1537
  const propType = this.checker.getTypeOfSymbolAtLocation(prop, declaration);
1552
1538
  const variable = {
1553
1539
  kind: java_1.Type.Kind.Variable,
1540
+ flags: 0,
1554
1541
  name: prop.getName(),
1555
1542
  owner: classType, // Cyclic reference to the containing class (already in cache)
1556
1543
  type: this.getType(propType), // This will find classType in cache if it's recursive
@@ -1603,6 +1590,10 @@ class JavaScriptTypeMapping {
1603
1590
  else if (type.flags & (typescript_1.default.TypeFlags.Boolean | typescript_1.default.TypeFlags.BooleanLiteral | typescript_1.default.TypeFlags.BooleanLike)) {
1604
1591
  return java_1.Type.Primitive.Boolean;
1605
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
+ }
1606
1597
  // Check for type aliases that may resolve to primitives
1607
1598
  const symbol = (_a = type.getSymbol) === null || _a === void 0 ? void 0 : _a.call(type);
1608
1599
  if (symbol && symbol.flags & typescript_1.default.SymbolFlags.TypeAlias) {
@@ -1702,6 +1693,19 @@ class JavaScriptTypeMapping {
1702
1693
  toJSON: typeSignatureToJSON
1703
1694
  };
1704
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
+ }
1705
1709
  /**
1706
1710
  * Create an empty function type shell with FQN 𝑓.
1707
1711
  * The shell will be populated later to handle circular references.