@openrewrite/rewrite 8.62.3 → 8.62.4
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/dist/execution.d.ts.map +1 -1
- package/dist/execution.js.map +1 -1
- package/dist/java/rpc.d.ts +1 -0
- package/dist/java/rpc.d.ts.map +1 -1
- package/dist/java/rpc.js +81 -0
- package/dist/java/rpc.js.map +1 -1
- package/dist/java/tree.d.ts.map +1 -1
- package/dist/java/tree.js +0 -87
- package/dist/java/tree.js.map +1 -1
- package/dist/java/visitor.d.ts +4 -4
- package/dist/java/visitor.d.ts.map +1 -1
- package/dist/java/visitor.js.map +1 -1
- package/dist/javascript/format.d.ts +2 -2
- package/dist/javascript/format.d.ts.map +1 -1
- package/dist/javascript/format.js.map +1 -1
- package/dist/javascript/parser.d.ts +1 -1
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +26 -4
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/print.d.ts +2 -2
- package/dist/javascript/print.d.ts.map +1 -1
- package/dist/javascript/print.js.map +1 -1
- package/dist/javascript/rpc.js +1 -16
- package/dist/javascript/rpc.js.map +1 -1
- package/dist/javascript/type-mapping.d.ts +4 -19
- package/dist/javascript/type-mapping.d.ts.map +1 -1
- package/dist/javascript/type-mapping.js +208 -167
- package/dist/javascript/type-mapping.js.map +1 -1
- package/dist/javascript/visitor.d.ts +1 -1
- package/dist/javascript/visitor.d.ts.map +1 -1
- package/dist/javascript/visitor.js.map +1 -1
- package/dist/json/print.js.map +1 -1
- package/dist/json/rpc.js +46 -17
- package/dist/json/rpc.js.map +1 -1
- package/dist/json/visitor.d.ts +2 -2
- package/dist/json/visitor.d.ts.map +1 -1
- package/dist/json/visitor.js.map +1 -1
- package/dist/rpc/queue.d.ts +15 -6
- package/dist/rpc/queue.d.ts.map +1 -1
- package/dist/rpc/queue.js +37 -13
- package/dist/rpc/queue.js.map +1 -1
- package/dist/rpc/request/generate.d.ts +4 -0
- package/dist/rpc/request/generate.d.ts.map +1 -1
- package/dist/rpc/request/generate.js +9 -4
- package/dist/rpc/request/generate.js.map +1 -1
- package/dist/rpc/request/get-object.d.ts +2 -2
- package/dist/rpc/request/get-object.d.ts.map +1 -1
- package/dist/rpc/request/get-object.js +4 -12
- 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.map +1 -1
- package/dist/rpc/request/print.d.ts +1 -1
- package/dist/rpc/request/print.d.ts.map +1 -1
- package/dist/rpc/request/print.js +1 -1
- package/dist/rpc/request/print.js.map +1 -1
- package/dist/rpc/request/visit.d.ts +3 -2
- package/dist/rpc/request/visit.d.ts.map +1 -1
- package/dist/rpc/request/visit.js +5 -4
- package/dist/rpc/request/visit.js.map +1 -1
- package/dist/rpc/rewrite-rpc.d.ts +3 -3
- package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
- package/dist/rpc/rewrite-rpc.js +16 -14
- package/dist/rpc/rewrite-rpc.js.map +1 -1
- package/dist/test/rewrite-test.js.map +1 -1
- package/dist/text/rpc.js +37 -40
- package/dist/text/rpc.js.map +1 -1
- package/dist/version.txt +1 -1
- package/package.json +1 -1
- package/src/execution.ts +0 -2
- package/src/java/rpc.ts +68 -0
- package/src/java/tree.ts +1 -65
- package/src/java/visitor.ts +4 -4
- package/src/javascript/format.ts +2 -2
- package/src/javascript/parser.ts +19 -5
- package/src/javascript/print.ts +3 -3
- package/src/javascript/rpc.ts +4 -17
- package/src/javascript/type-mapping.ts +216 -173
- package/src/javascript/visitor.ts +1 -1
- package/src/json/print.ts +1 -1
- package/src/json/rpc.ts +40 -19
- package/src/json/visitor.ts +2 -2
- package/src/rpc/queue.ts +36 -12
- package/src/rpc/request/generate.ts +18 -6
- package/src/rpc/request/get-object.ts +6 -13
- package/src/rpc/request/parse.ts +1 -1
- package/src/rpc/request/print.ts +2 -2
- package/src/rpc/request/visit.ts +6 -5
- package/src/rpc/rewrite-rpc.ts +21 -17
- package/src/test/rewrite-test.ts +1 -1
- package/src/text/rpc.ts +33 -37
|
@@ -34,8 +34,7 @@ export class JavaScriptTypeMapping {
|
|
|
34
34
|
private readonly regExpSymbol: ts.Symbol | undefined;
|
|
35
35
|
|
|
36
36
|
constructor(
|
|
37
|
-
private readonly checker: ts.TypeChecker
|
|
38
|
-
private readonly projectRoot: string = process.cwd()
|
|
37
|
+
private readonly checker: ts.TypeChecker
|
|
39
38
|
) {
|
|
40
39
|
this.regExpSymbol = checker.resolveName(
|
|
41
40
|
"RegExp",
|
|
@@ -62,15 +61,8 @@ export class JavaScriptTypeMapping {
|
|
|
62
61
|
return existing;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
// Check
|
|
66
|
-
//
|
|
67
|
-
if (this.checker.isArrayType(type)) {
|
|
68
|
-
const arrayType = this.createArrayType(type as ts.TypeReference);
|
|
69
|
-
this.typeCache.set(signature, arrayType);
|
|
70
|
-
return arrayType;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Check for class/interface/enum types (but not arrays)
|
|
64
|
+
// Check for class/interface/enum types (including arrays)
|
|
65
|
+
// Arrays in JavaScript are objects with methods, so we treat them as class types
|
|
74
66
|
const symbol = type.getSymbol?.();
|
|
75
67
|
if (symbol) {
|
|
76
68
|
if (symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface | ts.SymbolFlags.Enum | ts.SymbolFlags.TypeAlias)) {
|
|
@@ -169,11 +161,65 @@ export class JavaScriptTypeMapping {
|
|
|
169
161
|
// Get the method name
|
|
170
162
|
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
171
163
|
methodName = node.expression.name.getText();
|
|
164
|
+
|
|
165
|
+
// Check if the object is an imported symbol
|
|
166
|
+
const objSymbol = this.checker.getSymbolAtLocation(node.expression.expression);
|
|
167
|
+
let isImport = false;
|
|
168
|
+
if (objSymbol) {
|
|
169
|
+
// Only call getAliasedSymbol if the symbol is actually an alias
|
|
170
|
+
if (objSymbol.flags & ts.SymbolFlags.Alias) {
|
|
171
|
+
const aliasedSymbol = this.checker.getAliasedSymbol(objSymbol);
|
|
172
|
+
isImport = aliasedSymbol && aliasedSymbol !== objSymbol;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
172
176
|
const exprType = this.checker.getTypeAtLocation(node.expression.expression);
|
|
173
177
|
const mappedType = this.getType(exprType);
|
|
174
178
|
|
|
175
|
-
//
|
|
176
|
-
if (
|
|
179
|
+
// Handle different types
|
|
180
|
+
if (mappedType && mappedType.kind === Type.Kind.Class) {
|
|
181
|
+
// Update the declaring type with the corrected FQN
|
|
182
|
+
if (isImport && objSymbol) {
|
|
183
|
+
const importName = objSymbol.getName();
|
|
184
|
+
const origFqn = (mappedType as Type.Class).fullyQualifiedName;
|
|
185
|
+
const lastDot = origFqn.lastIndexOf('.');
|
|
186
|
+
if (lastDot > 0) {
|
|
187
|
+
const typeName = origFqn.substring(lastDot + 1);
|
|
188
|
+
declaringType = {
|
|
189
|
+
kind: Type.Kind.Class,
|
|
190
|
+
fullyQualifiedName: `${importName}.${typeName}`
|
|
191
|
+
} as Type.FullyQualified;
|
|
192
|
+
} else {
|
|
193
|
+
declaringType = mappedType as Type.FullyQualified;
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
declaringType = mappedType as Type.FullyQualified;
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
// Handle primitive types and other non-class types
|
|
200
|
+
if (mappedType) {
|
|
201
|
+
if ((mappedType as any).keyword === 'String') {
|
|
202
|
+
declaringType = {
|
|
203
|
+
kind: Type.Kind.Class,
|
|
204
|
+
fullyQualifiedName: 'lib.String'
|
|
205
|
+
} as Type.FullyQualified;
|
|
206
|
+
} else if ((mappedType as any).keyword === 'Number') {
|
|
207
|
+
declaringType = {
|
|
208
|
+
kind: Type.Kind.Class,
|
|
209
|
+
fullyQualifiedName: 'lib.Number'
|
|
210
|
+
} as Type.FullyQualified;
|
|
211
|
+
} else {
|
|
212
|
+
// Fallback for other types
|
|
213
|
+
declaringType = mappedType as Type.FullyQualified;
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
// Default to unknown if we can't determine the type
|
|
217
|
+
declaringType = Type.unknownType as Type.FullyQualified;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// For string methods like 'hello'.split(), ensure we have a proper declaring type for primitives
|
|
222
|
+
if (!isImport && declaringType === Type.unknownType) {
|
|
177
223
|
// If the expression type is a primitive string, use lib.String as declaring type
|
|
178
224
|
const typeString = this.checker.typeToString(exprType);
|
|
179
225
|
if (typeString === 'string' || exprType.flags & ts.TypeFlags.String || exprType.flags & ts.TypeFlags.StringLiteral) {
|
|
@@ -190,42 +236,89 @@ export class JavaScriptTypeMapping {
|
|
|
190
236
|
// Fallback for other primitive types or unknown
|
|
191
237
|
declaringType = Type.unknownType as Type.FullyQualified;
|
|
192
238
|
}
|
|
193
|
-
} else {
|
|
194
|
-
declaringType = mappedType as Type.FullyQualified;
|
|
195
239
|
}
|
|
240
|
+
|
|
196
241
|
} else if (ts.isIdentifier(node.expression)) {
|
|
197
242
|
methodName = node.expression.getText();
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
243
|
+
|
|
244
|
+
// Check if this is an import first
|
|
245
|
+
const symbol = this.checker.getSymbolAtLocation(node.expression);
|
|
246
|
+
let moduleSpecifier: string | undefined;
|
|
247
|
+
|
|
248
|
+
if (symbol) {
|
|
249
|
+
// Check if this is an aliased symbol (i.e., an import)
|
|
250
|
+
let aliasedSymbol: ts.Symbol | undefined;
|
|
251
|
+
if (symbol.flags & ts.SymbolFlags.Alias) {
|
|
252
|
+
aliasedSymbol = this.checker.getAliasedSymbol(symbol);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// If getAliasedSymbol returns something different, it's an import
|
|
256
|
+
if (aliasedSymbol && aliasedSymbol !== symbol) {
|
|
257
|
+
// This is definitely an imported symbol
|
|
258
|
+
// Now find the import declaration to get the module specifier
|
|
259
|
+
if (symbol.declarations && symbol.declarations.length > 0) {
|
|
260
|
+
let importNode: ts.Node = symbol.declarations[0];
|
|
261
|
+
|
|
262
|
+
// Traverse up to find the ImportDeclaration
|
|
263
|
+
while (importNode && !ts.isImportDeclaration(importNode)) {
|
|
264
|
+
importNode = importNode.parent;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (importNode && ts.isImportDeclaration(importNode)) {
|
|
268
|
+
const importDeclNode = importNode as ts.ImportDeclaration;
|
|
269
|
+
if (ts.isStringLiteral(importDeclNode.moduleSpecifier)) {
|
|
270
|
+
moduleSpecifier = importDeclNode.moduleSpecifier.text;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (moduleSpecifier) {
|
|
278
|
+
// This is an imported function - use the module specifier as declaring type
|
|
279
|
+
if (moduleSpecifier.startsWith('node:')) {
|
|
280
|
+
// Node.js built-in module
|
|
212
281
|
declaringType = {
|
|
213
282
|
kind: Type.Kind.Class,
|
|
214
|
-
fullyQualifiedName:
|
|
283
|
+
fullyQualifiedName: 'node'
|
|
215
284
|
} as Type.FullyQualified;
|
|
285
|
+
methodName = moduleSpecifier.substring(5); // Remove 'node:' prefix
|
|
216
286
|
} else {
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
287
|
+
// Regular module import
|
|
288
|
+
declaringType = {
|
|
289
|
+
kind: Type.Kind.Class,
|
|
290
|
+
fullyQualifiedName: moduleSpecifier
|
|
291
|
+
} as Type.FullyQualified;
|
|
292
|
+
methodName = '<default>';
|
|
220
293
|
}
|
|
221
294
|
} else {
|
|
222
|
-
//
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
295
|
+
// Fall back to the original logic for non-imported functions
|
|
296
|
+
const exprType = this.checker.getTypeAtLocation(node.expression);
|
|
297
|
+
const funcType = this.getType(exprType);
|
|
298
|
+
|
|
299
|
+
if (funcType && funcType.kind === Type.Kind.Class) {
|
|
300
|
+
const fqn = (funcType as Type.Class).fullyQualifiedName;
|
|
301
|
+
const lastDot = fqn.lastIndexOf('.');
|
|
302
|
+
|
|
303
|
+
if (lastDot > 0) {
|
|
304
|
+
// For functions from modules, use the module part as declaring type
|
|
305
|
+
declaringType = {
|
|
306
|
+
kind: Type.Kind.Class,
|
|
307
|
+
fullyQualifiedName: fqn.substring(0, lastDot)
|
|
308
|
+
} as Type.FullyQualified;
|
|
309
|
+
} else {
|
|
310
|
+
// No dots in the name - the type IS the module itself
|
|
311
|
+
declaringType = funcType as Type.FullyQualified;
|
|
312
|
+
}
|
|
227
313
|
} else {
|
|
228
|
-
|
|
314
|
+
// Try to use the symbol's parent or module
|
|
315
|
+
const parent = (symbol as any).parent;
|
|
316
|
+
if (parent) {
|
|
317
|
+
const parentType = this.checker.getDeclaredTypeOfSymbol(parent);
|
|
318
|
+
declaringType = this.getType(parentType) as Type.FullyQualified;
|
|
319
|
+
} else {
|
|
320
|
+
declaringType = Type.unknownType as Type.FullyQualified;
|
|
321
|
+
}
|
|
229
322
|
}
|
|
230
323
|
}
|
|
231
324
|
} else {
|
|
@@ -320,27 +413,12 @@ export class JavaScriptTypeMapping {
|
|
|
320
413
|
}) as Type.Method;
|
|
321
414
|
}
|
|
322
415
|
|
|
323
|
-
/**
|
|
324
|
-
* Create a JavaType.Array from a TypeScript array type
|
|
325
|
-
*/
|
|
326
|
-
private createArrayType(type: ts.TypeReference): Type.Array {
|
|
327
|
-
// Get the element type (type argument of Array<T>)
|
|
328
|
-
const typeArgs = this.checker.getTypeArguments(type);
|
|
329
|
-
const elemType = typeArgs.length > 0 ? this.getType(typeArgs[0]) : Type.unknownType;
|
|
330
|
-
|
|
331
|
-
return Object.assign(new NonDraftableType(), {
|
|
332
|
-
kind: Type.Kind.Array,
|
|
333
|
-
elemType: elemType,
|
|
334
|
-
annotations: [],
|
|
335
|
-
toJSON: function () {
|
|
336
|
-
return Type.signature(this);
|
|
337
|
-
}
|
|
338
|
-
}) as Type.Array;
|
|
339
|
-
}
|
|
340
416
|
|
|
341
417
|
/**
|
|
342
418
|
* Get the fully qualified name for a TypeScript type.
|
|
343
|
-
*
|
|
419
|
+
* Uses TypeScript's built-in resolution which properly handles things like:
|
|
420
|
+
* - React.Component (not @types/react.Component)
|
|
421
|
+
* - _.LoDashStatic (not @types/lodash.LoDashStatic)
|
|
344
422
|
*/
|
|
345
423
|
private getFullyQualifiedName(type: ts.Type): string {
|
|
346
424
|
const symbol = type.getSymbol?.();
|
|
@@ -348,140 +426,105 @@ export class JavaScriptTypeMapping {
|
|
|
348
426
|
return "unknown";
|
|
349
427
|
}
|
|
350
428
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (
|
|
354
|
-
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
// Check if this is a test file (snowflake ID as filename)
|
|
365
|
-
// Test files are generated with numeric IDs like "672087069480189952.ts"
|
|
366
|
-
if (/^\d+\.(ts|tsx|js|jsx)$/.test(fileName)) {
|
|
367
|
-
// For test files, just return the type name without module prefix
|
|
368
|
-
return typeName;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Check if this is from TypeScript's lib files (lib.d.ts, lib.dom.d.ts, etc.)
|
|
372
|
-
if (fileName.includes("/typescript/lib/lib.") || fileName.includes("\\typescript\\lib\\lib.")) {
|
|
373
|
-
return `lib.${typeName}`;
|
|
374
|
-
}
|
|
429
|
+
// First, check if this symbol is an import/alias
|
|
430
|
+
// For imported types, we want to use the module specifier instead of the file path
|
|
431
|
+
if (symbol.flags & ts.SymbolFlags.Alias) {
|
|
432
|
+
const aliasedSymbol = this.checker.getAliasedSymbol(symbol);
|
|
433
|
+
if (aliasedSymbol && aliasedSymbol !== symbol && symbol.declarations && symbol.declarations.length > 0) {
|
|
434
|
+
// Try to find the import declaration to get the module specifier
|
|
435
|
+
let importNode: ts.Node | undefined = symbol.declarations[0];
|
|
436
|
+
|
|
437
|
+
// Traverse up to find the ImportDeclaration or ImportSpecifier
|
|
438
|
+
while (importNode && importNode.parent && !ts.isImportDeclaration(importNode) && !ts.isImportSpecifier(importNode)) {
|
|
439
|
+
importNode = importNode.parent;
|
|
440
|
+
}
|
|
375
441
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
// For default exports from Node modules, we want the module to be the "class"
|
|
390
|
-
// But we still need to include the type name for proper identification
|
|
391
|
-
if (typeName === "default" || typeName === modulePath) {
|
|
392
|
-
// This is likely the default export, just use the module name
|
|
393
|
-
return `node.${modulePath}`;
|
|
394
|
-
}
|
|
395
|
-
// For named exports, include both module and type name
|
|
396
|
-
if (modulePath.includes('/')) {
|
|
397
|
-
return `node.${modulePath.replace(/\//g, '.')}.${typeName}`;
|
|
442
|
+
let moduleSpecifier: string | undefined;
|
|
443
|
+
|
|
444
|
+
if (importNode && ts.isImportSpecifier(importNode)) {
|
|
445
|
+
// Named import like: import { ClipLoader } from 'react-spinners'
|
|
446
|
+
// ImportSpecifier -> NamedImports -> ImportClause -> ImportDeclaration
|
|
447
|
+
const namedImports = importNode.parent; // NamedImports
|
|
448
|
+
if (namedImports && ts.isNamedImports(namedImports)) {
|
|
449
|
+
const importClause = namedImports.parent; // ImportClause
|
|
450
|
+
if (importClause && ts.isImportClause(importClause)) {
|
|
451
|
+
const importDecl = importClause.parent; // ImportDeclaration
|
|
452
|
+
if (importDecl && ts.isImportDeclaration(importDecl) && ts.isStringLiteral(importDecl.moduleSpecifier)) {
|
|
453
|
+
moduleSpecifier = importDecl.moduleSpecifier.text;
|
|
454
|
+
}
|
|
398
455
|
}
|
|
399
|
-
return `node.${modulePath}.${typeName}`;
|
|
400
456
|
}
|
|
401
|
-
|
|
402
|
-
|
|
457
|
+
} else if (importNode && ts.isImportDeclaration(importNode)) {
|
|
458
|
+
// Default or namespace import
|
|
459
|
+
if (ts.isStringLiteral(importNode.moduleSpecifier)) {
|
|
460
|
+
moduleSpecifier = importNode.moduleSpecifier.text;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (moduleSpecifier) {
|
|
465
|
+
// Build the fully qualified name from module specifier + symbol name
|
|
466
|
+
const symbolName = symbol.getName();
|
|
467
|
+
return `${moduleSpecifier}.${symbolName}`;
|
|
403
468
|
}
|
|
404
|
-
return `${packageName}.${typeName}`;
|
|
405
469
|
}
|
|
406
470
|
}
|
|
407
471
|
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
472
|
+
// Fall back to TypeScript's built-in getFullyQualifiedName
|
|
473
|
+
// This returns names with quotes that we need to clean up
|
|
474
|
+
// e.g., '"React"."Component"' -> 'React.Component'
|
|
475
|
+
const tsQualifiedName = this.checker.getFullyQualifiedName(symbol);
|
|
476
|
+
let cleanedName = tsQualifiedName.replace(/"/g, '');
|
|
477
|
+
|
|
478
|
+
// Check if this is a file path from node_modules (happens with some packages)
|
|
479
|
+
// TypeScript sometimes returns full paths instead of module names
|
|
480
|
+
if (cleanedName.includes('node_modules/')) {
|
|
481
|
+
// Extract the module name from the path
|
|
482
|
+
// Example: /private/var/.../node_modules/react-spinners/src/index.ClipLoader
|
|
483
|
+
// Should become: react-spinners.ClipLoader
|
|
484
|
+
const nodeModulesIndex = cleanedName.indexOf('node_modules/');
|
|
485
|
+
const afterNodeModules = cleanedName.substring(nodeModulesIndex + 'node_modules/'.length);
|
|
486
|
+
|
|
487
|
+
// Split by '/' to get parts of the path
|
|
488
|
+
const pathParts = afterNodeModules.split('/');
|
|
489
|
+
|
|
490
|
+
if (pathParts.length > 0) {
|
|
491
|
+
// First part is the package name (might be scoped like @types)
|
|
492
|
+
let packageName = pathParts[0];
|
|
493
|
+
|
|
494
|
+
// Handle scoped packages
|
|
495
|
+
if (packageName.startsWith('@') && pathParts.length > 1) {
|
|
496
|
+
packageName = `${packageName}/${pathParts[1]}`;
|
|
497
|
+
}
|
|
423
498
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
499
|
+
// Find the symbol name (everything after the last dot in the original cleaned name)
|
|
500
|
+
const lastDotIndex = cleanedName.lastIndexOf('.');
|
|
501
|
+
if (lastDotIndex > 0) {
|
|
502
|
+
const symbolName = cleanedName.substring(lastDotIndex + 1);
|
|
503
|
+
cleanedName = `${packageName}.${symbolName}`;
|
|
504
|
+
} else {
|
|
505
|
+
cleanedName = packageName;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
433
508
|
}
|
|
434
509
|
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
510
|
+
// If it's just a simple name without dots, check if it's a built-in type
|
|
511
|
+
if (!cleanedName.includes('.')) {
|
|
512
|
+
if (builtInTypes.has(cleanedName)) {
|
|
513
|
+
return `lib.${cleanedName}`;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
440
516
|
|
|
441
|
-
return
|
|
517
|
+
return cleanedName;
|
|
442
518
|
}
|
|
443
519
|
|
|
520
|
+
|
|
444
521
|
/**
|
|
445
522
|
* Create an empty JavaType.Class shell from a TypeScript type.
|
|
446
523
|
* The shell will be populated later to handle circular references.
|
|
447
524
|
*/
|
|
448
525
|
private createEmptyClassType(type: ts.Type): Type.Class {
|
|
449
|
-
// Use our
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
// If getFullyQualifiedName returned unknown, fall back to TypeScript's method
|
|
453
|
-
if (fullyQualifiedName === "unknown") {
|
|
454
|
-
const symbol = type.symbol;
|
|
455
|
-
fullyQualifiedName = symbol ? this.checker.getFullyQualifiedName(symbol) : `<anonymous>${this.checker.typeToString(type)}`;
|
|
456
|
-
|
|
457
|
-
// Fix FQN for types from @types packages
|
|
458
|
-
// TypeScript returns "_.LoDashStatic" but we want "@types/lodash.LoDashStatic"
|
|
459
|
-
if (symbol && symbol.declarations && symbol.declarations.length > 0) {
|
|
460
|
-
const sourceFile = symbol.declarations[0].getSourceFile();
|
|
461
|
-
const fileName = sourceFile.fileName;
|
|
462
|
-
// Check if this is from @types package
|
|
463
|
-
const typesMatch = fileName.match(/node_modules\/@types\/([^/]+)/);
|
|
464
|
-
if (typesMatch) {
|
|
465
|
-
const packageName = typesMatch[1];
|
|
466
|
-
// Special handling for @types/node - use "node" prefix instead
|
|
467
|
-
if (packageName === "node") {
|
|
468
|
-
// Extract the module name from the file path if possible
|
|
469
|
-
const nodeMatch = fileName.match(/node_modules\/@types\/node\/([^.]+)\.d\.ts/);
|
|
470
|
-
if (nodeMatch) {
|
|
471
|
-
const modulePath = nodeMatch[1];
|
|
472
|
-
// Replace the module specifier with node.module
|
|
473
|
-
fullyQualifiedName = fullyQualifiedName.replace(/^[^.]+\./, `node.${modulePath}.`);
|
|
474
|
-
} else {
|
|
475
|
-
// Fallback: just use "node" prefix
|
|
476
|
-
fullyQualifiedName = fullyQualifiedName.replace(/^[^.]+\./, `node.`);
|
|
477
|
-
}
|
|
478
|
-
} else {
|
|
479
|
-
// Replace the module specifier part with @types/package
|
|
480
|
-
fullyQualifiedName = fullyQualifiedName.replace(/^[^.]+\./, `@types/${packageName}.`);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
526
|
+
// Use our getFullyQualifiedName method which uses TypeScript's built-in resolution
|
|
527
|
+
const fullyQualifiedName = this.getFullyQualifiedName(type);
|
|
485
528
|
|
|
486
529
|
// Determine the class kind based on symbol flags
|
|
487
530
|
let classKind = Type.Class.Kind.Interface; // Default to interface
|
|
@@ -40,7 +40,7 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// noinspection JSUnusedLocalSymbols
|
|
43
|
-
|
|
43
|
+
override async visitSpace(space: J.Space, p: P): Promise<J.Space> {
|
|
44
44
|
return space;
|
|
45
45
|
}
|
|
46
46
|
|
package/src/json/print.ts
CHANGED
|
@@ -75,7 +75,7 @@ class JsonPrinter extends JsonVisitor<PrintOutputCapture> {
|
|
|
75
75
|
return jsonObject;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
public async visitSpace(space: Json.Space, p: PrintOutputCapture): Promise<Json.Space> {
|
|
79
79
|
p.append(space.whitespace);
|
|
80
80
|
for (const comment of space.comments) {
|
|
81
81
|
await this.visitMarkers(comment.markers, p);
|
package/src/json/rpc.ts
CHANGED
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import {JsonVisitor} from "./visitor";
|
|
17
|
-
import {asRef,
|
|
17
|
+
import {asRef, RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "../rpc";
|
|
18
18
|
import {Json} from "./tree";
|
|
19
19
|
import {produceAsync} from "../visitor";
|
|
20
20
|
import {createDraft, Draft, finishDraft} from "immer";
|
|
21
|
-
import {TreeKind} from "../tree";
|
|
22
21
|
|
|
23
22
|
class JsonSender extends JsonVisitor<RpcSendQueue> {
|
|
24
23
|
|
|
@@ -76,7 +75,7 @@ class JsonSender extends JsonVisitor<RpcSendQueue> {
|
|
|
76
75
|
return obj;
|
|
77
76
|
}
|
|
78
77
|
|
|
79
|
-
|
|
78
|
+
public async visitSpace(space: Json.Space, q: RpcSendQueue): Promise<Json.Space> {
|
|
80
79
|
await q.getAndSendList(space, s => s.comments, c => c.text + c.suffix, async c => {
|
|
81
80
|
await q.getAndSend(c, c2 => c2.multiline);
|
|
82
81
|
await q.getAndSend(c, c2 => c2.text);
|
|
@@ -87,7 +86,7 @@ class JsonSender extends JsonVisitor<RpcSendQueue> {
|
|
|
87
86
|
return space;
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
|
|
89
|
+
public async visitRightPadded<T extends Json>(right: Json.RightPadded<T>, q: RpcSendQueue): Promise<Json.RightPadded<T> | undefined> {
|
|
91
90
|
await q.getAndSend(right, r => r.element, j => this.visit(j, q));
|
|
92
91
|
await q.getAndSend(right, r => asRef(r.after), async space => await this.visitSpace(space, q));
|
|
93
92
|
await q.getAndSend(right, r => r.markers);
|
|
@@ -158,7 +157,7 @@ class JsonReceiver extends JsonVisitor<RpcReceiveQueue> {
|
|
|
158
157
|
return finishDraft(draft);
|
|
159
158
|
}
|
|
160
159
|
|
|
161
|
-
|
|
160
|
+
public async visitSpace(space: Json.Space, q: RpcReceiveQueue): Promise<Json.Space> {
|
|
162
161
|
return produceAsync<Json.Space>(space, async draft => {
|
|
163
162
|
draft.comments = await q.receiveListDefined(space.comments, async c => {
|
|
164
163
|
return await produceAsync(c, async draft => {
|
|
@@ -172,7 +171,7 @@ class JsonReceiver extends JsonVisitor<RpcReceiveQueue> {
|
|
|
172
171
|
});
|
|
173
172
|
}
|
|
174
173
|
|
|
175
|
-
|
|
174
|
+
public async visitRightPadded<T extends Json>(right: Json.RightPadded<T>, p: RpcReceiveQueue): Promise<Json.RightPadded<T> | undefined> {
|
|
176
175
|
if (!right) {
|
|
177
176
|
throw new Error("TreeDataReceiveQueue should have instantiated an empty padding")
|
|
178
177
|
}
|
|
@@ -184,18 +183,40 @@ class JsonReceiver extends JsonVisitor<RpcReceiveQueue> {
|
|
|
184
183
|
}
|
|
185
184
|
}
|
|
186
185
|
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
186
|
+
const receiver = new JsonReceiver();
|
|
187
|
+
const sender = new JsonSender();
|
|
188
|
+
|
|
189
|
+
// Register codec for all Java AST node types
|
|
190
|
+
for (const kind of Object.values(Json.Kind)) {
|
|
191
|
+
if (kind === Json.Kind.Space) {
|
|
192
|
+
RpcCodecs.registerCodec(kind, {
|
|
193
|
+
async rpcReceive(before: Json.Space, q: RpcReceiveQueue): Promise<Json.Space> {
|
|
194
|
+
return (await receiver.visitSpace(before, q))!;
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
async rpcSend(after: Json.Space, q: RpcSendQueue): Promise<void> {
|
|
198
|
+
await sender.visitSpace(after, q);
|
|
199
|
+
}
|
|
200
|
+
}, Json.Kind.Document);
|
|
201
|
+
} else if (kind === Json.Kind.RightPadded) {
|
|
202
|
+
RpcCodecs.registerCodec(kind, {
|
|
203
|
+
async rpcReceive<T extends Json>(before: Json.RightPadded<T>, q: RpcReceiveQueue): Promise<Json.RightPadded<T>> {
|
|
204
|
+
return (await receiver.visitRightPadded(before, q))!;
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
async rpcSend<T extends Json>(after: Json.RightPadded<T>, q: RpcSendQueue): Promise<void> {
|
|
208
|
+
await sender.visitRightPadded(after, q);
|
|
209
|
+
}
|
|
210
|
+
}, Json.Kind.Document);
|
|
211
|
+
} else {
|
|
212
|
+
RpcCodecs.registerCodec(kind as string, {
|
|
213
|
+
async rpcReceive(before: Json, q: RpcReceiveQueue): Promise<Json> {
|
|
214
|
+
return (await receiver.visit(before, q))!;
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
async rpcSend(after: Json, q: RpcSendQueue): Promise<void> {
|
|
218
|
+
await sender.visit(after, q);
|
|
219
|
+
}
|
|
220
|
+
}, Json.Kind.Document);
|
|
194
221
|
}
|
|
195
222
|
}
|
|
196
|
-
|
|
197
|
-
Object.values(Json.Kind).forEach(kind => {
|
|
198
|
-
if (!Object.values(TreeKind).includes(kind as any)) {
|
|
199
|
-
RpcCodecs.registerCodec(kind, jsonCodec);
|
|
200
|
-
}
|
|
201
|
-
});
|
package/src/json/visitor.ts
CHANGED
|
@@ -62,7 +62,7 @@ export class JsonVisitor<P> extends TreeVisitor<Json, P> {
|
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
public async visitRightPadded<T extends Json>(right: Json.RightPadded<T>, p: P):
|
|
66
66
|
Promise<Json.RightPadded<T> | undefined> {
|
|
67
67
|
return produceAsync<Json.RightPadded<T>>(right, async draft => {
|
|
68
68
|
draft.element = await this.visitDefined(right.element, p);
|
|
@@ -70,7 +70,7 @@ export class JsonVisitor<P> extends TreeVisitor<Json, P> {
|
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
public async visitSpace(space: Json.Space, p: P): Promise<Json.Space> {
|
|
74
74
|
return space;
|
|
75
75
|
}
|
|
76
76
|
|