@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.
- package/README.md +48 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/java/formatting-utils.d.ts +2 -1
- package/dist/java/formatting-utils.d.ts.map +1 -1
- package/dist/java/formatting-utils.js +4 -3
- package/dist/java/formatting-utils.js.map +1 -1
- package/dist/java/rpc.d.ts.map +1 -1
- package/dist/java/rpc.js +2 -0
- package/dist/java/rpc.js.map +1 -1
- package/dist/java/tree.d.ts +8 -0
- package/dist/java/tree.d.ts.map +1 -1
- package/dist/java/tree.js +11 -1
- package/dist/java/tree.js.map +1 -1
- package/dist/java/type.d.ts +7 -1
- package/dist/java/type.d.ts.map +1 -1
- package/dist/java/type.js +16 -1
- package/dist/java/type.js.map +1 -1
- package/dist/javascript/add-import.d.ts +27 -21
- package/dist/javascript/add-import.d.ts.map +1 -1
- package/dist/javascript/add-import.js +303 -143
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/amd.d.ts.map +1 -1
- package/dist/javascript/amd.js +25 -10
- package/dist/javascript/amd.js.map +1 -1
- package/dist/javascript/autodetect.js +36 -45
- package/dist/javascript/autodetect.js.map +1 -1
- package/dist/javascript/binding.d.ts +6 -4
- package/dist/javascript/binding.d.ts.map +1 -1
- package/dist/javascript/binding.js +54 -18
- package/dist/javascript/binding.js.map +1 -1
- package/dist/javascript/comparator.d.ts +22 -5
- package/dist/javascript/comparator.d.ts.map +1 -1
- package/dist/javascript/comparator.js +120 -38
- package/dist/javascript/comparator.js.map +1 -1
- package/dist/javascript/format/format.d.ts +2 -0
- package/dist/javascript/format/format.d.ts.map +1 -1
- package/dist/javascript/format/format.js +11 -1
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.js +31 -4
- package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
- package/dist/javascript/index.d.ts +4 -2
- package/dist/javascript/index.d.ts.map +1 -1
- package/dist/javascript/index.js +10 -1
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/markers.d.ts +12 -0
- package/dist/javascript/markers.d.ts.map +1 -1
- package/dist/javascript/markers.js +81 -2
- package/dist/javascript/markers.js.map +1 -1
- package/dist/javascript/method-matcher.d.ts +13 -2
- package/dist/javascript/method-matcher.d.ts.map +1 -1
- package/dist/javascript/method-matcher.js +32 -19
- package/dist/javascript/method-matcher.js.map +1 -1
- package/dist/javascript/node-resolution-result.js +3 -2
- package/dist/javascript/node-resolution-result.js.map +1 -1
- package/dist/javascript/package-name.d.ts +6 -0
- package/dist/javascript/package-name.d.ts.map +1 -0
- package/dist/javascript/package-name.js +47 -0
- package/dist/javascript/package-name.js.map +1 -0
- package/dist/javascript/parser.d.ts +9 -0
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +185 -88
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/preconditions.d.ts +4 -1
- package/dist/javascript/preconditions.d.ts.map +1 -1
- package/dist/javascript/preconditions.js +7 -4
- package/dist/javascript/preconditions.js.map +1 -1
- package/dist/javascript/print.d.ts +10 -1
- package/dist/javascript/print.d.ts.map +1 -1
- package/dist/javascript/print.js +120 -77
- package/dist/javascript/print.js.map +1 -1
- package/dist/javascript/recipes/change-method-target-to-import.d.ts +29 -0
- package/dist/javascript/recipes/change-method-target-to-import.d.ts.map +1 -0
- package/dist/javascript/recipes/change-method-target-to-import.js +164 -0
- package/dist/javascript/recipes/change-method-target-to-import.js.map +1 -0
- package/dist/javascript/recipes/index.d.ts +1 -0
- package/dist/javascript/recipes/index.d.ts.map +1 -1
- package/dist/javascript/recipes/index.js +1 -0
- package/dist/javascript/recipes/index.js.map +1 -1
- package/dist/javascript/scope.d.ts +60 -16
- package/dist/javascript/scope.d.ts.map +1 -1
- package/dist/javascript/scope.js +596 -131
- package/dist/javascript/scope.js.map +1 -1
- package/dist/javascript/search/uses-method.d.ts +1 -1
- package/dist/javascript/search/uses-method.d.ts.map +1 -1
- package/dist/javascript/search/uses-method.js +2 -2
- package/dist/javascript/search/uses-method.js.map +1 -1
- package/dist/javascript/search/uses-type.d.ts +14 -1
- package/dist/javascript/search/uses-type.d.ts.map +1 -1
- package/dist/javascript/search/uses-type.js +24 -9
- package/dist/javascript/search/uses-type.js.map +1 -1
- package/dist/javascript/templating/bindings.d.ts +1 -1
- package/dist/javascript/templating/bindings.d.ts.map +1 -1
- package/dist/javascript/templating/bindings.js +10 -50
- package/dist/javascript/templating/bindings.js.map +1 -1
- package/dist/javascript/templating/comparator.d.ts +8 -11
- package/dist/javascript/templating/comparator.d.ts.map +1 -1
- package/dist/javascript/templating/comparator.js +12 -110
- package/dist/javascript/templating/comparator.js.map +1 -1
- package/dist/javascript/templating/engine.d.ts +34 -24
- package/dist/javascript/templating/engine.d.ts.map +1 -1
- package/dist/javascript/templating/engine.js +208 -115
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/pattern.d.ts +11 -5
- package/dist/javascript/templating/pattern.d.ts.map +1 -1
- package/dist/javascript/templating/pattern.js +86 -20
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.d.ts +34 -3
- package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.js +126 -60
- package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
- package/dist/javascript/templating/precedence.d.ts +3 -1
- package/dist/javascript/templating/precedence.d.ts.map +1 -1
- package/dist/javascript/templating/precedence.js +28 -8
- package/dist/javascript/templating/precedence.js.map +1 -1
- package/dist/javascript/templating/template.d.ts +7 -6
- package/dist/javascript/templating/template.d.ts.map +1 -1
- package/dist/javascript/templating/template.js +31 -28
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/templating/types.d.ts +6 -3
- package/dist/javascript/templating/types.d.ts.map +1 -1
- package/dist/javascript/templating/utils.d.ts +10 -1
- package/dist/javascript/templating/utils.d.ts.map +1 -1
- package/dist/javascript/templating/utils.js +22 -3
- package/dist/javascript/templating/utils.js.map +1 -1
- package/dist/javascript/tree-debug.d.ts +2 -0
- package/dist/javascript/tree-debug.d.ts.map +1 -1
- package/dist/javascript/tree-debug.js +6 -0
- package/dist/javascript/tree-debug.js.map +1 -1
- package/dist/javascript/tsconfig.d.ts.map +1 -1
- package/dist/javascript/tsconfig.js +7 -17
- package/dist/javascript/tsconfig.js.map +1 -1
- package/dist/javascript/type-mapping.d.ts +35 -16
- package/dist/javascript/type-mapping.d.ts.map +1 -1
- package/dist/javascript/type-mapping.js +271 -252
- package/dist/javascript/type-mapping.js.map +1 -1
- package/dist/javascript/type-report-cli.d.ts +7 -0
- package/dist/javascript/type-report-cli.d.ts.map +1 -0
- package/dist/javascript/type-report-cli.js +129 -0
- package/dist/javascript/type-report-cli.js.map +1 -0
- package/dist/javascript/type-report.d.ts +61 -0
- package/dist/javascript/type-report.d.ts.map +1 -0
- package/dist/javascript/type-report.js +488 -0
- package/dist/javascript/type-report.js.map +1 -0
- package/dist/markers.d.ts +4 -0
- package/dist/markers.d.ts.map +1 -1
- package/dist/markers.js +8 -0
- package/dist/markers.js.map +1 -1
- package/dist/print.d.ts +6 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +21 -7
- package/dist/print.js.map +1 -1
- package/dist/recipe.d.ts +5 -0
- package/dist/recipe.d.ts.map +1 -1
- package/dist/recipe.js +5 -0
- package/dist/recipe.js.map +1 -1
- package/dist/rewrite-javascript-version.txt +1 -1
- package/dist/rpc/java-rpc-client.d.ts +2 -0
- package/dist/rpc/java-rpc-client.d.ts.map +1 -1
- package/dist/rpc/java-rpc-client.js +1 -0
- package/dist/rpc/java-rpc-client.js.map +1 -1
- package/dist/rpc/queue.d.ts +24 -0
- package/dist/rpc/queue.d.ts.map +1 -1
- package/dist/rpc/queue.js +71 -11
- package/dist/rpc/queue.js.map +1 -1
- package/dist/rpc/request/get-object.d.ts +4 -0
- package/dist/rpc/request/get-object.d.ts.map +1 -1
- package/dist/rpc/request/get-object.js +23 -1
- package/dist/rpc/request/get-object.js.map +1 -1
- package/dist/rpc/request/parse.d.ts.map +1 -1
- package/dist/rpc/request/parse.js +3 -1
- package/dist/rpc/request/parse.js.map +1 -1
- package/dist/rpc/request/prepare-recipe.d.ts +3 -1
- package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
- package/dist/rpc/request/prepare-recipe.js +13 -6
- package/dist/rpc/request/prepare-recipe.js.map +1 -1
- package/dist/rpc/request/print.d.ts +8 -2
- package/dist/rpc/request/print.d.ts.map +1 -1
- package/dist/rpc/request/print.js +12 -9
- package/dist/rpc/request/print.js.map +1 -1
- package/dist/rpc/rewrite-rpc.d.ts +3 -2
- package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
- package/dist/rpc/rewrite-rpc.js +9 -3
- package/dist/rpc/rewrite-rpc.js.map +1 -1
- package/dist/rpc/server.d.ts.map +1 -1
- package/dist/rpc/server.js +19 -5
- package/dist/rpc/server.js.map +1 -1
- package/dist/search/is-source-file.d.ts +1 -0
- package/dist/search/is-source-file.d.ts.map +1 -1
- package/dist/search/is-source-file.js +7 -2
- package/dist/search/is-source-file.js.map +1 -1
- package/dist/test/java-rpc.d.ts.map +1 -1
- package/dist/test/java-rpc.js +3 -0
- package/dist/test/java-rpc.js.map +1 -1
- package/dist/test/rewrite-test.d.ts +5 -0
- package/dist/test/rewrite-test.d.ts.map +1 -1
- package/dist/test/rewrite-test.js +14 -3
- package/dist/test/rewrite-test.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +3 -1
- package/src/java/formatting-utils.ts +5 -4
- package/src/java/rpc.ts +2 -0
- package/src/java/tree.ts +15 -0
- package/src/java/type.ts +19 -2
- package/src/javascript/add-import.ts +338 -152
- package/src/javascript/amd.ts +28 -12
- package/src/javascript/autodetect.ts +32 -41
- package/src/javascript/binding.ts +64 -22
- package/src/javascript/comparator.ts +129 -43
- package/src/javascript/format/format.ts +9 -0
- package/src/javascript/format/tabs-and-indents-visitor.ts +30 -3
- package/src/javascript/index.ts +6 -3
- package/src/javascript/markers.ts +77 -5
- package/src/javascript/method-matcher.ts +34 -22
- package/src/javascript/node-resolution-result.ts +3 -2
- package/src/javascript/package-name.ts +45 -0
- package/src/javascript/parser.ts +200 -91
- package/src/javascript/preconditions.ts +7 -4
- package/src/javascript/print.ts +123 -76
- package/src/javascript/recipes/change-method-target-to-import.ts +178 -0
- package/src/javascript/recipes/index.ts +1 -0
- package/src/javascript/scope.ts +705 -169
- package/src/javascript/search/uses-method.ts +2 -2
- package/src/javascript/search/uses-type.ts +30 -9
- package/src/javascript/templating/bindings.ts +13 -38
- package/src/javascript/templating/comparator.ts +16 -127
- package/src/javascript/templating/engine.ts +236 -129
- package/src/javascript/templating/pattern.ts +107 -28
- package/src/javascript/templating/placeholder-replacement.ts +154 -62
- package/src/javascript/templating/precedence.ts +33 -11
- package/src/javascript/templating/template.ts +35 -30
- package/src/javascript/templating/types.ts +6 -3
- package/src/javascript/templating/utils.ts +24 -2
- package/src/javascript/tree-debug.ts +9 -0
- package/src/javascript/tsconfig.ts +7 -17
- package/src/javascript/type-mapping.ts +277 -255
- package/src/javascript/type-report-cli.ts +96 -0
- package/src/javascript/type-report.ts +575 -0
- package/src/markers.ts +8 -0
- package/src/print.ts +23 -8
- package/src/recipe.ts +6 -0
- package/src/rpc/java-rpc-client.ts +3 -0
- package/src/rpc/queue.ts +80 -7
- package/src/rpc/request/get-object.ts +24 -0
- package/src/rpc/request/parse.ts +4 -1
- package/src/rpc/request/prepare-recipe.ts +16 -6
- package/src/rpc/request/print.ts +12 -8
- package/src/rpc/rewrite-rpc.ts +16 -5
- package/src/rpc/server.ts +18 -6
- package/src/search/is-source-file.ts +8 -3
- package/src/test/java-rpc.ts +3 -0
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
575
|
-
if (
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
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
|
-
|
|
708
|
-
|
|
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 (
|
|
797
|
+
if (afterNodeModules.split('/')[0] === '.pnpm') {
|
|
781
798
|
return undefined;
|
|
782
799
|
}
|
|
783
|
-
return
|
|
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
|
-
|
|
961
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
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
|
-
//
|
|
1066
|
-
|
|
1067
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1281
|
-
|
|
1282
|
-
if (
|
|
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
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
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
|
|
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 = (
|
|
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 = (
|
|
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 = (
|
|
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
|
-
//
|
|
1476
|
-
|
|
1477
|
-
if (classType.classKind === java_1.Type.Class.Kind.Class
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
if (
|
|
1481
|
-
classType.supertype =
|
|
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
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
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 || ((
|
|
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.
|