@openrewrite/rewrite 8.66.0-20251027-112229 → 8.66.0-20251027-133754

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.
@@ -0,0 +1,789 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AddImport = exports.ImportStyle = void 0;
13
+ exports.maybeAddImport = maybeAddImport;
14
+ const visitor_1 = require("./visitor");
15
+ const java_1 = require("../java");
16
+ const tree_1 = require("./tree");
17
+ const uuid_1 = require("../uuid");
18
+ const markers_1 = require("../markers");
19
+ const execution_1 = require("../execution");
20
+ var ImportStyle;
21
+ (function (ImportStyle) {
22
+ ImportStyle[ImportStyle["ES6Named"] = 0] = "ES6Named";
23
+ ImportStyle[ImportStyle["ES6Namespace"] = 1] = "ES6Namespace";
24
+ ImportStyle[ImportStyle["ES6Default"] = 2] = "ES6Default";
25
+ ImportStyle[ImportStyle["CommonJS"] = 3] = "CommonJS"; // const x = require('module')
26
+ })(ImportStyle || (exports.ImportStyle = ImportStyle = {}));
27
+ /**
28
+ * Register an AddImport visitor to add an import statement to a JavaScript/TypeScript file
29
+ * @param visitor The visitor to add the import addition to
30
+ * @param options Configuration options for the import to add
31
+ */
32
+ function maybeAddImport(visitor, options) {
33
+ for (const v of visitor.afterVisit || []) {
34
+ if (v instanceof AddImport &&
35
+ v.target === options.target &&
36
+ v.member === options.member &&
37
+ v.alias === options.alias) {
38
+ return;
39
+ }
40
+ }
41
+ visitor.afterVisit.push(new AddImport(options));
42
+ }
43
+ class AddImport extends visitor_1.JavaScriptVisitor {
44
+ constructor(options) {
45
+ var _a;
46
+ super();
47
+ this.target = options.target;
48
+ this.member = options.member;
49
+ this.alias = options.alias;
50
+ this.onlyIfReferenced = (_a = options.onlyIfReferenced) !== null && _a !== void 0 ? _a : true;
51
+ this.style = options.style;
52
+ }
53
+ /**
54
+ * Extract module name from a module specifier literal
55
+ */
56
+ getModuleName(moduleSpecifier) {
57
+ var _a;
58
+ if (moduleSpecifier.kind !== java_1.J.Kind.Literal) {
59
+ return undefined;
60
+ }
61
+ return (_a = moduleSpecifier.value) === null || _a === void 0 ? void 0 : _a.toString();
62
+ }
63
+ /**
64
+ * Check if a method invocation is a require() call
65
+ */
66
+ isRequireCall(methodInv) {
67
+ var _a;
68
+ return ((_a = methodInv.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
69
+ methodInv.name.simpleName === 'require';
70
+ }
71
+ /**
72
+ * Determine the appropriate import style based on file type and existing imports
73
+ */
74
+ determineImportStyle(compilationUnit) {
75
+ var _a;
76
+ // If style was explicitly provided, use it
77
+ if (this.style !== undefined) {
78
+ return this.style;
79
+ }
80
+ // Check the file extension from sourcePath
81
+ const sourcePath = compilationUnit.sourcePath;
82
+ const isTypeScript = sourcePath.endsWith('.ts') ||
83
+ sourcePath.endsWith('.tsx') ||
84
+ sourcePath.endsWith('.mts') ||
85
+ sourcePath.endsWith('.cts');
86
+ // Check for .cjs extension - must use CommonJS
87
+ if (sourcePath.endsWith('.cjs')) {
88
+ return ImportStyle.CommonJS;
89
+ }
90
+ // First, check if there's already an import from the same module
91
+ // and match that style
92
+ const existingStyleForModule = this.findExistingImportStyleForModule(compilationUnit);
93
+ if (existingStyleForModule !== null) {
94
+ return existingStyleForModule;
95
+ }
96
+ // For .mjs or TypeScript, prefer ES6
97
+ if (sourcePath.endsWith('.mjs') || isTypeScript) {
98
+ // If we're importing a member, use named imports
99
+ if (this.member !== undefined) {
100
+ return ImportStyle.ES6Named;
101
+ }
102
+ // Otherwise default import
103
+ return ImportStyle.ES6Default;
104
+ }
105
+ // For .js files, check what style is predominantly being used
106
+ let hasNamedImports = false;
107
+ let hasNamespaceImports = false;
108
+ let hasDefaultImports = false;
109
+ let hasCommonJSRequires = false;
110
+ for (const stmt of compilationUnit.statements) {
111
+ const statement = stmt.element;
112
+ // Check for ES6 imports
113
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
114
+ const jsImport = statement;
115
+ const importClause = jsImport.importClause;
116
+ if (importClause) {
117
+ // Check for named bindings
118
+ if (importClause.namedBindings) {
119
+ if (importClause.namedBindings.kind === tree_1.JS.Kind.NamedImports) {
120
+ hasNamedImports = true;
121
+ }
122
+ else if (importClause.namedBindings.kind === java_1.J.Kind.Identifier ||
123
+ importClause.namedBindings.kind === tree_1.JS.Kind.Alias) {
124
+ // import * as x from 'module'
125
+ hasNamespaceImports = true;
126
+ }
127
+ }
128
+ // Check for default import
129
+ if (importClause.name) {
130
+ hasDefaultImports = true;
131
+ }
132
+ }
133
+ }
134
+ // Check for CommonJS requires
135
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
136
+ const varDecl = statement;
137
+ if (varDecl.variables.length === 1) {
138
+ const namedVar = varDecl.variables[0].element;
139
+ const initializer = (_a = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
140
+ if ((initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation &&
141
+ this.isRequireCall(initializer)) {
142
+ hasCommonJSRequires = true;
143
+ }
144
+ }
145
+ }
146
+ }
147
+ // Prefer matching the predominant style
148
+ // If file uses CommonJS, stick with it
149
+ if (hasCommonJSRequires && !hasNamedImports && !hasNamespaceImports && !hasDefaultImports) {
150
+ return ImportStyle.CommonJS;
151
+ }
152
+ // If importing a member, prefer named imports if they exist in the file
153
+ if (this.member !== undefined) {
154
+ if (hasNamedImports) {
155
+ return ImportStyle.ES6Named;
156
+ }
157
+ if (hasNamespaceImports) {
158
+ return ImportStyle.ES6Namespace;
159
+ }
160
+ }
161
+ // For default/whole module imports
162
+ if (this.member === undefined) {
163
+ if (hasNamespaceImports) {
164
+ return ImportStyle.ES6Namespace;
165
+ }
166
+ if (hasDefaultImports) {
167
+ return ImportStyle.ES6Default;
168
+ }
169
+ }
170
+ // Default to named imports for members, default imports for modules
171
+ return this.member !== undefined ? ImportStyle.ES6Named : ImportStyle.ES6Default;
172
+ }
173
+ /**
174
+ * Find the import style used for an existing import from the same module
175
+ */
176
+ findExistingImportStyleForModule(compilationUnit) {
177
+ var _a, _b;
178
+ for (const stmt of compilationUnit.statements) {
179
+ const statement = stmt.element;
180
+ // Check ES6 imports
181
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
182
+ const jsImport = statement;
183
+ const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
184
+ if (moduleSpecifier) {
185
+ const moduleName = this.getModuleName(moduleSpecifier);
186
+ if (moduleName === this.target) {
187
+ const importClause = jsImport.importClause;
188
+ if (importClause === null || importClause === void 0 ? void 0 : importClause.namedBindings) {
189
+ if (importClause.namedBindings.kind === tree_1.JS.Kind.NamedImports) {
190
+ return ImportStyle.ES6Named;
191
+ }
192
+ else {
193
+ return ImportStyle.ES6Namespace;
194
+ }
195
+ }
196
+ if (importClause === null || importClause === void 0 ? void 0 : importClause.name) {
197
+ return ImportStyle.ES6Default;
198
+ }
199
+ }
200
+ }
201
+ }
202
+ // Check CommonJS requires
203
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
204
+ const varDecl = statement;
205
+ if (varDecl.variables.length === 1) {
206
+ const namedVar = varDecl.variables[0].element;
207
+ const initializer = (_b = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _b === void 0 ? void 0 : _b.element;
208
+ if ((initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation &&
209
+ this.isRequireCall(initializer)) {
210
+ const moduleName = this.getModuleNameFromRequire(initializer);
211
+ if (moduleName === this.target) {
212
+ return ImportStyle.CommonJS;
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+ return null;
219
+ }
220
+ visitJsCompilationUnit(compilationUnit, p) {
221
+ return __awaiter(this, void 0, void 0, function* () {
222
+ // First, check if the import already exists
223
+ const hasImport = yield this.checkImportExists(compilationUnit);
224
+ if (hasImport) {
225
+ return compilationUnit;
226
+ }
227
+ // If onlyIfReferenced is true, check if the identifier is actually used
228
+ if (this.onlyIfReferenced) {
229
+ const isReferenced = yield this.checkIdentifierReferenced(compilationUnit);
230
+ if (!isReferenced) {
231
+ return compilationUnit;
232
+ }
233
+ }
234
+ // Determine the appropriate import style
235
+ const importStyle = this.determineImportStyle(compilationUnit);
236
+ // For ES6 named imports, check if we can merge into an existing import from the same module
237
+ if (importStyle === ImportStyle.ES6Named && this.member !== undefined) {
238
+ const mergedCu = yield this.tryMergeIntoExistingImport(compilationUnit, p);
239
+ if (mergedCu !== compilationUnit) {
240
+ return mergedCu;
241
+ }
242
+ }
243
+ // Add the import using the appropriate style
244
+ if (importStyle === ImportStyle.CommonJS) {
245
+ // TODO: Implement CommonJS require creation
246
+ // For now, fall back to ES6 imports
247
+ // return this.addCommonJSRequire(compilationUnit, p);
248
+ }
249
+ // Add ES6 import (handles ES6Named, ES6Namespace, ES6Default)
250
+ return this.produceJavaScript(compilationUnit, p, (draft) => __awaiter(this, void 0, void 0, function* () {
251
+ // Find the position to insert the import
252
+ const insertionIndex = this.findImportInsertionIndex(compilationUnit);
253
+ const newImport = yield this.createImportStatement(compilationUnit, insertionIndex, p);
254
+ // Insert the import at the appropriate position
255
+ // Create semicolon marker for the import statement
256
+ const semicolonMarkers = (0, markers_1.markers)({
257
+ kind: java_1.J.Markers.Semicolon,
258
+ id: (0, uuid_1.randomId)()
259
+ });
260
+ if (insertionIndex === 0) {
261
+ // Insert at the beginning
262
+ // The `after` space should be empty since semicolon is printed after it
263
+ // The spacing comes from updating the next statement's prefix
264
+ const updatedStatements = compilationUnit.statements.length > 0
265
+ ? [
266
+ (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
267
+ Object.assign(Object.assign({}, compilationUnit.statements[0]), { element: compilationUnit.statements[0].element
268
+ ? Object.assign(Object.assign({}, compilationUnit.statements[0].element), { prefix: (0, java_1.space)("\n\n") }) : undefined }),
269
+ ...compilationUnit.statements.slice(1)
270
+ ]
271
+ : [(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers)];
272
+ draft.statements = updatedStatements;
273
+ }
274
+ else {
275
+ // Insert after existing imports
276
+ const before = compilationUnit.statements.slice(0, insertionIndex);
277
+ const after = compilationUnit.statements.slice(insertionIndex);
278
+ //The `after` space is empty, spacing comes from next statement's prefix
279
+ // Ensure the next statement has at least one newline in its prefix
280
+ if (after.length > 0 && after[0].element) {
281
+ const currentPrefix = after[0].element.prefix;
282
+ const needsNewline = !currentPrefix.whitespace.includes('\n');
283
+ 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];
284
+ draft.statements = [
285
+ ...before,
286
+ (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
287
+ updatedNextStatement,
288
+ ...after.slice(1)
289
+ ];
290
+ }
291
+ else {
292
+ draft.statements = [
293
+ ...before,
294
+ (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
295
+ ...after
296
+ ];
297
+ }
298
+ }
299
+ }));
300
+ });
301
+ }
302
+ /**
303
+ * Try to merge the new member into an existing import from the same module
304
+ */
305
+ tryMergeIntoExistingImport(compilationUnit, p) {
306
+ return __awaiter(this, void 0, void 0, function* () {
307
+ var _a;
308
+ for (let i = 0; i < compilationUnit.statements.length; i++) {
309
+ const stmt = compilationUnit.statements[i];
310
+ const statement = stmt.element;
311
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
312
+ const jsImport = statement;
313
+ const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
314
+ if (!moduleSpecifier) {
315
+ continue;
316
+ }
317
+ const moduleName = this.getModuleName(moduleSpecifier);
318
+ // Check if this is an import from our target module
319
+ if (moduleName !== this.target) {
320
+ continue;
321
+ }
322
+ const importClause = jsImport.importClause;
323
+ if (!importClause || !importClause.namedBindings) {
324
+ continue;
325
+ }
326
+ // Only merge into NamedImports, not namespace imports
327
+ if (importClause.namedBindings.kind !== tree_1.JS.Kind.NamedImports) {
328
+ continue;
329
+ }
330
+ // We found a matching import with named bindings - merge into it
331
+ return this.produceJavaScript(compilationUnit, p, (draft) => __awaiter(this, void 0, void 0, function* () {
332
+ const namedImports = importClause.namedBindings;
333
+ // Create the new specifier with a space prefix (since it's not the first element)
334
+ const newSpecifierBase = this.createImportSpecifier();
335
+ const newSpecifier = Object.assign(Object.assign({}, newSpecifierBase), { prefix: java_1.singleSpace });
336
+ // Add the new specifier to the elements
337
+ const updatedNamedImports = yield this.produceJavaScript(namedImports, p, (namedDraft) => __awaiter(this, void 0, void 0, function* () {
338
+ namedDraft.elements = Object.assign(Object.assign({}, namedImports.elements), { elements: [
339
+ ...namedImports.elements.elements,
340
+ (0, java_1.rightPadded)(newSpecifier, java_1.emptySpace)
341
+ ] });
342
+ }));
343
+ // Update the import with the new named imports
344
+ const updatedImport = yield this.produceJavaScript(jsImport, p, (importDraft) => __awaiter(this, void 0, void 0, function* () {
345
+ importDraft.importClause = yield this.produceJavaScript(importClause, p, (clauseDraft) => __awaiter(this, void 0, void 0, function* () {
346
+ clauseDraft.namedBindings = updatedNamedImports;
347
+ }));
348
+ }));
349
+ // Replace the statement in the compilation unit
350
+ draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
351
+ }));
352
+ }
353
+ }
354
+ return compilationUnit;
355
+ });
356
+ }
357
+ /**
358
+ * Check if the import already exists in the compilation unit
359
+ */
360
+ checkImportExists(compilationUnit) {
361
+ return __awaiter(this, void 0, void 0, function* () {
362
+ for (const stmt of compilationUnit.statements) {
363
+ const statement = stmt.element;
364
+ // Check ES6 imports
365
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
366
+ const jsImport = statement;
367
+ if (this.isMatchingImport(jsImport)) {
368
+ return true;
369
+ }
370
+ }
371
+ // Check CommonJS require statements
372
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
373
+ const varDecl = statement;
374
+ if (this.isMatchingRequire(varDecl)) {
375
+ return true;
376
+ }
377
+ }
378
+ }
379
+ return false;
380
+ });
381
+ }
382
+ /**
383
+ * Check if the import matches what we're trying to add
384
+ */
385
+ isMatchingImport(jsImport) {
386
+ var _a, _b;
387
+ // Check module specifier
388
+ const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
389
+ if (!moduleSpecifier) {
390
+ return false;
391
+ }
392
+ const moduleName = this.getModuleName(moduleSpecifier);
393
+ if (moduleName !== this.target) {
394
+ return false;
395
+ }
396
+ const importClause = jsImport.importClause;
397
+ if (!importClause) {
398
+ return false;
399
+ }
400
+ // Check if the specific member or default import already exists
401
+ if (this.member === undefined) {
402
+ // We're adding a default import, check if one exists
403
+ return importClause.name !== undefined;
404
+ }
405
+ else {
406
+ // We're adding a named import, check if it exists
407
+ const namedBindings = importClause.namedBindings;
408
+ if (!namedBindings) {
409
+ return false;
410
+ }
411
+ if (namedBindings.kind === tree_1.JS.Kind.NamedImports) {
412
+ const namedImports = namedBindings;
413
+ for (const elem of namedImports.elements.elements) {
414
+ if (((_b = elem.element) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.ImportSpecifier) {
415
+ const specifier = elem.element;
416
+ const importName = this.getImportName(specifier);
417
+ const aliasName = this.getImportAlias(specifier);
418
+ if (importName === this.member && aliasName === this.alias) {
419
+ return true;
420
+ }
421
+ }
422
+ }
423
+ }
424
+ }
425
+ return false;
426
+ }
427
+ /**
428
+ * Check if this is a matching CommonJS require statement
429
+ */
430
+ isMatchingRequire(varDecl) {
431
+ var _a, _b, _c;
432
+ if (varDecl.variables.length !== 1) {
433
+ return false;
434
+ }
435
+ const namedVar = varDecl.variables[0].element;
436
+ if (!namedVar) {
437
+ return false;
438
+ }
439
+ const initializer = (_a = namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
440
+ if (!initializer || initializer.kind !== java_1.J.Kind.MethodInvocation) {
441
+ return false;
442
+ }
443
+ const methodInv = initializer;
444
+ if (!this.isRequireCall(methodInv)) {
445
+ return false;
446
+ }
447
+ const moduleName = this.getModuleNameFromRequire(methodInv);
448
+ if (moduleName !== this.target) {
449
+ return false;
450
+ }
451
+ // Check if the variable name matches what we're trying to add
452
+ const pattern = namedVar.name;
453
+ if (this.member === undefined && (pattern === null || pattern === void 0 ? void 0 : pattern.kind) === java_1.J.Kind.Identifier) {
454
+ // Default import style: const fs = require('fs')
455
+ return true;
456
+ }
457
+ else if (this.member !== undefined && (pattern === null || pattern === void 0 ? void 0 : pattern.kind) === tree_1.JS.Kind.ObjectBindingPattern) {
458
+ // Destructured import: const { member } = require('module')
459
+ const objectPattern = pattern;
460
+ for (const elem of objectPattern.bindings.elements) {
461
+ if (((_b = elem.element) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.BindingElement) {
462
+ const bindingElem = elem.element;
463
+ const name = (_c = bindingElem.name) === null || _c === void 0 ? void 0 : _c.simpleName;
464
+ if (name === (this.alias || this.member)) {
465
+ return true;
466
+ }
467
+ }
468
+ }
469
+ }
470
+ return false;
471
+ }
472
+ /**
473
+ * Check if the identifier is actually referenced in the file
474
+ */
475
+ checkIdentifierReferenced(compilationUnit) {
476
+ return __awaiter(this, void 0, void 0, function* () {
477
+ // Use type attribution to detect if the identifier is referenced
478
+ // Map of module name -> Set of member names used from that module
479
+ const usedImports = new Map();
480
+ // Helper to record usage of a method from a module
481
+ const recordMethodUsage = (methodType) => {
482
+ const moduleName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
483
+ if (moduleName) {
484
+ if (!usedImports.has(moduleName)) {
485
+ usedImports.set(moduleName, new Set());
486
+ }
487
+ usedImports.get(moduleName).add(methodType.name);
488
+ }
489
+ };
490
+ // Create a visitor to collect used identifiers with their type attribution
491
+ const collector = new class extends visitor_1.JavaScriptVisitor {
492
+ visitIdentifier(identifier, p) {
493
+ const _super = Object.create(null, {
494
+ visitIdentifier: { get: () => super.visitIdentifier }
495
+ });
496
+ return __awaiter(this, void 0, void 0, function* () {
497
+ const type = identifier.type;
498
+ if (type && java_1.Type.isMethod(type)) {
499
+ recordMethodUsage(type);
500
+ }
501
+ return _super.visitIdentifier.call(this, identifier, p);
502
+ });
503
+ }
504
+ visitMethodInvocation(methodInvocation, p) {
505
+ const _super = Object.create(null, {
506
+ visitMethodInvocation: { get: () => super.visitMethodInvocation }
507
+ });
508
+ return __awaiter(this, void 0, void 0, function* () {
509
+ if (methodInvocation.methodType) {
510
+ recordMethodUsage(methodInvocation.methodType);
511
+ }
512
+ return _super.visitMethodInvocation.call(this, methodInvocation, p);
513
+ });
514
+ }
515
+ visitFunctionCall(functionCall, p) {
516
+ const _super = Object.create(null, {
517
+ visitFunctionCall: { get: () => super.visitFunctionCall }
518
+ });
519
+ return __awaiter(this, void 0, void 0, function* () {
520
+ if (functionCall.methodType) {
521
+ recordMethodUsage(functionCall.methodType);
522
+ }
523
+ return _super.visitFunctionCall.call(this, functionCall, p);
524
+ });
525
+ }
526
+ visitFieldAccess(fieldAccess, p) {
527
+ const _super = Object.create(null, {
528
+ visitFieldAccess: { get: () => super.visitFieldAccess }
529
+ });
530
+ return __awaiter(this, void 0, void 0, function* () {
531
+ const type = fieldAccess.type;
532
+ if (type && java_1.Type.isMethod(type)) {
533
+ recordMethodUsage(type);
534
+ }
535
+ return _super.visitFieldAccess.call(this, fieldAccess, p);
536
+ });
537
+ }
538
+ };
539
+ yield collector.visit(compilationUnit, new execution_1.ExecutionContext());
540
+ // Check if our target import is used based on type attribution
541
+ const moduleMembers = usedImports.get(this.target);
542
+ if (!moduleMembers) {
543
+ return false;
544
+ }
545
+ // For specific members, check if that member is used; otherwise check if any member is used
546
+ return this.member ? moduleMembers.has(this.member) : moduleMembers.size > 0;
547
+ });
548
+ }
549
+ /**
550
+ * Create a new import statement
551
+ */
552
+ createImportStatement(compilationUnit, insertionIndex, p) {
553
+ return __awaiter(this, void 0, void 0, function* () {
554
+ // Determine the appropriate prefix (spacing before the import)
555
+ const prefix = this.determineImportPrefix(compilationUnit, insertionIndex);
556
+ // Create the module specifier
557
+ const moduleSpecifier = {
558
+ id: (0, uuid_1.randomId)(),
559
+ kind: java_1.J.Kind.Literal,
560
+ prefix: java_1.singleSpace,
561
+ markers: markers_1.emptyMarkers,
562
+ value: `'${this.target}'`,
563
+ valueSource: `'${this.target}'`,
564
+ unicodeEscapes: [],
565
+ type: undefined
566
+ };
567
+ let importClause;
568
+ if (this.member === undefined) {
569
+ // Default import: import target from 'module'
570
+ const defaultName = {
571
+ id: (0, uuid_1.randomId)(),
572
+ kind: java_1.J.Kind.Identifier,
573
+ prefix: java_1.singleSpace,
574
+ markers: markers_1.emptyMarkers,
575
+ annotations: [],
576
+ simpleName: this.alias || this.target,
577
+ type: undefined,
578
+ fieldType: undefined
579
+ };
580
+ importClause = {
581
+ id: (0, uuid_1.randomId)(),
582
+ kind: tree_1.JS.Kind.ImportClause,
583
+ prefix: java_1.emptySpace,
584
+ markers: markers_1.emptyMarkers,
585
+ typeOnly: false,
586
+ name: (0, java_1.rightPadded)(defaultName, java_1.emptySpace),
587
+ namedBindings: undefined
588
+ };
589
+ }
590
+ else {
591
+ // Named import: import { member } from 'module'
592
+ const importSpec = this.createImportSpecifier();
593
+ const namedImports = {
594
+ id: (0, uuid_1.randomId)(),
595
+ kind: tree_1.JS.Kind.NamedImports,
596
+ prefix: java_1.singleSpace,
597
+ markers: markers_1.emptyMarkers,
598
+ elements: {
599
+ kind: java_1.J.Kind.Container,
600
+ before: java_1.emptySpace,
601
+ elements: [(0, java_1.rightPadded)(importSpec, java_1.emptySpace)],
602
+ markers: markers_1.emptyMarkers
603
+ }
604
+ };
605
+ importClause = {
606
+ id: (0, uuid_1.randomId)(),
607
+ kind: tree_1.JS.Kind.ImportClause,
608
+ prefix: java_1.emptySpace,
609
+ markers: markers_1.emptyMarkers,
610
+ typeOnly: false,
611
+ name: undefined,
612
+ namedBindings: namedImports
613
+ };
614
+ }
615
+ const jsImport = {
616
+ id: (0, uuid_1.randomId)(),
617
+ kind: tree_1.JS.Kind.Import,
618
+ prefix,
619
+ markers: markers_1.emptyMarkers,
620
+ modifiers: [],
621
+ importClause,
622
+ moduleSpecifier: {
623
+ kind: java_1.J.Kind.LeftPadded,
624
+ before: java_1.singleSpace,
625
+ element: moduleSpecifier,
626
+ markers: markers_1.emptyMarkers
627
+ },
628
+ initializer: undefined
629
+ };
630
+ return jsImport;
631
+ });
632
+ }
633
+ /**
634
+ * Create an import specifier for a named import
635
+ */
636
+ createImportSpecifier() {
637
+ let specifier;
638
+ if (this.alias) {
639
+ // Aliased import: import { member as alias } from 'module'
640
+ const propertyName = {
641
+ id: (0, uuid_1.randomId)(),
642
+ kind: java_1.J.Kind.Identifier,
643
+ prefix: java_1.emptySpace,
644
+ markers: markers_1.emptyMarkers,
645
+ annotations: [],
646
+ simpleName: this.member,
647
+ type: undefined,
648
+ fieldType: undefined
649
+ };
650
+ const aliasName = {
651
+ id: (0, uuid_1.randomId)(),
652
+ kind: java_1.J.Kind.Identifier,
653
+ prefix: java_1.singleSpace,
654
+ markers: markers_1.emptyMarkers,
655
+ annotations: [],
656
+ simpleName: this.alias,
657
+ type: undefined,
658
+ fieldType: undefined
659
+ };
660
+ specifier = {
661
+ id: (0, uuid_1.randomId)(),
662
+ kind: tree_1.JS.Kind.Alias,
663
+ prefix: java_1.emptySpace,
664
+ markers: markers_1.emptyMarkers,
665
+ propertyName: (0, java_1.rightPadded)(propertyName, java_1.singleSpace),
666
+ alias: aliasName
667
+ };
668
+ }
669
+ else {
670
+ // Regular import: import { member } from 'module'
671
+ specifier = {
672
+ id: (0, uuid_1.randomId)(),
673
+ kind: java_1.J.Kind.Identifier,
674
+ prefix: java_1.emptySpace,
675
+ markers: markers_1.emptyMarkers,
676
+ annotations: [],
677
+ simpleName: this.member,
678
+ type: undefined,
679
+ fieldType: undefined
680
+ };
681
+ }
682
+ return {
683
+ id: (0, uuid_1.randomId)(),
684
+ kind: tree_1.JS.Kind.ImportSpecifier,
685
+ prefix: java_1.emptySpace,
686
+ markers: markers_1.emptyMarkers,
687
+ importType: {
688
+ kind: java_1.J.Kind.LeftPadded,
689
+ before: java_1.emptySpace,
690
+ element: false,
691
+ markers: markers_1.emptyMarkers
692
+ },
693
+ specifier
694
+ };
695
+ }
696
+ /**
697
+ * Determine the appropriate spacing before the import statement
698
+ */
699
+ determineImportPrefix(compilationUnit, insertionIndex) {
700
+ var _a;
701
+ // If inserting at the beginning (index 0), use the prefix of the first statement
702
+ // but only the whitespace part (preserve comments on the original first statement)
703
+ if (insertionIndex === 0 && compilationUnit.statements.length > 0) {
704
+ const firstPrefix = (_a = compilationUnit.statements[0].element) === null || _a === void 0 ? void 0 : _a.prefix;
705
+ if (firstPrefix) {
706
+ // Keep only whitespace, not comments
707
+ return {
708
+ kind: java_1.J.Kind.Space,
709
+ comments: [],
710
+ whitespace: firstPrefix.whitespace
711
+ };
712
+ }
713
+ return java_1.emptySpace;
714
+ }
715
+ // If inserting after other statements, ensure we have at least one newline
716
+ // to separate from the previous statement
717
+ return (0, java_1.space)("\n");
718
+ }
719
+ /**
720
+ * Find the index where the new import should be inserted
721
+ */
722
+ findImportInsertionIndex(compilationUnit) {
723
+ let lastImportIndex = -1;
724
+ for (let i = 0; i < compilationUnit.statements.length; i++) {
725
+ const statement = compilationUnit.statements[i].element;
726
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
727
+ lastImportIndex = i;
728
+ }
729
+ else if (lastImportIndex >= 0) {
730
+ // We've found a non-import after imports, insert after the last import
731
+ return lastImportIndex + 1;
732
+ }
733
+ }
734
+ // If we found imports, insert after them
735
+ if (lastImportIndex >= 0) {
736
+ return lastImportIndex + 1;
737
+ }
738
+ // No imports found, insert at the beginning
739
+ return 0;
740
+ }
741
+ /**
742
+ * Get the module name from a require() call
743
+ */
744
+ getModuleNameFromRequire(methodInv) {
745
+ var _a, _b;
746
+ const args = (_a = methodInv.arguments) === null || _a === void 0 ? void 0 : _a.elements;
747
+ if (!args || args.length === 0) {
748
+ return undefined;
749
+ }
750
+ const firstArg = args[0].element;
751
+ if (!firstArg || firstArg.kind !== java_1.J.Kind.Literal || typeof firstArg.value !== 'string') {
752
+ return undefined;
753
+ }
754
+ return (_b = firstArg.value) === null || _b === void 0 ? void 0 : _b.toString();
755
+ }
756
+ /**
757
+ * Get the import name from an import specifier
758
+ */
759
+ getImportName(specifier) {
760
+ const spec = specifier.specifier;
761
+ if ((spec === null || spec === void 0 ? void 0 : spec.kind) === tree_1.JS.Kind.Alias) {
762
+ const alias = spec;
763
+ const propertyName = alias.propertyName.element;
764
+ if ((propertyName === null || propertyName === void 0 ? void 0 : propertyName.kind) === java_1.J.Kind.Identifier) {
765
+ return propertyName.simpleName;
766
+ }
767
+ }
768
+ else if ((spec === null || spec === void 0 ? void 0 : spec.kind) === java_1.J.Kind.Identifier) {
769
+ return spec.simpleName;
770
+ }
771
+ return '';
772
+ }
773
+ /**
774
+ * Get the import alias from an import specifier
775
+ */
776
+ getImportAlias(specifier) {
777
+ var _a;
778
+ const spec = specifier.specifier;
779
+ if ((spec === null || spec === void 0 ? void 0 : spec.kind) === tree_1.JS.Kind.Alias) {
780
+ const alias = spec;
781
+ if (((_a = alias.alias) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier) {
782
+ return alias.alias.simpleName;
783
+ }
784
+ }
785
+ return undefined;
786
+ }
787
+ }
788
+ exports.AddImport = AddImport;
789
+ //# sourceMappingURL=add-import.js.map