@openrewrite/rewrite 8.72.2 → 8.72.3
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.js +3 -16
- package/dist/execution.js.map +1 -1
- package/dist/index.js +34 -49
- package/dist/index.js.map +1 -1
- package/dist/java/markers.js +12 -29
- package/dist/java/markers.js.map +1 -1
- package/dist/java/print.js +2 -13
- package/dist/java/print.js.map +1 -1
- package/dist/java/rpc.js +1344 -1725
- package/dist/java/rpc.js.map +1 -1
- package/dist/java/type-visitor.js +143 -184
- package/dist/java/type-visitor.js.map +1 -1
- package/dist/java/visitor.js +1072 -1249
- package/dist/java/visitor.js.map +1 -1
- package/dist/javascript/add-import.js +495 -534
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/autodetect.js +116 -159
- package/dist/javascript/autodetect.js.map +1 -1
- package/dist/javascript/cleanup/add-parse-int-radix.js +41 -57
- package/dist/javascript/cleanup/add-parse-int-radix.js.map +1 -1
- package/dist/javascript/cleanup/prefer-optional-chain.js +89 -105
- package/dist/javascript/cleanup/prefer-optional-chain.js.map +1 -1
- package/dist/javascript/cleanup/use-object-property-shorthand.js +74 -95
- package/dist/javascript/cleanup/use-object-property-shorthand.js.map +1 -1
- package/dist/javascript/comparator.js +815 -1167
- package/dist/javascript/comparator.js.map +1 -1
- package/dist/javascript/dependency-workspace.js +206 -219
- package/dist/javascript/dependency-workspace.js.map +1 -1
- package/dist/javascript/format/format.js +682 -908
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/minimum-viable-spacing-visitor.js +152 -231
- package/dist/javascript/format/minimum-viable-spacing-visitor.js.map +1 -1
- package/dist/javascript/format/normalize-whitespace-visitor.js +12 -31
- package/dist/javascript/format/normalize-whitespace-visitor.js.map +1 -1
- package/dist/javascript/format/prettier-config-loader.js +134 -153
- package/dist/javascript/format/prettier-config-loader.js.map +1 -1
- package/dist/javascript/format/prettier-format.js +112 -129
- package/dist/javascript/format/prettier-format.js.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.js +112 -136
- package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
- package/dist/javascript/markers.js +59 -92
- package/dist/javascript/markers.js.map +1 -1
- package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js +39 -52
- package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js.map +1 -1
- package/dist/javascript/migrate/es6/modernize-octal-literals.js +25 -38
- package/dist/javascript/migrate/es6/modernize-octal-literals.js.map +1 -1
- package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js +66 -82
- package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js.map +1 -1
- package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js +10 -23
- package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js.map +1 -1
- package/dist/javascript/node-resolution-result.js +137 -166
- package/dist/javascript/node-resolution-result.js.map +1 -1
- package/dist/javascript/package-json-parser.js +312 -343
- package/dist/javascript/package-json-parser.js.map +1 -1
- package/dist/javascript/package-manager.js +145 -170
- package/dist/javascript/package-manager.js.map +1 -1
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +94 -68
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/print.js +1572 -1835
- package/dist/javascript/print.js.map +1 -1
- package/dist/javascript/project-parser.js +151 -172
- package/dist/javascript/project-parser.js.map +1 -1
- package/dist/javascript/recipes/add-dependency.js +140 -175
- package/dist/javascript/recipes/add-dependency.js.map +1 -1
- package/dist/javascript/recipes/async-callback-in-sync-array-method.js +20 -36
- package/dist/javascript/recipes/async-callback-in-sync-array-method.js.map +1 -1
- package/dist/javascript/recipes/auto-format.js +3 -14
- package/dist/javascript/recipes/auto-format.js.map +1 -1
- package/dist/javascript/recipes/change-import.js +447 -495
- package/dist/javascript/recipes/change-import.js.map +1 -1
- package/dist/javascript/recipes/order-imports.js +162 -175
- package/dist/javascript/recipes/order-imports.js.map +1 -1
- package/dist/javascript/recipes/upgrade-dependency-version.js +167 -197
- package/dist/javascript/recipes/upgrade-dependency-version.js.map +1 -1
- package/dist/javascript/recipes/upgrade-transitive-dependency-version.js +166 -193
- package/dist/javascript/recipes/upgrade-transitive-dependency-version.js.map +1 -1
- package/dist/javascript/remove-import.js +689 -724
- package/dist/javascript/remove-import.js.map +1 -1
- package/dist/javascript/rpc.js +1007 -1332
- package/dist/javascript/rpc.js.map +1 -1
- package/dist/javascript/search/find-dependency.js +84 -110
- package/dist/javascript/search/find-dependency.js.map +1 -1
- package/dist/javascript/search/uses-method.js +5 -19
- package/dist/javascript/search/uses-method.js.map +1 -1
- package/dist/javascript/search/uses-type.js +9 -20
- package/dist/javascript/search/uses-type.js.map +1 -1
- package/dist/javascript/templating/comparator.js +737 -822
- package/dist/javascript/templating/comparator.js.map +1 -1
- package/dist/javascript/templating/engine.js +211 -245
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/pattern.js +169 -190
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.js +172 -210
- package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
- package/dist/javascript/templating/rewrite.js +75 -97
- package/dist/javascript/templating/rewrite.js.map +1 -1
- package/dist/javascript/templating/template.js +69 -82
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/tree-debug.js +109 -137
- package/dist/javascript/tree-debug.js.map +1 -1
- package/dist/javascript/visitor.js +1090 -1254
- package/dist/javascript/visitor.js.map +1 -1
- package/dist/json/print.js +72 -103
- package/dist/json/print.js.map +1 -1
- package/dist/json/rpc.js +120 -181
- package/dist/json/rpc.js.map +1 -1
- package/dist/json/visitor.js +69 -100
- package/dist/json/visitor.js.map +1 -1
- package/dist/marketplace.js +20 -33
- package/dist/marketplace.js.map +1 -1
- package/dist/parse-error.js +41 -62
- package/dist/parse-error.js.map +1 -1
- package/dist/parser.js +7 -18
- package/dist/parser.js.map +1 -1
- package/dist/path-utils.js +46 -59
- package/dist/path-utils.js.map +1 -1
- package/dist/preconditions.js +30 -47
- package/dist/preconditions.js.map +1 -1
- package/dist/print.js +6 -19
- package/dist/print.js.map +1 -1
- package/dist/recipe.js +42 -73
- package/dist/recipe.js.map +1 -1
- package/dist/rpc/index.js +74 -115
- package/dist/rpc/index.js.map +1 -1
- package/dist/rpc/queue.js +71 -90
- package/dist/rpc/queue.js.map +1 -1
- package/dist/rpc/recipe.js +32 -57
- package/dist/rpc/recipe.js.map +1 -1
- package/dist/rpc/request/generate.js +4 -13
- package/dist/rpc/request/generate.js.map +1 -1
- package/dist/rpc/request/get-languages.js +2 -11
- package/dist/rpc/request/get-languages.js.map +1 -1
- package/dist/rpc/request/get-marketplace.js +9 -20
- package/dist/rpc/request/get-marketplace.js.map +1 -1
- package/dist/rpc/request/get-object.js +4 -13
- package/dist/rpc/request/get-object.js.map +1 -1
- package/dist/rpc/request/install-recipes.js +25 -36
- package/dist/rpc/request/install-recipes.js.map +1 -1
- package/dist/rpc/request/metrics.js +8 -17
- package/dist/rpc/request/metrics.js.map +1 -1
- package/dist/rpc/request/parse-project.js +36 -45
- package/dist/rpc/request/parse-project.js.map +1 -1
- package/dist/rpc/request/parse.js +5 -14
- package/dist/rpc/request/parse.js.map +1 -1
- package/dist/rpc/request/prepare-recipe.js +37 -52
- package/dist/rpc/request/prepare-recipe.js.map +1 -1
- package/dist/rpc/request/print.js +5 -14
- package/dist/rpc/request/print.js.map +1 -1
- package/dist/rpc/request/visit.js +56 -71
- package/dist/rpc/request/visit.js.map +1 -1
- package/dist/rpc/rewrite-rpc.js +70 -97
- package/dist/rpc/rewrite-rpc.js.map +1 -1
- package/dist/rpc/server.js +76 -89
- package/dist/rpc/server.js.map +1 -1
- package/dist/run.js +47 -66
- package/dist/run.js.map +1 -1
- package/dist/search/is-source-file.js +8 -19
- package/dist/search/is-source-file.js.map +1 -1
- package/dist/test/rewrite-test.js +154 -188
- package/dist/test/rewrite-test.js.map +1 -1
- package/dist/text/print.js +23 -38
- package/dist/text/print.js.map +1 -1
- package/dist/text/rpc.js +29 -44
- package/dist/text/rpc.js.map +1 -1
- package/dist/text/visitor.js +16 -33
- package/dist/text/visitor.js.map +1 -1
- package/dist/util.js +13 -24
- package/dist/util.js.map +1 -1
- package/dist/version.txt +1 -1
- package/dist/visitor.js +84 -115
- package/dist/visitor.js.map +1 -1
- package/dist/yaml/index.d.ts +2 -0
- package/dist/yaml/index.d.ts.map +1 -1
- package/dist/yaml/index.js +2 -0
- package/dist/yaml/index.js.map +1 -1
- package/dist/yaml/markers.d.ts +21 -0
- package/dist/yaml/markers.d.ts.map +1 -0
- package/dist/yaml/markers.js +37 -0
- package/dist/yaml/markers.js.map +1 -0
- package/dist/yaml/parser.d.ts.map +1 -1
- package/dist/yaml/parser.js +4 -1
- package/dist/yaml/parser.js.map +1 -1
- package/dist/yaml/print.d.ts +1 -1
- package/dist/yaml/print.d.ts.map +1 -1
- package/dist/yaml/print.js +175 -208
- package/dist/yaml/print.js.map +1 -1
- package/dist/yaml/rpc.js +154 -219
- package/dist/yaml/rpc.js.map +1 -1
- package/dist/yaml/visitor.js +78 -113
- package/dist/yaml/visitor.js.map +1 -1
- package/package.json +1 -1
- package/src/javascript/parser.ts +56 -14
- package/src/yaml/index.ts +2 -0
- package/src/yaml/markers.ts +70 -0
- package/src/yaml/parser.ts +5 -1
- package/src/yaml/print.ts +5 -2
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.AddImport = exports.ImportStyle = void 0;
|
|
13
4
|
exports.maybeAddImport = maybeAddImport;
|
|
@@ -267,260 +258,254 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
267
258
|
}
|
|
268
259
|
return null;
|
|
269
260
|
}
|
|
270
|
-
visitJsCompilationUnit(compilationUnit, p) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
261
|
+
async visitJsCompilationUnit(compilationUnit, p) {
|
|
262
|
+
// First, check if the import already exists
|
|
263
|
+
const hasImport = await this.checkImportExists(compilationUnit);
|
|
264
|
+
if (hasImport) {
|
|
265
|
+
return compilationUnit;
|
|
266
|
+
}
|
|
267
|
+
// If onlyIfReferenced is true, check if the identifier is actually used
|
|
268
|
+
// Skip this check for side-effect imports
|
|
269
|
+
if (!this.sideEffectOnly && this.onlyIfReferenced) {
|
|
270
|
+
const isReferenced = await this.checkIdentifierReferenced(compilationUnit);
|
|
271
|
+
if (!isReferenced) {
|
|
275
272
|
return compilationUnit;
|
|
276
273
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// - Case 1: Existing import has named bindings - merge into them
|
|
290
|
-
// - Case 2: Default import without named bindings - add named bindings
|
|
291
|
-
// Don't try to merge default imports (member === 'default'), side-effect imports, or namespace imports (member === '*')
|
|
292
|
-
if (!this.sideEffectOnly && this.member !== undefined && this.member !== 'default' && this.member !== '*') {
|
|
293
|
-
const mergedCu = yield this.tryMergeIntoExistingImport(compilationUnit, p);
|
|
294
|
-
if (mergedCu !== compilationUnit) {
|
|
295
|
-
return mergedCu;
|
|
296
|
-
}
|
|
274
|
+
}
|
|
275
|
+
// Determine the appropriate import style
|
|
276
|
+
const importStyle = this.determineImportStyle(compilationUnit);
|
|
277
|
+
// For named imports, check if we can merge into an existing import from the same module
|
|
278
|
+
// This handles both:
|
|
279
|
+
// - Case 1: Existing import has named bindings - merge into them
|
|
280
|
+
// - Case 2: Default import without named bindings - add named bindings
|
|
281
|
+
// Don't try to merge default imports (member === 'default'), side-effect imports, or namespace imports (member === '*')
|
|
282
|
+
if (!this.sideEffectOnly && this.member !== undefined && this.member !== 'default' && this.member !== '*') {
|
|
283
|
+
const mergedCu = await this.tryMergeIntoExistingImport(compilationUnit, p);
|
|
284
|
+
if (mergedCu !== compilationUnit) {
|
|
285
|
+
return mergedCu;
|
|
297
286
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
287
|
+
}
|
|
288
|
+
// Add the import using the appropriate style
|
|
289
|
+
if (importStyle === ImportStyle.CommonJS) {
|
|
290
|
+
// TODO: Implement CommonJS require creation
|
|
291
|
+
// For now, fall back to ES6 imports
|
|
292
|
+
// return this.addCommonJSRequire(compilationUnit, p);
|
|
293
|
+
}
|
|
294
|
+
// Add ES6 import (handles ES6Named, ES6Namespace, ES6Default)
|
|
295
|
+
return this.produceJavaScript(compilationUnit, p, async (draft) => {
|
|
296
|
+
// Find the position to insert the import
|
|
297
|
+
const insertionIndex = this.findImportInsertionIndex(compilationUnit);
|
|
298
|
+
const newImport = await this.createImportStatement(compilationUnit, insertionIndex, p);
|
|
299
|
+
// Insert the import at the appropriate position
|
|
300
|
+
// Create semicolon marker for the import statement
|
|
301
|
+
const semicolonMarkers = (0, markers_1.markers)({
|
|
302
|
+
kind: java_1.J.Markers.Semicolon,
|
|
303
|
+
id: (0, uuid_1.randomId)()
|
|
304
|
+
});
|
|
305
|
+
if (insertionIndex === 0) {
|
|
306
|
+
// Insert at the beginning
|
|
307
|
+
// The `after` space should be empty since semicolon is printed after it
|
|
308
|
+
// The spacing comes from updating the next statement's prefix
|
|
309
|
+
const updatedStatements = compilationUnit.statements.length > 0
|
|
310
|
+
? [
|
|
311
|
+
(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
|
|
312
|
+
Object.assign(Object.assign({}, compilationUnit.statements[0]), { element: compilationUnit.statements[0].element
|
|
313
|
+
? Object.assign(Object.assign({}, compilationUnit.statements[0].element), { prefix: (0, java_1.space)("\n\n") }) : undefined }),
|
|
314
|
+
...compilationUnit.statements.slice(1)
|
|
315
|
+
]
|
|
316
|
+
: [(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers)];
|
|
317
|
+
draft.statements = updatedStatements;
|
|
303
318
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
? [
|
|
321
|
-
(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
|
|
322
|
-
Object.assign(Object.assign({}, compilationUnit.statements[0]), { element: compilationUnit.statements[0].element
|
|
323
|
-
? Object.assign(Object.assign({}, compilationUnit.statements[0].element), { prefix: (0, java_1.space)("\n\n") }) : undefined }),
|
|
324
|
-
...compilationUnit.statements.slice(1)
|
|
325
|
-
]
|
|
326
|
-
: [(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers)];
|
|
327
|
-
draft.statements = updatedStatements;
|
|
319
|
+
else {
|
|
320
|
+
// Insert after existing imports
|
|
321
|
+
const before = compilationUnit.statements.slice(0, insertionIndex);
|
|
322
|
+
const after = compilationUnit.statements.slice(insertionIndex);
|
|
323
|
+
//The `after` space is empty, spacing comes from next statement's prefix
|
|
324
|
+
// Ensure the next statement has at least one newline in its prefix
|
|
325
|
+
if (after.length > 0 && after[0].element) {
|
|
326
|
+
const currentPrefix = after[0].element.prefix;
|
|
327
|
+
const needsNewline = !currentPrefix.whitespace.includes('\n');
|
|
328
|
+
const updatedNextStatement = needsNewline ? Object.assign(Object.assign({}, after[0]), { element: Object.assign(Object.assign({}, after[0].element), { prefix: (0, java_1.space)("\n" + currentPrefix.whitespace) }) }) : after[0];
|
|
329
|
+
draft.statements = [
|
|
330
|
+
...before,
|
|
331
|
+
(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
|
|
332
|
+
updatedNextStatement,
|
|
333
|
+
...after.slice(1)
|
|
334
|
+
];
|
|
328
335
|
}
|
|
329
336
|
else {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
if (after.length > 0 && after[0].element) {
|
|
336
|
-
const currentPrefix = after[0].element.prefix;
|
|
337
|
-
const needsNewline = !currentPrefix.whitespace.includes('\n');
|
|
338
|
-
const updatedNextStatement = needsNewline ? Object.assign(Object.assign({}, after[0]), { element: Object.assign(Object.assign({}, after[0].element), { prefix: (0, java_1.space)("\n" + currentPrefix.whitespace) }) }) : after[0];
|
|
339
|
-
draft.statements = [
|
|
340
|
-
...before,
|
|
341
|
-
(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
|
|
342
|
-
updatedNextStatement,
|
|
343
|
-
...after.slice(1)
|
|
344
|
-
];
|
|
345
|
-
}
|
|
346
|
-
else {
|
|
347
|
-
draft.statements = [
|
|
348
|
-
...before,
|
|
349
|
-
(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
|
|
350
|
-
...after
|
|
351
|
-
];
|
|
352
|
-
}
|
|
337
|
+
draft.statements = [
|
|
338
|
+
...before,
|
|
339
|
+
(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
|
|
340
|
+
...after
|
|
341
|
+
];
|
|
353
342
|
}
|
|
354
|
-
}
|
|
343
|
+
}
|
|
355
344
|
});
|
|
356
345
|
}
|
|
357
346
|
/**
|
|
358
347
|
* Try to merge the new member into an existing import from the same module
|
|
359
348
|
*/
|
|
360
|
-
tryMergeIntoExistingImport(compilationUnit, p) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
349
|
+
async tryMergeIntoExistingImport(compilationUnit, p) {
|
|
350
|
+
var _a;
|
|
351
|
+
for (let i = 0; i < compilationUnit.statements.length; i++) {
|
|
352
|
+
const stmt = compilationUnit.statements[i];
|
|
353
|
+
const statement = stmt.element;
|
|
354
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
|
|
355
|
+
const jsImport = statement;
|
|
356
|
+
const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
357
|
+
if (!moduleSpecifier) {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
const moduleName = this.getModuleName(moduleSpecifier);
|
|
361
|
+
// Check if this is an import from our target module
|
|
362
|
+
if (moduleName !== this.module) {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
const importClause = jsImport.importClause;
|
|
366
|
+
if (!importClause) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
// Only merge into imports with matching typeOnly - don't mix type and value imports
|
|
370
|
+
if (importClause.typeOnly !== this.typeOnly) {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
// Case 1: Existing import has named bindings - merge into them
|
|
374
|
+
if (importClause.namedBindings) {
|
|
375
|
+
// Only merge into NamedImports, not namespace imports
|
|
376
|
+
if (importClause.namedBindings.kind !== tree_1.JS.Kind.NamedImports) {
|
|
383
377
|
continue;
|
|
384
378
|
}
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
var _a
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
379
|
+
// We found a matching import with named bindings - merge into it
|
|
380
|
+
return this.produceJavaScript(compilationUnit, p, async (draft) => {
|
|
381
|
+
var _a, _b, _c;
|
|
382
|
+
const namedImports = importClause.namedBindings;
|
|
383
|
+
const existingElements = namedImports.elements.elements;
|
|
384
|
+
// Find the correct insertion position (alphabetical, case-insensitive)
|
|
385
|
+
const newName = (this.alias || this.member).toLowerCase();
|
|
386
|
+
let insertIndex = existingElements.findIndex(elem => {
|
|
387
|
+
var _a;
|
|
388
|
+
if (((_a = elem.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.ImportSpecifier) {
|
|
389
|
+
const name = this.getImportAlias(elem.element) || this.getImportName(elem.element);
|
|
390
|
+
return newName.localeCompare(name.toLowerCase()) < 0;
|
|
391
|
+
}
|
|
392
|
+
return false;
|
|
393
|
+
});
|
|
394
|
+
if (insertIndex === -1)
|
|
395
|
+
insertIndex = existingElements.length;
|
|
396
|
+
// Detect spacing style from existing elements:
|
|
397
|
+
// - firstElementPrefix: space after { (from first element's prefix)
|
|
398
|
+
// - trailingSpace: space before } (from last element's after)
|
|
399
|
+
const firstElementPrefix = (_c = (_b = (_a = existingElements[0]) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.prefix) !== null && _c !== void 0 ? _c : java_1.emptySpace;
|
|
400
|
+
const lastIndex = existingElements.length - 1;
|
|
401
|
+
const trailingSpace = existingElements[lastIndex].after;
|
|
402
|
+
// Build the new elements array with proper spacing
|
|
403
|
+
const updatedNamedImports = await this.produceJavaScript(namedImports, p, async (namedDraft) => {
|
|
404
|
+
const newSpecifier = this.createImportSpecifier();
|
|
405
|
+
const newElements = existingElements.flatMap((elem, j) => {
|
|
406
|
+
const results = [];
|
|
407
|
+
if (j === insertIndex) {
|
|
408
|
+
// Insert new element here
|
|
409
|
+
// First element gets the same prefix as the original first element
|
|
410
|
+
// Other positions get a single space (separator after comma)
|
|
411
|
+
const prefix = j === 0 ? firstElementPrefix : java_1.singleSpace;
|
|
412
|
+
results.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix }), java_1.emptySpace));
|
|
403
413
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
// Detect spacing style from existing elements:
|
|
409
|
-
// - firstElementPrefix: space after { (from first element's prefix)
|
|
410
|
-
// - trailingSpace: space before } (from last element's after)
|
|
411
|
-
const firstElementPrefix = (_c = (_b = (_a = existingElements[0]) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.prefix) !== null && _c !== void 0 ? _c : java_1.emptySpace;
|
|
412
|
-
const lastIndex = existingElements.length - 1;
|
|
413
|
-
const trailingSpace = existingElements[lastIndex].after;
|
|
414
|
-
// Build the new elements array with proper spacing
|
|
415
|
-
const updatedNamedImports = yield this.produceJavaScript(namedImports, p, (namedDraft) => __awaiter(this, void 0, void 0, function* () {
|
|
416
|
-
const newSpecifier = this.createImportSpecifier();
|
|
417
|
-
const newElements = existingElements.flatMap((elem, j) => {
|
|
418
|
-
const results = [];
|
|
419
|
-
if (j === insertIndex) {
|
|
420
|
-
// Insert new element here
|
|
421
|
-
// First element gets the same prefix as the original first element
|
|
422
|
-
// Other positions get a single space (separator after comma)
|
|
423
|
-
const prefix = j === 0 ? firstElementPrefix : java_1.singleSpace;
|
|
424
|
-
results.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix }), java_1.emptySpace));
|
|
425
|
-
}
|
|
426
|
-
// Adjust existing element: if inserting before first, give it space prefix
|
|
427
|
-
let adjusted = elem;
|
|
428
|
-
if (j === 0 && insertIndex === 0 && elem.element) {
|
|
429
|
-
adjusted = Object.assign(Object.assign({}, elem), { element: Object.assign(Object.assign({}, elem.element), { prefix: java_1.singleSpace }) });
|
|
430
|
-
}
|
|
431
|
-
// Last element before a new trailing element loses its trailing space
|
|
432
|
-
if (j === lastIndex && insertIndex > lastIndex) {
|
|
433
|
-
adjusted = Object.assign(Object.assign({}, adjusted), { after: java_1.emptySpace });
|
|
434
|
-
}
|
|
435
|
-
results.push(adjusted);
|
|
436
|
-
return results;
|
|
437
|
-
});
|
|
438
|
-
// Append at end if inserting after all existing elements
|
|
439
|
-
if (insertIndex > lastIndex) {
|
|
440
|
-
newElements.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: java_1.singleSpace }), trailingSpace));
|
|
414
|
+
// Adjust existing element: if inserting before first, give it space prefix
|
|
415
|
+
let adjusted = elem;
|
|
416
|
+
if (j === 0 && insertIndex === 0 && elem.element) {
|
|
417
|
+
adjusted = Object.assign(Object.assign({}, elem), { element: Object.assign(Object.assign({}, elem.element), { prefix: java_1.singleSpace }) });
|
|
441
418
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const updatedImport = yield this.produceJavaScript(jsImport, p, (importDraft) => __awaiter(this, void 0, void 0, function* () {
|
|
446
|
-
importDraft.importClause = yield this.produceJavaScript(importClause, p, (clauseDraft) => __awaiter(this, void 0, void 0, function* () {
|
|
447
|
-
clauseDraft.namedBindings = updatedNamedImports;
|
|
448
|
-
}));
|
|
449
|
-
}));
|
|
450
|
-
// Replace the statement in the compilation unit
|
|
451
|
-
draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
|
|
452
|
-
}));
|
|
453
|
-
}
|
|
454
|
-
// Case 2: Default import without named bindings - add named bindings
|
|
455
|
-
// Transform: import React from 'react' -> import React, { useState } from 'react'
|
|
456
|
-
if (importClause.name && !importClause.namedBindings) {
|
|
457
|
-
return this.produceJavaScript(compilationUnit, p, (draft) => __awaiter(this, void 0, void 0, function* () {
|
|
458
|
-
const newSpecifier = this.createImportSpecifier();
|
|
459
|
-
// Get the spaces style for brace spacing
|
|
460
|
-
const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
|
|
461
|
-
const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
|
|
462
|
-
// Create new NamedImports with a single element
|
|
463
|
-
// Apply brace spacing: space after { is in specifier's prefix, space before } is in after
|
|
464
|
-
const namedImports = {
|
|
465
|
-
id: (0, uuid_1.randomId)(),
|
|
466
|
-
kind: tree_1.JS.Kind.NamedImports,
|
|
467
|
-
prefix: java_1.singleSpace,
|
|
468
|
-
markers: markers_1.emptyMarkers,
|
|
469
|
-
elements: {
|
|
470
|
-
kind: java_1.J.Kind.Container,
|
|
471
|
-
before: java_1.emptySpace,
|
|
472
|
-
elements: [(0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: braceSpace }), braceSpace)],
|
|
473
|
-
markers: markers_1.emptyMarkers
|
|
419
|
+
// Last element before a new trailing element loses its trailing space
|
|
420
|
+
if (j === lastIndex && insertIndex > lastIndex) {
|
|
421
|
+
adjusted = Object.assign(Object.assign({}, adjusted), { after: java_1.emptySpace });
|
|
474
422
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
423
|
+
results.push(adjusted);
|
|
424
|
+
return results;
|
|
425
|
+
});
|
|
426
|
+
// Append at end if inserting after all existing elements
|
|
427
|
+
if (insertIndex > lastIndex) {
|
|
428
|
+
newElements.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: java_1.singleSpace }), trailingSpace));
|
|
429
|
+
}
|
|
430
|
+
namedDraft.elements = Object.assign(Object.assign({}, namedImports.elements), { elements: newElements });
|
|
431
|
+
});
|
|
432
|
+
// Update the import with the new named imports
|
|
433
|
+
const updatedImport = await this.produceJavaScript(jsImport, p, async (importDraft) => {
|
|
434
|
+
importDraft.importClause = await this.produceJavaScript(importClause, p, async (clauseDraft) => {
|
|
435
|
+
clauseDraft.namedBindings = updatedNamedImports;
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
// Replace the statement in the compilation unit
|
|
439
|
+
draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
// Case 2: Default import without named bindings - add named bindings
|
|
443
|
+
// Transform: import React from 'react' -> import React, { useState } from 'react'
|
|
444
|
+
if (importClause.name && !importClause.namedBindings) {
|
|
445
|
+
return this.produceJavaScript(compilationUnit, p, async (draft) => {
|
|
446
|
+
const newSpecifier = this.createImportSpecifier();
|
|
447
|
+
// Get the spaces style for brace spacing
|
|
448
|
+
const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
|
|
449
|
+
const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
|
|
450
|
+
// Create new NamedImports with a single element
|
|
451
|
+
// Apply brace spacing: space after { is in specifier's prefix, space before } is in after
|
|
452
|
+
const namedImports = {
|
|
453
|
+
id: (0, uuid_1.randomId)(),
|
|
454
|
+
kind: tree_1.JS.Kind.NamedImports,
|
|
455
|
+
prefix: java_1.singleSpace,
|
|
456
|
+
markers: markers_1.emptyMarkers,
|
|
457
|
+
elements: {
|
|
458
|
+
kind: java_1.J.Kind.Container,
|
|
459
|
+
before: java_1.emptySpace,
|
|
460
|
+
elements: [(0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: braceSpace }), braceSpace)],
|
|
461
|
+
markers: markers_1.emptyMarkers
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
// Update the import clause to include named bindings
|
|
465
|
+
// Also update name.after to emptySpace since the comma goes right after the name
|
|
466
|
+
const updatedImport = await this.produceJavaScript(jsImport, p, async (importDraft) => {
|
|
467
|
+
importDraft.importClause = await this.produceJavaScript(importClause, p, async (clauseDraft) => {
|
|
468
|
+
// Remove space after default name (comma goes right after)
|
|
469
|
+
if (clauseDraft.name) {
|
|
470
|
+
clauseDraft.name = Object.assign(Object.assign({}, clauseDraft.name), { after: java_1.emptySpace });
|
|
489
471
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
472
|
+
clauseDraft.namedBindings = namedImports;
|
|
473
|
+
});
|
|
474
|
+
// Ensure moduleSpecifier has proper space before 'from'
|
|
475
|
+
if (importDraft.moduleSpecifier) {
|
|
476
|
+
importDraft.moduleSpecifier = Object.assign(Object.assign({}, importDraft.moduleSpecifier), { before: java_1.singleSpace });
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
// Replace the statement in the compilation unit
|
|
480
|
+
draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
|
|
481
|
+
});
|
|
495
482
|
}
|
|
496
483
|
}
|
|
497
|
-
|
|
498
|
-
|
|
484
|
+
}
|
|
485
|
+
return compilationUnit;
|
|
499
486
|
}
|
|
500
487
|
/**
|
|
501
488
|
* Check if the import already exists in the compilation unit
|
|
502
489
|
*/
|
|
503
|
-
checkImportExists(compilationUnit) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
return true;
|
|
512
|
-
}
|
|
490
|
+
async checkImportExists(compilationUnit) {
|
|
491
|
+
for (const stmt of compilationUnit.statements) {
|
|
492
|
+
const statement = stmt.element;
|
|
493
|
+
// Check ES6 imports
|
|
494
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
|
|
495
|
+
const jsImport = statement;
|
|
496
|
+
if (this.isMatchingImport(jsImport)) {
|
|
497
|
+
return true;
|
|
513
498
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
499
|
+
}
|
|
500
|
+
// Check CommonJS require statements
|
|
501
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
|
|
502
|
+
const varDecl = statement;
|
|
503
|
+
if (this.isMatchingRequire(varDecl)) {
|
|
504
|
+
return true;
|
|
520
505
|
}
|
|
521
506
|
}
|
|
522
|
-
|
|
523
|
-
|
|
507
|
+
}
|
|
508
|
+
return false;
|
|
524
509
|
}
|
|
525
510
|
/**
|
|
526
511
|
* Check if the import matches what we're trying to add
|
|
@@ -714,335 +699,311 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
714
699
|
/**
|
|
715
700
|
* Check if the identifier is actually referenced in the file
|
|
716
701
|
*/
|
|
717
|
-
checkIdentifierReferenced(compilationUnit) {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
if
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
identifier = aliasSpec.alias;
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
expectedDeclaringType = this.getModuleFromType(identifier === null || identifier === void 0 ? void 0 : identifier.type, identifier === null || identifier === void 0 ? void 0 : identifier.fieldType);
|
|
761
|
-
if (expectedDeclaringType) {
|
|
762
|
-
break; // Found it!
|
|
702
|
+
async checkIdentifierReferenced(compilationUnit) {
|
|
703
|
+
var _a, _b, _c, _d, _e;
|
|
704
|
+
// For namespace imports, we cannot use type attribution to detect usage
|
|
705
|
+
// because the namespace itself is used as an identifier, not individual members.
|
|
706
|
+
// For simplicity, we skip the onlyIfReferenced check for namespace imports.
|
|
707
|
+
if (this.member === '*') {
|
|
708
|
+
// TODO: Implement proper namespace usage detection by checking if alias identifier is used
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
// Step 1: Find the expected declaring type by examining existing imports from the same module
|
|
712
|
+
let expectedDeclaringType;
|
|
713
|
+
for (const stmt of compilationUnit.statements) {
|
|
714
|
+
const statement = stmt.element;
|
|
715
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
|
|
716
|
+
const jsImport = statement;
|
|
717
|
+
const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
718
|
+
if (!moduleSpecifier) {
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
const moduleName = this.getModuleName(moduleSpecifier);
|
|
722
|
+
if (moduleName !== this.module) {
|
|
723
|
+
continue; // Not the module we're interested in
|
|
724
|
+
}
|
|
725
|
+
// Found an existing import from our target module
|
|
726
|
+
// Extract the declaring type from any imported member with type attribution
|
|
727
|
+
const importClause = jsImport.importClause;
|
|
728
|
+
if (((_b = importClause === null || importClause === void 0 ? void 0 : importClause.namedBindings) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.NamedImports) {
|
|
729
|
+
const namedImports = importClause.namedBindings;
|
|
730
|
+
for (const elem of namedImports.elements.elements) {
|
|
731
|
+
const specifier = elem.element;
|
|
732
|
+
if ((specifier === null || specifier === void 0 ? void 0 : specifier.kind) === tree_1.JS.Kind.ImportSpecifier) {
|
|
733
|
+
const importSpec = specifier;
|
|
734
|
+
let identifier;
|
|
735
|
+
if (((_c = importSpec.specifier) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
|
|
736
|
+
identifier = importSpec.specifier;
|
|
737
|
+
}
|
|
738
|
+
else if (((_d = importSpec.specifier) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.Alias) {
|
|
739
|
+
const aliasSpec = importSpec.specifier;
|
|
740
|
+
if (((_e = aliasSpec.alias) === null || _e === void 0 ? void 0 : _e.kind) === java_1.J.Kind.Identifier) {
|
|
741
|
+
identifier = aliasSpec.alias;
|
|
763
742
|
}
|
|
764
743
|
}
|
|
744
|
+
expectedDeclaringType = this.getModuleFromType(identifier === null || identifier === void 0 ? void 0 : identifier.type, identifier === null || identifier === void 0 ? void 0 : identifier.fieldType);
|
|
745
|
+
if (expectedDeclaringType) {
|
|
746
|
+
break; // Found it!
|
|
747
|
+
}
|
|
765
748
|
}
|
|
766
749
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
750
|
+
}
|
|
751
|
+
if (expectedDeclaringType) {
|
|
752
|
+
break; // No need to scan more imports
|
|
770
753
|
}
|
|
771
754
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
755
|
+
}
|
|
756
|
+
// Step 2: Look for references that match
|
|
757
|
+
const targetName = this.alias || this.member;
|
|
758
|
+
const targetModule = this.module;
|
|
759
|
+
let found = false;
|
|
760
|
+
const self = this;
|
|
761
|
+
// If no existing imports from this module, look for unresolved references
|
|
762
|
+
// If there ARE existing imports, look for references with the expected declaring type
|
|
763
|
+
const collector = new class extends visitor_1.JavaScriptVisitor {
|
|
764
|
+
async visitIdentifier(identifier, p) {
|
|
765
|
+
if (identifier.simpleName === targetName) {
|
|
766
|
+
const type = identifier.type;
|
|
767
|
+
const fieldType = identifier.fieldType;
|
|
768
|
+
if (expectedDeclaringType) {
|
|
769
|
+
// We have an expected declaring type - check for exact match
|
|
770
|
+
if (type && java_1.Type.isMethod(type)) {
|
|
771
|
+
const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(type.declaringType);
|
|
772
|
+
if (declaringTypeName === expectedDeclaringType) {
|
|
773
|
+
found = true;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
else if (type && java_1.Type.isClass(type)) {
|
|
777
|
+
if (self.classTypeMatchesModule(type, expectedDeclaringType)) {
|
|
778
|
+
found = true;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
|
|
782
|
+
const ownerTypeName = fieldType.owner
|
|
783
|
+
? java_1.Type.FullyQualified.getFullyQualifiedName(fieldType.owner)
|
|
784
|
+
: undefined;
|
|
785
|
+
if (ownerTypeName === expectedDeclaringType) {
|
|
786
|
+
found = true;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
// Also check for unresolved references (member isn't imported yet)
|
|
790
|
+
else if (!type && !fieldType) {
|
|
791
|
+
found = true;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
else {
|
|
795
|
+
// No existing imports from this module - look for references that match
|
|
796
|
+
// 1. Unresolved references (no type/unknown type and no fieldType)
|
|
797
|
+
const isUnknownType = !type || type.kind === java_1.Type.Kind.Unknown;
|
|
798
|
+
if (isUnknownType && !fieldType) {
|
|
799
|
+
found = true;
|
|
800
|
+
}
|
|
801
|
+
// 2. References with fieldType matching the target module
|
|
802
|
+
else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
|
|
803
|
+
const variableType = fieldType;
|
|
804
|
+
if (variableType.owner && java_1.Type.isClass(variableType.owner)) {
|
|
805
|
+
// Traverse owningClass chain to find the root module (handles nested namespaces)
|
|
806
|
+
// For example: React.forwardRef -> owner is "React" namespace -> owningClass is "react" module
|
|
807
|
+
let current = variableType.owner;
|
|
808
|
+
// Walk up the owningClass chain until we reach the root
|
|
809
|
+
while (current.owningClass && java_1.Type.isClass(current.owningClass)) {
|
|
810
|
+
current = current.owningClass;
|
|
808
811
|
}
|
|
809
|
-
|
|
810
|
-
|
|
812
|
+
const moduleName = java_1.Type.FullyQualified.getFullyQualifiedName(current);
|
|
813
|
+
if (moduleName === targetModule) {
|
|
811
814
|
found = true;
|
|
812
815
|
}
|
|
813
816
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
// 2. References with fieldType matching the target module
|
|
822
|
-
else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
|
|
823
|
-
const variableType = fieldType;
|
|
824
|
-
if (variableType.owner && java_1.Type.isClass(variableType.owner)) {
|
|
825
|
-
// Traverse owningClass chain to find the root module (handles nested namespaces)
|
|
826
|
-
// For example: React.forwardRef -> owner is "React" namespace -> owningClass is "react" module
|
|
827
|
-
let current = variableType.owner;
|
|
828
|
-
// Walk up the owningClass chain until we reach the root
|
|
829
|
-
while (current.owningClass && java_1.Type.isClass(current.owningClass)) {
|
|
830
|
-
current = current.owningClass;
|
|
831
|
-
}
|
|
832
|
-
const moduleName = java_1.Type.FullyQualified.getFullyQualifiedName(current);
|
|
833
|
-
if (moduleName === targetModule) {
|
|
834
|
-
found = true;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
// 3. References with method type matching the target module
|
|
839
|
-
else if (type && java_1.Type.isMethod(type)) {
|
|
840
|
-
const methodType = type;
|
|
841
|
-
const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
|
|
842
|
-
if (declaringTypeName === targetModule) {
|
|
843
|
-
found = true;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
817
|
+
}
|
|
818
|
+
// 3. References with method type matching the target module
|
|
819
|
+
else if (type && java_1.Type.isMethod(type)) {
|
|
820
|
+
const methodType = type;
|
|
821
|
+
const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
|
|
822
|
+
if (declaringTypeName === targetModule) {
|
|
823
|
+
found = true;
|
|
846
824
|
}
|
|
847
825
|
}
|
|
848
|
-
|
|
849
|
-
});
|
|
826
|
+
}
|
|
850
827
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if (declaringTypeName === expectedDeclaringType) {
|
|
860
|
-
found = true;
|
|
861
|
-
}
|
|
862
|
-
}
|
|
828
|
+
return super.visitIdentifier(identifier, p);
|
|
829
|
+
}
|
|
830
|
+
async visitMethodInvocation(methodInvocation, p) {
|
|
831
|
+
if (methodInvocation.methodType && methodInvocation.methodType.name === targetName) {
|
|
832
|
+
if (expectedDeclaringType) {
|
|
833
|
+
const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodInvocation.methodType.declaringType);
|
|
834
|
+
if (declaringTypeName === expectedDeclaringType) {
|
|
835
|
+
found = true;
|
|
863
836
|
}
|
|
864
|
-
|
|
865
|
-
});
|
|
837
|
+
}
|
|
866
838
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
if (declaringTypeName === expectedDeclaringType) {
|
|
876
|
-
found = true;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
839
|
+
return super.visitMethodInvocation(methodInvocation, p);
|
|
840
|
+
}
|
|
841
|
+
async visitFunctionCall(functionCall, p) {
|
|
842
|
+
if (functionCall.methodType && functionCall.methodType.name === targetName) {
|
|
843
|
+
if (expectedDeclaringType) {
|
|
844
|
+
const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(functionCall.methodType.declaringType);
|
|
845
|
+
if (declaringTypeName === expectedDeclaringType) {
|
|
846
|
+
found = true;
|
|
879
847
|
}
|
|
880
|
-
|
|
881
|
-
});
|
|
848
|
+
}
|
|
882
849
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
if (declaringTypeName === expectedDeclaringType) {
|
|
895
|
-
found = true;
|
|
896
|
-
}
|
|
897
|
-
}
|
|
850
|
+
return super.visitFunctionCall(functionCall, p);
|
|
851
|
+
}
|
|
852
|
+
async visitFieldAccess(fieldAccess, p) {
|
|
853
|
+
const type = fieldAccess.type;
|
|
854
|
+
if (type && java_1.Type.isMethod(type)) {
|
|
855
|
+
const methodType = type;
|
|
856
|
+
if (methodType.name === targetName) {
|
|
857
|
+
if (expectedDeclaringType) {
|
|
858
|
+
const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
|
|
859
|
+
if (declaringTypeName === expectedDeclaringType) {
|
|
860
|
+
found = true;
|
|
898
861
|
}
|
|
899
862
|
}
|
|
900
|
-
|
|
901
|
-
});
|
|
863
|
+
}
|
|
902
864
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
865
|
+
return super.visitFieldAccess(fieldAccess, p);
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
await collector.visit(compilationUnit, undefined);
|
|
869
|
+
return found;
|
|
907
870
|
}
|
|
908
871
|
/**
|
|
909
872
|
* Create a new import statement
|
|
910
873
|
*/
|
|
911
|
-
createImportStatement(compilationUnit, insertionIndex, p) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
874
|
+
async createImportStatement(compilationUnit, insertionIndex, p) {
|
|
875
|
+
// Determine the appropriate prefix (spacing before the import)
|
|
876
|
+
const prefix = this.determineImportPrefix(compilationUnit, insertionIndex);
|
|
877
|
+
// Create the module specifier
|
|
878
|
+
// For side-effect imports, use emptySpace since space comes from LeftPadded.before
|
|
879
|
+
// For regular imports with import clause, use emptySpace since space comes from LeftPadded.before
|
|
880
|
+
// However, the printer expects the space after 'from' in the literal's prefix
|
|
881
|
+
// Note: value contains the unquoted string, valueSource contains the quoted version for printing
|
|
882
|
+
const moduleSpecifier = {
|
|
883
|
+
id: (0, uuid_1.randomId)(),
|
|
884
|
+
kind: java_1.J.Kind.Literal,
|
|
885
|
+
prefix: this.sideEffectOnly ? java_1.emptySpace : java_1.singleSpace,
|
|
886
|
+
markers: markers_1.emptyMarkers,
|
|
887
|
+
value: this.module,
|
|
888
|
+
valueSource: `'${this.module}'`,
|
|
889
|
+
unicodeEscapes: [],
|
|
890
|
+
type: undefined
|
|
891
|
+
};
|
|
892
|
+
let importClause;
|
|
893
|
+
if (this.sideEffectOnly) {
|
|
894
|
+
// Side-effect import: import 'module'
|
|
895
|
+
importClause = undefined;
|
|
896
|
+
}
|
|
897
|
+
else if (this.member === '*') {
|
|
898
|
+
// Namespace import: import * as alias from 'module'
|
|
899
|
+
const propertyName = {
|
|
921
900
|
id: (0, uuid_1.randomId)(),
|
|
922
|
-
kind: java_1.J.Kind.
|
|
923
|
-
prefix:
|
|
901
|
+
kind: java_1.J.Kind.Identifier,
|
|
902
|
+
prefix: java_1.emptySpace,
|
|
924
903
|
markers: markers_1.emptyMarkers,
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
904
|
+
annotations: [],
|
|
905
|
+
simpleName: '*',
|
|
906
|
+
type: undefined,
|
|
907
|
+
fieldType: undefined
|
|
929
908
|
};
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
kind: java_1.J.Kind.Identifier,
|
|
950
|
-
prefix: java_1.singleSpace,
|
|
951
|
-
markers: markers_1.emptyMarkers,
|
|
952
|
-
annotations: [],
|
|
953
|
-
simpleName: this.alias,
|
|
954
|
-
type: undefined,
|
|
955
|
-
fieldType: undefined
|
|
956
|
-
};
|
|
957
|
-
const namespaceBinding = {
|
|
958
|
-
id: (0, uuid_1.randomId)(),
|
|
959
|
-
kind: tree_1.JS.Kind.Alias,
|
|
960
|
-
prefix: java_1.singleSpace,
|
|
961
|
-
markers: markers_1.emptyMarkers,
|
|
962
|
-
propertyName: (0, java_1.rightPadded)(propertyName, java_1.singleSpace),
|
|
963
|
-
alias: aliasIdentifier
|
|
964
|
-
};
|
|
965
|
-
importClause = {
|
|
966
|
-
id: (0, uuid_1.randomId)(),
|
|
967
|
-
kind: tree_1.JS.Kind.ImportClause,
|
|
968
|
-
prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
|
|
969
|
-
markers: markers_1.emptyMarkers,
|
|
970
|
-
typeOnly: this.typeOnly,
|
|
971
|
-
name: undefined,
|
|
972
|
-
namedBindings: namespaceBinding
|
|
973
|
-
};
|
|
974
|
-
}
|
|
975
|
-
else if (this.member === undefined || this.member === 'default') {
|
|
976
|
-
// Default import: import target from 'module'
|
|
977
|
-
// or: import alias from 'module' (when member === 'default')
|
|
978
|
-
const defaultName = {
|
|
979
|
-
id: (0, uuid_1.randomId)(),
|
|
980
|
-
kind: java_1.J.Kind.Identifier,
|
|
981
|
-
prefix: java_1.singleSpace,
|
|
982
|
-
markers: markers_1.emptyMarkers,
|
|
983
|
-
annotations: [],
|
|
984
|
-
simpleName: this.alias || this.module,
|
|
985
|
-
type: undefined,
|
|
986
|
-
fieldType: undefined
|
|
987
|
-
};
|
|
988
|
-
importClause = {
|
|
989
|
-
id: (0, uuid_1.randomId)(),
|
|
990
|
-
kind: tree_1.JS.Kind.ImportClause,
|
|
991
|
-
prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
|
|
992
|
-
markers: markers_1.emptyMarkers,
|
|
993
|
-
typeOnly: this.typeOnly,
|
|
994
|
-
name: (0, java_1.rightPadded)(defaultName, java_1.emptySpace),
|
|
995
|
-
namedBindings: undefined
|
|
996
|
-
};
|
|
997
|
-
}
|
|
998
|
-
else {
|
|
999
|
-
// Named import: import { member } from 'module'
|
|
1000
|
-
// Get the spaces style for brace spacing
|
|
1001
|
-
const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
|
|
1002
|
-
const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
|
|
1003
|
-
const importSpec = this.createImportSpecifier();
|
|
1004
|
-
// Apply brace spacing: the space after { is in the specifier's prefix,
|
|
1005
|
-
// and the space before } is in the rightPadded's after
|
|
1006
|
-
const importSpecWithSpacing = Object.assign(Object.assign({}, importSpec), { prefix: braceSpace });
|
|
1007
|
-
const namedImports = {
|
|
1008
|
-
id: (0, uuid_1.randomId)(),
|
|
1009
|
-
kind: tree_1.JS.Kind.NamedImports,
|
|
1010
|
-
prefix: java_1.singleSpace,
|
|
1011
|
-
markers: markers_1.emptyMarkers,
|
|
1012
|
-
elements: {
|
|
1013
|
-
kind: java_1.J.Kind.Container,
|
|
1014
|
-
before: java_1.emptySpace,
|
|
1015
|
-
elements: [(0, java_1.rightPadded)(importSpecWithSpacing, braceSpace)],
|
|
1016
|
-
markers: markers_1.emptyMarkers
|
|
1017
|
-
}
|
|
1018
|
-
};
|
|
1019
|
-
importClause = {
|
|
1020
|
-
id: (0, uuid_1.randomId)(),
|
|
1021
|
-
kind: tree_1.JS.Kind.ImportClause,
|
|
1022
|
-
prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
|
|
1023
|
-
markers: markers_1.emptyMarkers,
|
|
1024
|
-
typeOnly: this.typeOnly,
|
|
1025
|
-
name: undefined,
|
|
1026
|
-
namedBindings: namedImports
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
const jsImport = {
|
|
909
|
+
const aliasIdentifier = {
|
|
910
|
+
id: (0, uuid_1.randomId)(),
|
|
911
|
+
kind: java_1.J.Kind.Identifier,
|
|
912
|
+
prefix: java_1.singleSpace,
|
|
913
|
+
markers: markers_1.emptyMarkers,
|
|
914
|
+
annotations: [],
|
|
915
|
+
simpleName: this.alias,
|
|
916
|
+
type: undefined,
|
|
917
|
+
fieldType: undefined
|
|
918
|
+
};
|
|
919
|
+
const namespaceBinding = {
|
|
920
|
+
id: (0, uuid_1.randomId)(),
|
|
921
|
+
kind: tree_1.JS.Kind.Alias,
|
|
922
|
+
prefix: java_1.singleSpace,
|
|
923
|
+
markers: markers_1.emptyMarkers,
|
|
924
|
+
propertyName: (0, java_1.rightPadded)(propertyName, java_1.singleSpace),
|
|
925
|
+
alias: aliasIdentifier
|
|
926
|
+
};
|
|
927
|
+
importClause = {
|
|
1030
928
|
id: (0, uuid_1.randomId)(),
|
|
1031
|
-
kind: tree_1.JS.Kind.
|
|
1032
|
-
prefix,
|
|
929
|
+
kind: tree_1.JS.Kind.ImportClause,
|
|
930
|
+
prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
|
|
1033
931
|
markers: markers_1.emptyMarkers,
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
932
|
+
typeOnly: this.typeOnly,
|
|
933
|
+
name: undefined,
|
|
934
|
+
namedBindings: namespaceBinding
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
else if (this.member === undefined || this.member === 'default') {
|
|
938
|
+
// Default import: import target from 'module'
|
|
939
|
+
// or: import alias from 'module' (when member === 'default')
|
|
940
|
+
const defaultName = {
|
|
941
|
+
id: (0, uuid_1.randomId)(),
|
|
942
|
+
kind: java_1.J.Kind.Identifier,
|
|
943
|
+
prefix: java_1.singleSpace,
|
|
944
|
+
markers: markers_1.emptyMarkers,
|
|
945
|
+
annotations: [],
|
|
946
|
+
simpleName: this.alias || this.module,
|
|
947
|
+
type: undefined,
|
|
948
|
+
fieldType: undefined
|
|
949
|
+
};
|
|
950
|
+
importClause = {
|
|
951
|
+
id: (0, uuid_1.randomId)(),
|
|
952
|
+
kind: tree_1.JS.Kind.ImportClause,
|
|
953
|
+
prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
|
|
954
|
+
markers: markers_1.emptyMarkers,
|
|
955
|
+
typeOnly: this.typeOnly,
|
|
956
|
+
name: (0, java_1.rightPadded)(defaultName, java_1.emptySpace),
|
|
957
|
+
namedBindings: undefined
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
// Named import: import { member } from 'module'
|
|
962
|
+
// Get the spaces style for brace spacing
|
|
963
|
+
const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
|
|
964
|
+
const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
|
|
965
|
+
const importSpec = this.createImportSpecifier();
|
|
966
|
+
// Apply brace spacing: the space after { is in the specifier's prefix,
|
|
967
|
+
// and the space before } is in the rightPadded's after
|
|
968
|
+
const importSpecWithSpacing = Object.assign(Object.assign({}, importSpec), { prefix: braceSpace });
|
|
969
|
+
const namedImports = {
|
|
970
|
+
id: (0, uuid_1.randomId)(),
|
|
971
|
+
kind: tree_1.JS.Kind.NamedImports,
|
|
972
|
+
prefix: java_1.singleSpace,
|
|
973
|
+
markers: markers_1.emptyMarkers,
|
|
974
|
+
elements: {
|
|
975
|
+
kind: java_1.J.Kind.Container,
|
|
976
|
+
before: java_1.emptySpace,
|
|
977
|
+
elements: [(0, java_1.rightPadded)(importSpecWithSpacing, braceSpace)],
|
|
1040
978
|
markers: markers_1.emptyMarkers
|
|
1041
|
-
}
|
|
1042
|
-
initializer: undefined
|
|
979
|
+
}
|
|
1043
980
|
};
|
|
1044
|
-
|
|
1045
|
-
|
|
981
|
+
importClause = {
|
|
982
|
+
id: (0, uuid_1.randomId)(),
|
|
983
|
+
kind: tree_1.JS.Kind.ImportClause,
|
|
984
|
+
prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
|
|
985
|
+
markers: markers_1.emptyMarkers,
|
|
986
|
+
typeOnly: this.typeOnly,
|
|
987
|
+
name: undefined,
|
|
988
|
+
namedBindings: namedImports
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
const jsImport = {
|
|
992
|
+
id: (0, uuid_1.randomId)(),
|
|
993
|
+
kind: tree_1.JS.Kind.Import,
|
|
994
|
+
prefix,
|
|
995
|
+
markers: markers_1.emptyMarkers,
|
|
996
|
+
modifiers: [],
|
|
997
|
+
importClause,
|
|
998
|
+
moduleSpecifier: {
|
|
999
|
+
kind: java_1.J.Kind.LeftPadded,
|
|
1000
|
+
before: java_1.singleSpace,
|
|
1001
|
+
element: moduleSpecifier,
|
|
1002
|
+
markers: markers_1.emptyMarkers
|
|
1003
|
+
},
|
|
1004
|
+
initializer: undefined
|
|
1005
|
+
};
|
|
1006
|
+
return jsImport;
|
|
1046
1007
|
}
|
|
1047
1008
|
/**
|
|
1048
1009
|
* Create an import specifier for a named import
|