@openrewrite/rewrite 8.91.0 → 8.91.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/java/formatting-utils.d.ts +8 -5
  2. package/dist/java/formatting-utils.d.ts.map +1 -1
  3. package/dist/java/formatting-utils.js +14 -10
  4. package/dist/java/formatting-utils.js.map +1 -1
  5. package/dist/java/type.d.ts +2 -0
  6. package/dist/java/type.d.ts.map +1 -1
  7. package/dist/java/type.js +5 -0
  8. package/dist/java/type.js.map +1 -1
  9. package/dist/javascript/add-import.d.ts +39 -20
  10. package/dist/javascript/add-import.d.ts.map +1 -1
  11. package/dist/javascript/add-import.js +513 -243
  12. package/dist/javascript/add-import.js.map +1 -1
  13. package/dist/javascript/assertions.d.ts +7 -0
  14. package/dist/javascript/assertions.d.ts.map +1 -1
  15. package/dist/javascript/assertions.js +31 -5
  16. package/dist/javascript/assertions.js.map +1 -1
  17. package/dist/javascript/comparator.d.ts +5 -0
  18. package/dist/javascript/comparator.d.ts.map +1 -1
  19. package/dist/javascript/comparator.js +34 -9
  20. package/dist/javascript/comparator.js.map +1 -1
  21. package/dist/javascript/format/format.d.ts.map +1 -1
  22. package/dist/javascript/format/format.js +8 -9
  23. package/dist/javascript/format/format.js.map +1 -1
  24. package/dist/javascript/format/tabs-and-indents-visitor.d.ts +2 -0
  25. package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
  26. package/dist/javascript/format/tabs-and-indents-visitor.js +17 -11
  27. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  28. package/dist/javascript/node-resolution-result.d.ts +19 -1
  29. package/dist/javascript/node-resolution-result.d.ts.map +1 -1
  30. package/dist/javascript/node-resolution-result.js +37 -2
  31. package/dist/javascript/node-resolution-result.js.map +1 -1
  32. package/dist/javascript/package-exported-types.d.ts.map +1 -1
  33. package/dist/javascript/package-exported-types.js +56 -72
  34. package/dist/javascript/package-exported-types.js.map +1 -1
  35. package/dist/javascript/parser.d.ts.map +1 -1
  36. package/dist/javascript/parser.js +10 -3
  37. package/dist/javascript/parser.js.map +1 -1
  38. package/dist/javascript/recipes/change-import.d.ts.map +1 -1
  39. package/dist/javascript/recipes/change-import.js +4 -8
  40. package/dist/javascript/recipes/change-import.js.map +1 -1
  41. package/dist/javascript/style.d.ts.map +1 -1
  42. package/dist/javascript/style.js +3 -10
  43. package/dist/javascript/style.js.map +1 -1
  44. package/dist/javascript/templating/bindings.d.ts +19 -0
  45. package/dist/javascript/templating/bindings.d.ts.map +1 -0
  46. package/dist/javascript/templating/bindings.js +121 -0
  47. package/dist/javascript/templating/bindings.js.map +1 -0
  48. package/dist/javascript/templating/comparator.d.ts.map +1 -1
  49. package/dist/javascript/templating/comparator.js +5 -6
  50. package/dist/javascript/templating/comparator.js.map +1 -1
  51. package/dist/javascript/templating/engine.d.ts +18 -7
  52. package/dist/javascript/templating/engine.d.ts.map +1 -1
  53. package/dist/javascript/templating/engine.js +70 -42
  54. package/dist/javascript/templating/engine.js.map +1 -1
  55. package/dist/javascript/templating/index.d.ts +1 -1
  56. package/dist/javascript/templating/index.d.ts.map +1 -1
  57. package/dist/javascript/templating/index.js.map +1 -1
  58. package/dist/javascript/templating/pattern.d.ts.map +1 -1
  59. package/dist/javascript/templating/pattern.js +13 -10
  60. package/dist/javascript/templating/pattern.js.map +1 -1
  61. package/dist/javascript/templating/placeholder-replacement.d.ts +2 -0
  62. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
  63. package/dist/javascript/templating/placeholder-replacement.js +14 -5
  64. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  65. package/dist/javascript/templating/rewrite.d.ts.map +1 -1
  66. package/dist/javascript/templating/rewrite.js +14 -18
  67. package/dist/javascript/templating/rewrite.js.map +1 -1
  68. package/dist/javascript/templating/template.d.ts +8 -0
  69. package/dist/javascript/templating/template.d.ts.map +1 -1
  70. package/dist/javascript/templating/template.js +43 -3
  71. package/dist/javascript/templating/template.js.map +1 -1
  72. package/dist/javascript/templating/types.d.ts +47 -1
  73. package/dist/javascript/templating/types.d.ts.map +1 -1
  74. package/dist/javascript/templating/utils.d.ts +5 -0
  75. package/dist/javascript/templating/utils.d.ts.map +1 -1
  76. package/dist/javascript/templating/utils.js +17 -0
  77. package/dist/javascript/templating/utils.js.map +1 -1
  78. package/dist/javascript/type-mapping.d.ts +1 -0
  79. package/dist/javascript/type-mapping.d.ts.map +1 -1
  80. package/dist/javascript/type-mapping.js +52 -2
  81. package/dist/javascript/type-mapping.js.map +1 -1
  82. package/dist/rewrite-javascript-version.txt +1 -1
  83. package/dist/style.d.ts +2 -0
  84. package/dist/style.d.ts.map +1 -1
  85. package/dist/style.js +5 -0
  86. package/dist/style.js.map +1 -1
  87. package/dist/test/rewrite-test.d.ts +12 -0
  88. package/dist/test/rewrite-test.d.ts.map +1 -1
  89. package/dist/test/rewrite-test.js +40 -3
  90. package/dist/test/rewrite-test.js.map +1 -1
  91. package/package.json +1 -1
  92. package/src/java/formatting-utils.ts +14 -10
  93. package/src/java/type.ts +5 -0
  94. package/src/javascript/add-import.ts +590 -230
  95. package/src/javascript/assertions.ts +33 -5
  96. package/src/javascript/comparator.ts +39 -10
  97. package/src/javascript/format/format.ts +9 -10
  98. package/src/javascript/format/tabs-and-indents-visitor.ts +18 -12
  99. package/src/javascript/node-resolution-result.ts +59 -4
  100. package/src/javascript/package-exported-types.ts +60 -74
  101. package/src/javascript/parser.ts +10 -3
  102. package/src/javascript/recipes/change-import.ts +4 -7
  103. package/src/javascript/style.ts +3 -11
  104. package/src/javascript/templating/bindings.ts +129 -0
  105. package/src/javascript/templating/comparator.ts +5 -6
  106. package/src/javascript/templating/engine.ts +82 -44
  107. package/src/javascript/templating/index.ts +2 -0
  108. package/src/javascript/templating/pattern.ts +16 -15
  109. package/src/javascript/templating/placeholder-replacement.ts +16 -5
  110. package/src/javascript/templating/rewrite.ts +16 -18
  111. package/src/javascript/templating/template.ts +45 -3
  112. package/src/javascript/templating/types.ts +53 -1
  113. package/src/javascript/templating/utils.ts +17 -0
  114. package/src/javascript/type-mapping.ts +54 -2
  115. package/src/style.ts +5 -0
  116. package/src/test/rewrite-test.ts +61 -3
@@ -15,97 +15,505 @@ var ImportStyle;
15
15
  ImportStyle[ImportStyle["ES6Default"] = 2] = "ES6Default";
16
16
  ImportStyle[ImportStyle["CommonJS"] = 3] = "CommonJS"; // const x = require('module')
17
17
  })(ImportStyle || (exports.ImportStyle = ImportStyle = {}));
18
- /**
19
- * Register an AddImport visitor to add an import statement to a JavaScript/TypeScript file
20
- * @param visitor The visitor to add the import addition to
21
- * @param options Configuration options for the import to add
22
- *
23
- * @example
24
- * // Add a named import
25
- * maybeAddImport(visitor, { module: 'fs', member: 'readFile' });
26
- *
27
- * @example
28
- * // Add a default import using the 'default' member specifier
29
- * maybeAddImport(visitor, { module: 'react', member: 'default', alias: 'React' });
30
- *
31
- * @example
32
- * // Add a default import (legacy way, without specifying member)
33
- * maybeAddImport(visitor, { module: 'react', alias: 'React' });
34
- *
35
- * @example
36
- * // Add a namespace import
37
- * maybeAddImport(visitor, { module: 'crypto', member: '*', alias: 'crypto' });
38
- *
39
- * @example
40
- * // Add a side-effect import
41
- * maybeAddImport(visitor, { module: 'core-js/stable', sideEffectOnly: true });
42
- */
43
18
  function maybeAddImport(visitor, options) {
44
19
  var _a, _b;
20
+ validate(options);
21
+ const module = moduleNameOf(options.module);
22
+ const sideEffectOnly = (_a = options.sideEffectOnly) !== null && _a !== void 0 ? _a : false;
23
+ const typeOnly = (_b = options.typeOnly) !== null && _b !== void 0 ? _b : false;
24
+ // A queued import binds the module as much as one already in the file, so it answers a later
25
+ // request the same way; a name a merged request never emits would be referenced but not bound.
45
26
  for (const v of visitor.afterVisit || []) {
46
- if (v instanceof AddImport &&
47
- v.module === options.module &&
48
- v.member === options.member &&
49
- v.alias === options.alias &&
50
- v.sideEffectOnly === ((_a = options.sideEffectOnly) !== null && _a !== void 0 ? _a : false) &&
51
- v.typeOnly === ((_b = options.typeOnly) !== null && _b !== void 0 ? _b : false)) {
52
- return;
27
+ if (!(v instanceof AddImport) || v.module !== module ||
28
+ v.sideEffectOnly !== sideEffectOnly || v.typeOnly !== typeOnly) {
29
+ continue;
30
+ }
31
+ // How a specifier prints, or what name would be nice, does not say which binding is wanted.
32
+ // A pinned alias does: it asks for a binding of its own, which only the same request answers.
33
+ const answers = options.alias
34
+ ? v.alias === options.alias && v.member === options.member
35
+ : memberName(v.member) === memberName(options.member);
36
+ if (answers) {
37
+ return v.bindingName;
38
+ }
39
+ }
40
+ if (sideEffectOnly) {
41
+ visitor.afterVisit.push(new AddImport(options));
42
+ return undefined;
43
+ }
44
+ // A pinned alias is the whole answer, so the file has no say and nothing below needs to read it.
45
+ if (options.alias) {
46
+ visitor.afterVisit.push(new AddImport(options, options.alias));
47
+ return options.alias;
48
+ }
49
+ const derived = derivedName(options);
50
+ const cu = compilationUnitOf(visitor);
51
+ if (!cu) {
52
+ visitor.afterVisit.push(new AddImport(options, derived));
53
+ return derived;
54
+ }
55
+ const bindings = bindingsInScope(cu, cursorOf(visitor));
56
+ // An import already serving this request answers it; queuing one would, on the next cycle,
57
+ // derive a suffixed name from the binding this call just added. A caller that named a preference
58
+ // takes whatever comes back; one that did not assumes the name it derived, so a binding under
59
+ // any other name would leave the references it emits unbound.
60
+ for (const binding of bindings) {
61
+ if (binding.module === module && binding.member === memberName(options.member) &&
62
+ binding.typeOnly === typeOnly &&
63
+ (options.preferredName !== undefined || anyNameAnswers(options) ||
64
+ binding.name === derived)) {
65
+ return binding.name;
53
66
  }
54
67
  }
55
- visitor.afterVisit.push(new AddImport(options));
68
+ const name = deconflict(derived, takenNames(bindings, visitor));
69
+ visitor.afterVisit.push(new AddImport(options, name));
70
+ return name;
56
71
  }
57
- class AddImport extends visitor_1.JavaScriptVisitor {
58
- constructor(options) {
59
- var _a, _b, _c;
60
- super();
61
- // Validate that alias is provided when member is 'default'
62
- if (options.member === 'default' && !options.alias) {
63
- throw new Error("When member is 'default', the alias parameter is required");
64
- }
65
- // Validate that alias is provided when member is '*' (namespace import)
66
- if (options.member === '*' && !options.alias) {
67
- throw new Error("When member is '*', the alias parameter is required");
68
- }
69
- // Validate that sideEffectOnly is not combined with incompatible options
70
- if (options.sideEffectOnly) {
71
- if (options.member !== undefined) {
72
- throw new Error("Cannot combine sideEffectOnly with member");
72
+ /** Rejects a request on its own terms, whatever the queue already holds. */
73
+ function validate(options) {
74
+ // Validate that a name is provided when member is 'default'
75
+ if (options.member === 'default' && !options.alias && !options.preferredName) {
76
+ throw new Error("When member is 'default', the alias parameter is required");
77
+ }
78
+ // Validate that a name is provided when member is '*' (namespace import)
79
+ if (options.member === '*' && !options.alias && !options.preferredName) {
80
+ throw new Error("When member is '*', the alias parameter is required");
81
+ }
82
+ // Validate that sideEffectOnly is not combined with incompatible options
83
+ if (options.sideEffectOnly) {
84
+ if (options.member !== undefined) {
85
+ throw new Error("Cannot combine sideEffectOnly with member");
86
+ }
87
+ if (options.alias !== undefined) {
88
+ throw new Error("Cannot combine sideEffectOnly with alias");
89
+ }
90
+ if (options.preferredName !== undefined) {
91
+ throw new Error("Cannot combine sideEffectOnly with preferredName");
92
+ }
93
+ if (options.onlyIfReferenced !== undefined) {
94
+ throw new Error("Cannot combine sideEffectOnly with onlyIfReferenced");
95
+ }
96
+ if (options.typeOnly) {
97
+ throw new Error("Cannot combine sideEffectOnly with typeOnly");
98
+ }
99
+ }
100
+ }
101
+ /**
102
+ * A request that named no local name and asks for no member of the module. Having expressed no
103
+ * preference it has none to disappoint, so whatever the file already calls that module answers it.
104
+ */
105
+ function anyNameAnswers(options) {
106
+ return !options.sideEffectOnly && memberName(options.member) === undefined &&
107
+ options.alias === undefined && options.preferredName === undefined;
108
+ }
109
+ /** The local name a request asks for, before the file has a say in it. */
110
+ function derivedName(options) {
111
+ var _a, _b, _c;
112
+ return (_c = (_b = (_a = options.alias) !== null && _a !== void 0 ? _a : options.preferredName) !== null && _b !== void 0 ? _b : memberName(options.member)) !== null && _c !== void 0 ? _c : moduleNameOf(options.module);
113
+ }
114
+ /** `'default'` and an absent member both name a default import, which binds no member name of its own. */
115
+ function memberName(member) {
116
+ return member === 'default' ? undefined : member;
117
+ }
118
+ function cursorOf(visitor) {
119
+ return visitor.cursor;
120
+ }
121
+ function compilationUnitOf(visitor) {
122
+ var _a;
123
+ // `cursor` is protected on `TreeVisitor`, and the `maybeAddImport`/`maybeRemoveImport`
124
+ // API is free functions, so reaching it takes a cast.
125
+ return (_a = cursorOf(visitor)) === null || _a === void 0 ? void 0 : _a.firstEnclosing((v) => (v === null || v === void 0 ? void 0 : v.kind) === tree_1.JS.Kind.CompilationUnit);
126
+ }
127
+ /** Every name in scope at `cursor`: what the file binds, and what each block enclosing it declares. */
128
+ function bindingsInScope(cu, cursor) {
129
+ const bindings = statementBindings(cu.statements);
130
+ // A local shadows an import for the code the template lands in, so a name a block declares is
131
+ // taken there even though the module never answers for it.
132
+ for (let c = cursor; c && c.value !== cu; c = c.parent) {
133
+ for (const name of scopeNames(c.value)) {
134
+ bindings.push({ name });
135
+ }
136
+ }
137
+ return bindings;
138
+ }
139
+ /** The names a scope introduces directly: a block's declarations, or a function's parameters. */
140
+ function scopeNames(scope) {
141
+ const node = scope;
142
+ if ((node === null || node === void 0 ? void 0 : node.kind) === java_1.J.Kind.Block) {
143
+ return statementBindings(node.statements).map(binding => binding.name);
144
+ }
145
+ if ((node === null || node === void 0 ? void 0 : node.kind) === java_1.J.Kind.MethodDeclaration) {
146
+ return node.parameters.elements
147
+ .flatMap(param => {
148
+ var _a;
149
+ return ((_a = param.element) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.VariableDeclarations
150
+ ? param.element.variables.flatMap(v => { var _a; return patternNames((_a = v.element) === null || _a === void 0 ? void 0 : _a.name); })
151
+ : patternNames(param.element);
152
+ })
153
+ .map(bound => bound.name);
154
+ }
155
+ if ((node === null || node === void 0 ? void 0 : node.kind) === java_1.J.Kind.Lambda) {
156
+ return node.parameters.parameters
157
+ .flatMap(param => {
158
+ var _a;
159
+ return ((_a = param.element) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.VariableDeclarations
160
+ ? param.element.variables.flatMap(v => { var _a; return patternNames((_a = v.element) === null || _a === void 0 ? void 0 : _a.name); })
161
+ : patternNames(param.element);
162
+ })
163
+ .map(bound => bound.name);
164
+ }
165
+ return [];
166
+ }
167
+ /** Imports are top-level statements and so is anything that can shadow one, so a flat scan sees every name. */
168
+ function statementBindings(statements) {
169
+ var _a;
170
+ const bindings = [];
171
+ const declaredBy = (name) => {
172
+ for (const bound of patternNames(name)) {
173
+ bindings.push({ name: bound.name });
174
+ }
175
+ };
176
+ const declaredByVariables = (varDecl) => {
177
+ var _a, _b, _c, _d;
178
+ for (const variable of varDecl.variables) {
179
+ const required = requiredModule((_b = (_a = variable.element) === null || _a === void 0 ? void 0 : _a.initializer) === null || _b === void 0 ? void 0 : _b.element);
180
+ if (required !== undefined) {
181
+ bindings.push(...requireBindings((_c = variable.element) === null || _c === void 0 ? void 0 : _c.name, required));
182
+ }
183
+ else {
184
+ declaredBy((_d = variable.element) === null || _d === void 0 ? void 0 : _d.name);
185
+ }
186
+ }
187
+ };
188
+ for (const stmt of statements) {
189
+ const statement = stmt.element;
190
+ switch (statement === null || statement === void 0 ? void 0 : statement.kind) {
191
+ case tree_1.JS.Kind.Import:
192
+ bindings.push(...importBindings(statement));
193
+ break;
194
+ case java_1.J.Kind.VariableDeclarations:
195
+ declaredByVariables(statement);
196
+ break;
197
+ case tree_1.JS.Kind.ScopedVariableDeclarations:
198
+ for (const variable of statement.variables) {
199
+ if (((_a = variable.element) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.VariableDeclarations) {
200
+ declaredByVariables(variable.element);
201
+ }
202
+ }
203
+ break;
204
+ case java_1.J.Kind.MethodDeclaration:
205
+ declaredBy(statement.name);
206
+ break;
207
+ case java_1.J.Kind.ClassDeclaration:
208
+ declaredBy(statement.name);
209
+ break;
210
+ case tree_1.JS.Kind.NamespaceDeclaration:
211
+ declaredBy(statement.name.element);
212
+ break;
213
+ case tree_1.JS.Kind.TypeDeclaration:
214
+ declaredBy(statement.name.element);
215
+ break;
216
+ }
217
+ }
218
+ return bindings;
219
+ }
220
+ /** The module a `require('...')` initializer names, `undefined` for an initializer that is anything else. */
221
+ function requiredModule(initializer) {
222
+ return (initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation
223
+ ? requiredModuleOf(initializer)
224
+ : undefined;
225
+ }
226
+ /** A `require(...)` call, whatever it is passed. `obj.require('x')` selects a method rather than loading a module. */
227
+ function isRequireCall(methodInv) {
228
+ var _a;
229
+ return !methodInv.select && ((_a = methodInv.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
230
+ methodInv.name.simpleName === 'require';
231
+ }
232
+ /**
233
+ * The module a `require(...)` call loads. `obj.require('x')` selects a method rather than loading a
234
+ * module, and a specifier that is not a string literal names none that can be read here.
235
+ */
236
+ function requiredModuleOf(methodInv) {
237
+ var _a, _b;
238
+ if (!isRequireCall(methodInv)) {
239
+ return undefined;
240
+ }
241
+ const argument = (_b = (_a = methodInv.arguments) === null || _a === void 0 ? void 0 : _a.elements[0]) === null || _b === void 0 ? void 0 : _b.element;
242
+ return (argument === null || argument === void 0 ? void 0 : argument.kind) === java_1.J.Kind.Literal && typeof argument.value === 'string'
243
+ ? moduleNameOf(argument)
244
+ : undefined;
245
+ }
246
+ /**
247
+ * Every name a binding pattern introduces. `member` is the property a name takes its value from,
248
+ * and only a name bound directly by the pattern has one — anything deeper reads a property of a
249
+ * property, so it occupies its name without binding a member of the module.
250
+ */
251
+ function patternNames(pattern) {
252
+ var _a, _b, _c;
253
+ if ((pattern === null || pattern === void 0 ? void 0 : pattern.kind) === java_1.J.Kind.Identifier) {
254
+ return [{ name: pattern.simpleName }];
255
+ }
256
+ // An array pattern binds by position, so its elements name no member of what they destructure.
257
+ if ((pattern === null || pattern === void 0 ? void 0 : pattern.kind) === tree_1.JS.Kind.ArrayBindingPattern) {
258
+ return pattern.elements.elements
259
+ .flatMap(elem => {
260
+ var _a;
261
+ return ((_a = elem.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.BindingElement
262
+ ? patternNames(elem.element.name)
263
+ : patternNames(elem.element);
264
+ })
265
+ .map(bound => ({ name: bound.name }));
266
+ }
267
+ if ((pattern === null || pattern === void 0 ? void 0 : pattern.kind) !== tree_1.JS.Kind.ObjectBindingPattern) {
268
+ return [];
269
+ }
270
+ const names = [];
271
+ for (const elem of pattern.bindings.elements) {
272
+ if (((_a = elem.element) === null || _a === void 0 ? void 0 : _a.kind) !== tree_1.JS.Kind.BindingElement) {
273
+ continue;
274
+ }
275
+ const bindingElem = elem.element;
276
+ if (((_b = bindingElem.name) === null || _b === void 0 ? void 0 : _b.kind) === java_1.J.Kind.Identifier) {
277
+ const name = bindingElem.name.simpleName;
278
+ const propertyName = (_c = bindingElem.propertyName) === null || _c === void 0 ? void 0 : _c.element;
279
+ names.push({
280
+ name,
281
+ member: (propertyName === null || propertyName === void 0 ? void 0 : propertyName.kind) === java_1.J.Kind.Identifier
282
+ ? propertyName.simpleName
283
+ : name
284
+ });
285
+ }
286
+ else {
287
+ names.push(...patternNames(bindingElem.name).map(bound => ({ name: bound.name })));
288
+ }
289
+ }
290
+ return names;
291
+ }
292
+ /** A `require` binds a module the way an import does, so the pool records it the same way. */
293
+ function requireBindings(pattern, module) {
294
+ // A whole-module require binds no member, exactly as a default import does.
295
+ if ((pattern === null || pattern === void 0 ? void 0 : pattern.kind) === java_1.J.Kind.Identifier) {
296
+ return [{ name: pattern.simpleName, module, member: undefined, typeOnly: false }];
297
+ }
298
+ return patternNames(pattern).map(bound => bound.member === undefined
299
+ ? { name: bound.name }
300
+ : { name: bound.name, module, member: bound.member, typeOnly: false });
301
+ }
302
+ /** The member a specifier imports and the name it binds it under, which are the same absent an alias. */
303
+ function specifierBinding(specifier) {
304
+ var _a, _b, _c, _d, _e;
305
+ if (((_a = specifier.specifier) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier) {
306
+ const name = specifier.specifier.simpleName;
307
+ return { name, member: name };
308
+ }
309
+ if (((_b = specifier.specifier) === null || _b === void 0 ? void 0 : _b.kind) !== tree_1.JS.Kind.Alias) {
310
+ return undefined;
311
+ }
312
+ const alias = specifier.specifier;
313
+ return ((_d = (_c = alias.propertyName) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.kind) === java_1.J.Kind.Identifier && ((_e = alias.alias) === null || _e === void 0 ? void 0 : _e.kind) === java_1.J.Kind.Identifier
314
+ ? { name: alias.alias.simpleName, member: alias.propertyName.element.simpleName }
315
+ : undefined;
316
+ }
317
+ function importBindings(jsImport) {
318
+ var _a, _b, _c, _d;
319
+ const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
320
+ const module = (moduleSpecifier === null || moduleSpecifier === void 0 ? void 0 : moduleSpecifier.kind) === java_1.J.Kind.Literal
321
+ ? moduleNameOf(moduleSpecifier)
322
+ : undefined;
323
+ const importClause = jsImport.importClause;
324
+ if (!importClause) {
325
+ return [];
326
+ }
327
+ const typeOnly = importClause.typeOnly;
328
+ const bindings = [];
329
+ if (((_c = (_b = importClause.name) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
330
+ bindings.push({ name: importClause.name.element.simpleName, module, member: undefined, typeOnly });
331
+ }
332
+ const namedBindings = importClause.namedBindings;
333
+ if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === java_1.J.Kind.Identifier) {
334
+ bindings.push({ name: namedBindings.simpleName, module, member: '*', typeOnly });
335
+ }
336
+ else if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.Alias) {
337
+ const alias = namedBindings.alias;
338
+ if ((alias === null || alias === void 0 ? void 0 : alias.kind) === java_1.J.Kind.Identifier) {
339
+ bindings.push({ name: alias.simpleName, module, member: '*', typeOnly });
340
+ }
341
+ }
342
+ else if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.NamedImports) {
343
+ for (const elem of namedBindings.elements.elements) {
344
+ const bound = ((_d = elem.element) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.ImportSpecifier
345
+ ? specifierBinding(elem.element)
346
+ : undefined;
347
+ if (bound) {
348
+ bindings.push(Object.assign(Object.assign({}, bound), { module, typeOnly }));
73
349
  }
74
- if (options.alias !== undefined) {
75
- throw new Error("Cannot combine sideEffectOnly with alias");
350
+ }
351
+ }
352
+ return bindings;
353
+ }
354
+ /**
355
+ * Names the file binds, plus those pending `AddImport`s on the `afterVisit` queue have claimed. A
356
+ * queued `RemoveImport` does not free one: it removes only what the file leaves unused, and binding
357
+ * a name it keeps is an error, where an unnecessary suffix merely reads oddly.
358
+ */
359
+ function takenNames(bindings, visitor) {
360
+ const taken = new Set();
361
+ for (const v of visitor.afterVisit || []) {
362
+ if (v instanceof AddImport && v.bindingName) {
363
+ taken.add(v.bindingName);
364
+ }
365
+ }
366
+ for (const binding of bindings) {
367
+ taken.add(binding.name);
368
+ }
369
+ return taken;
370
+ }
371
+ function deconflict(derived, taken) {
372
+ if (!taken.has(derived)) {
373
+ return derived;
374
+ }
375
+ let suffix = 1;
376
+ while (taken.has(`${derived}_${suffix}`)) {
377
+ suffix++;
378
+ }
379
+ return `${derived}_${suffix}`;
380
+ }
381
+ /**
382
+ * The parser lifts surrogate pairs out of `valueSource` into `unicodeEscapes` and, when it does,
383
+ * sets `value` to the quoted source (`parser.ts` `mapLiteral`), so neither field alone is the
384
+ * module name. Reuniting them and stripping the quotes yields it for either shape of literal.
385
+ */
386
+ function moduleNameOf(module) {
387
+ var _a;
388
+ if (typeof module === 'string') {
389
+ return module;
390
+ }
391
+ const source = module.valueSource;
392
+ if (source === undefined) {
393
+ return String(module.value);
394
+ }
395
+ let restored = '';
396
+ let cut = 0;
397
+ for (const escape of (_a = module.unicodeEscapes) !== null && _a !== void 0 ? _a : []) {
398
+ restored += source.slice(cut, escape.valueSourceIndex) + String.fromCharCode(parseInt(escape.codePoint, 16));
399
+ cut = escape.valueSourceIndex;
400
+ }
401
+ restored += source.slice(cut);
402
+ const quote = restored.charAt(0);
403
+ return (quote === "'" || quote === '"') && restored.endsWith(quote) && restored.length > 1
404
+ ? restored.slice(1, -1)
405
+ : restored;
406
+ }
407
+ function quoteOf(expression) {
408
+ if ((expression === null || expression === void 0 ? void 0 : expression.kind) !== java_1.J.Kind.Literal) {
409
+ return undefined;
410
+ }
411
+ const source = expression.valueSource;
412
+ const quote = source === null || source === void 0 ? void 0 : source.charAt(0);
413
+ // JsxText carries raw text as its `valueSource`, so a leading quote alone does not make a
414
+ // literal quote-delimited; requiring a matching pair keeps prose out of the tally.
415
+ return (quote === "'" || quote === '"') && source.length > 1 && source.endsWith(quote)
416
+ ? quote
417
+ : undefined;
418
+ }
419
+ /**
420
+ * Pick the quote character for a module specifier being added to `cu`, so that it agrees
421
+ * with the file it lands in. An existing specifier is the most direct precedent; a Prettier
422
+ * config states intent even where the file itself has not been formatted to match.
423
+ */
424
+ async function detectQuote(cu) {
425
+ var _a, _b;
426
+ // Static imports are top-level, so the highest-ranked signal needs no traversal to find.
427
+ for (const statement of cu.statements) {
428
+ const element = statement.element;
429
+ const topLevelQuote = (element === null || element === void 0 ? void 0 : element.kind) === tree_1.JS.Kind.Import
430
+ ? quoteOf((_a = element.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element)
431
+ : (element === null || element === void 0 ? void 0 : element.kind) === tree_1.JS.Kind.ExportDeclaration
432
+ ? quoteOf((_b = element.moduleSpecifier) === null || _b === void 0 ? void 0 : _b.element)
433
+ : undefined;
434
+ if (topLevelQuote) {
435
+ return topLevelQuote;
436
+ }
437
+ }
438
+ let importQuote;
439
+ let requireQuote;
440
+ let single = 0;
441
+ let double = 0;
442
+ await new class extends visitor_1.JavaScriptVisitor {
443
+ async visitImportDeclaration(jsImport, p) {
444
+ var _a;
445
+ importQuote !== null && importQuote !== void 0 ? importQuote : (importQuote = quoteOf((_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element));
446
+ return super.visitImportDeclaration(jsImport, p);
447
+ }
448
+ async visitExportDeclaration(exportDeclaration, p) {
449
+ var _a;
450
+ importQuote !== null && importQuote !== void 0 ? importQuote : (importQuote = quoteOf((_a = exportDeclaration.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element));
451
+ return super.visitExportDeclaration(exportDeclaration, p);
452
+ }
453
+ async visitMethodInvocation(method, p) {
454
+ var _a, _b, _c;
455
+ if (!method.select && ((_a = method.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
456
+ method.name.simpleName === 'require') {
457
+ requireQuote !== null && requireQuote !== void 0 ? requireQuote : (requireQuote = quoteOf((_c = (_b = method.arguments) === null || _b === void 0 ? void 0 : _b.elements[0]) === null || _c === void 0 ? void 0 : _c.element));
76
458
  }
77
- if (options.onlyIfReferenced !== undefined) {
78
- throw new Error("Cannot combine sideEffectOnly with onlyIfReferenced");
459
+ return super.visitMethodInvocation(method, p);
460
+ }
461
+ async visitJsxAttribute(attribute, p) {
462
+ // JSX attribute quoting answers to Prettier's `jsxSingleQuote`, so it is no evidence
463
+ // about the quote style of ordinary strings.
464
+ return attribute;
465
+ }
466
+ async visitLiteral(literal, p) {
467
+ const quote = quoteOf(literal);
468
+ if (quote === "'") {
469
+ single++;
79
470
  }
80
- if (options.typeOnly) {
81
- throw new Error("Cannot combine sideEffectOnly with typeOnly");
471
+ else if (quote === '"') {
472
+ double++;
82
473
  }
474
+ return super.visitLiteral(literal, p);
83
475
  }
84
- this.module = options.module;
476
+ }().visit(cu, undefined);
477
+ // Imports outrank requires; that ordering is what makes the import-only scan above sound.
478
+ const specifierQuote = importQuote !== null && importQuote !== void 0 ? importQuote : requireQuote;
479
+ if (specifierQuote) {
480
+ return specifierQuote;
481
+ }
482
+ const prettier = (0, style_1.getStyle)(style_1.StyleKind.PrettierStyle, cu);
483
+ if ((prettier === null || prettier === void 0 ? void 0 : prettier.kind) === style_1.StyleKind.PrettierStyle && !prettier.ignored) {
484
+ const singleQuote = prettier.config.singleQuote;
485
+ if (typeof singleQuote === 'boolean') {
486
+ return singleQuote ? "'" : '"';
487
+ }
488
+ }
489
+ return double > single ? '"' : "'";
490
+ }
491
+ class AddImport extends visitor_1.JavaScriptVisitor {
492
+ constructor(options, bindingName) {
493
+ var _a, _b, _c;
494
+ super();
495
+ validate(options);
496
+ this.module = moduleNameOf(options.module);
497
+ this.moduleValueSource = typeof options.module === 'string' ? undefined : options.module.valueSource;
498
+ this.moduleUnicodeEscapes = typeof options.module === 'string' ? undefined : options.module.unicodeEscapes;
85
499
  this.member = options.member;
86
500
  this.alias = options.alias;
87
501
  this.onlyIfReferenced = (_a = options.onlyIfReferenced) !== null && _a !== void 0 ? _a : true;
88
502
  this.sideEffectOnly = (_b = options.sideEffectOnly) !== null && _b !== void 0 ? _b : false;
89
503
  this.typeOnly = (_c = options.typeOnly) !== null && _c !== void 0 ? _c : false;
90
504
  this.style = options.style;
505
+ this.quoteStyle = options.quoteStyle;
506
+ this.bindingName = this.sideEffectOnly ? undefined : bindingName !== null && bindingName !== void 0 ? bindingName : derivedName(options);
507
+ this.anyNameAnswers = anyNameAnswers(options);
91
508
  }
92
509
  /**
93
510
  * Extract module name from a module specifier literal
94
511
  */
95
512
  getModuleName(moduleSpecifier) {
96
- var _a;
97
513
  if (moduleSpecifier.kind !== java_1.J.Kind.Literal) {
98
514
  return undefined;
99
515
  }
100
- return (_a = moduleSpecifier.value) === null || _a === void 0 ? void 0 : _a.toString();
101
- }
102
- /**
103
- * Check if a method invocation is a require() call
104
- */
105
- isRequireCall(methodInv) {
106
- var _a;
107
- return ((_a = methodInv.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
108
- methodInv.name.simpleName === 'require';
516
+ return moduleNameOf(moduleSpecifier);
109
517
  }
110
518
  /**
111
519
  * Determine the appropriate import style based on file type and existing imports
@@ -177,7 +585,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
177
585
  const namedVar = varDecl.variables[0].element;
178
586
  const initializer = (_a = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
179
587
  if ((initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation &&
180
- this.isRequireCall(initializer)) {
588
+ isRequireCall(initializer)) {
181
589
  hasCommonJSRequires = true;
182
590
  }
183
591
  }
@@ -246,12 +654,8 @@ class AddImport extends visitor_1.JavaScriptVisitor {
246
654
  if (varDecl.variables.length === 1) {
247
655
  const namedVar = varDecl.variables[0].element;
248
656
  const initializer = (_b = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _b === void 0 ? void 0 : _b.element;
249
- if ((initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation &&
250
- this.isRequireCall(initializer)) {
251
- const moduleName = this.getModuleNameFromRequire(initializer);
252
- if (moduleName === this.module) {
253
- return ImportStyle.CommonJS;
254
- }
657
+ if (requiredModule(initializer) === this.module) {
658
+ return ImportStyle.CommonJS;
255
659
  }
256
660
  }
257
661
  }
@@ -382,11 +786,11 @@ class AddImport extends visitor_1.JavaScriptVisitor {
382
786
  const namedImports = importClause.namedBindings;
383
787
  const existingElements = namedImports.elements.elements;
384
788
  // Find the correct insertion position (alphabetical, case-insensitive)
385
- const newName = (this.alias || this.member).toLowerCase();
789
+ const newName = this.bindingName.toLowerCase();
386
790
  let insertIndex = existingElements.findIndex(elem => {
387
- var _a;
791
+ var _a, _b, _c;
388
792
  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);
793
+ const name = (_c = (_b = specifierBinding(elem.element)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : '';
390
794
  return newName.localeCompare(name.toLowerCase()) < 0;
391
795
  }
392
796
  return false;
@@ -511,135 +915,40 @@ class AddImport extends visitor_1.JavaScriptVisitor {
511
915
  * Check if the import matches what we're trying to add
512
916
  */
513
917
  isMatchingImport(jsImport) {
514
- var _a, _b, _c, _d;
515
- // Check module specifier
918
+ var _a;
516
919
  const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
517
- if (!moduleSpecifier) {
518
- return false;
519
- }
520
- const moduleName = this.getModuleName(moduleSpecifier);
521
- if (moduleName !== this.module) {
920
+ if (!moduleSpecifier || this.getModuleName(moduleSpecifier) !== this.module) {
522
921
  return false;
523
922
  }
923
+ // A side-effect import is the clause-less one, and no import carrying bindings stands in
924
+ // for it — nor it for them.
524
925
  const importClause = jsImport.importClause;
525
- // Handle side-effect imports (no import clause)
526
- if (!importClause) {
527
- // If we're trying to add a side-effect import and one already exists, it's a match
528
- return this.sideEffectOnly;
529
- }
530
- // If we're adding a side-effect import but there's an existing import with bindings,
531
- // it's not a match (side-effect import should be separate)
532
- if (this.sideEffectOnly) {
533
- return false;
534
- }
535
- // Check if the typeOnly flag matches - type-only and value imports are separate
536
- if (importClause.typeOnly !== this.typeOnly) {
537
- return false;
538
- }
539
- // Check if the specific member or default import already exists
540
- if (this.member === '*') {
541
- // We're adding a namespace import, check if one exists
542
- const namedBindings = importClause.namedBindings;
543
- if (!namedBindings) {
544
- return false;
545
- }
546
- // Namespace imports can be represented as J.Identifier or JS.Alias
547
- if (namedBindings.kind === java_1.J.Kind.Identifier) {
548
- const identifier = namedBindings;
549
- return identifier.simpleName === this.alias;
550
- }
551
- else if (namedBindings.kind === tree_1.JS.Kind.Alias) {
552
- const alias = namedBindings;
553
- if (((_b = alias.alias) === null || _b === void 0 ? void 0 : _b.kind) === java_1.J.Kind.Identifier) {
554
- return alias.alias.simpleName === this.alias;
555
- }
556
- }
557
- return false;
558
- }
559
- else if (this.member === undefined || this.member === 'default') {
560
- // We're adding a default import, check if one exists
561
- // For member === 'default', also verify the alias matches if specified
562
- if (importClause.name === undefined) {
563
- return false;
564
- }
565
- // If we have an alias, check that it matches
566
- if (this.alias && ((_c = importClause.name.element) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
567
- const existingName = importClause.name.element.simpleName;
568
- return existingName === this.alias;
569
- }
570
- return true;
571
- }
572
- else {
573
- // We're adding a named import, check if it exists
574
- const namedBindings = importClause.namedBindings;
575
- if (!namedBindings) {
576
- return false;
577
- }
578
- if (namedBindings.kind === tree_1.JS.Kind.NamedImports) {
579
- const namedImports = namedBindings;
580
- for (const elem of namedImports.elements.elements) {
581
- if (((_d = elem.element) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.ImportSpecifier) {
582
- const specifier = elem.element;
583
- const importName = this.getImportName(specifier);
584
- const aliasName = this.getImportAlias(specifier);
585
- if (importName === this.member && aliasName === this.alias) {
586
- return true;
587
- }
588
- }
589
- }
590
- }
926
+ if (!importClause || this.sideEffectOnly) {
927
+ return !importClause && this.sideEffectOnly;
591
928
  }
592
- return false;
929
+ return importBindings(jsImport).some(binding => this.answeredBy(binding));
930
+ }
931
+ /** Whether a binding the file already has serves this request. */
932
+ answeredBy(binding) {
933
+ return binding.module === this.module &&
934
+ binding.member === memberName(this.member) &&
935
+ binding.typeOnly === this.typeOnly &&
936
+ (this.anyNameAnswers || binding.name === this.bindingName);
593
937
  }
594
938
  /**
595
939
  * Check if this is a matching CommonJS require statement
596
940
  */
597
941
  isMatchingRequire(varDecl) {
598
- var _a, _b, _c;
942
+ var _a;
599
943
  if (varDecl.variables.length !== 1) {
600
944
  return false;
601
945
  }
602
946
  const namedVar = varDecl.variables[0].element;
603
- if (!namedVar) {
604
- return false;
605
- }
606
- const initializer = (_a = namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
607
- if (!initializer || initializer.kind !== java_1.J.Kind.MethodInvocation) {
608
- return false;
609
- }
610
- const methodInv = initializer;
611
- if (!this.isRequireCall(methodInv)) {
947
+ const module = requiredModule((_a = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element);
948
+ if (module !== this.module) {
612
949
  return false;
613
950
  }
614
- const moduleName = this.getModuleNameFromRequire(methodInv);
615
- if (moduleName !== this.module) {
616
- return false;
617
- }
618
- // Check if the variable name matches what we're trying to add
619
- const pattern = namedVar.name;
620
- if ((this.member === undefined || this.member === 'default') && (pattern === null || pattern === void 0 ? void 0 : pattern.kind) === java_1.J.Kind.Identifier) {
621
- // Default import style: const fs = require('fs')
622
- // For member === 'default', also check the alias matches if specified
623
- if (this.alias) {
624
- const varName = pattern.simpleName;
625
- return varName === this.alias;
626
- }
627
- return true;
628
- }
629
- else if (this.member !== undefined && this.member !== 'default' && (pattern === null || pattern === void 0 ? void 0 : pattern.kind) === tree_1.JS.Kind.ObjectBindingPattern) {
630
- // Destructured import: const { member } = require('module')
631
- const objectPattern = pattern;
632
- for (const elem of objectPattern.bindings.elements) {
633
- if (((_b = elem.element) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.BindingElement) {
634
- const bindingElem = elem.element;
635
- const name = (_c = bindingElem.name) === null || _c === void 0 ? void 0 : _c.simpleName;
636
- if (name === (this.alias || this.member)) {
637
- return true;
638
- }
639
- }
640
- }
641
- }
642
- return false;
951
+ return requireBindings(namedVar.name, module).some(binding => this.answeredBy(binding));
643
952
  }
644
953
  /**
645
954
  * Extract the module name from a class type by traversing the owningClass chain
@@ -754,7 +1063,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
754
1063
  }
755
1064
  }
756
1065
  // Step 2: Look for references that match
757
- const targetName = this.alias || this.member;
1066
+ const targetName = this.bindingName;
758
1067
  const targetModule = this.module;
759
1068
  let found = false;
760
1069
  const self = this;
@@ -872,21 +1181,27 @@ class AddImport extends visitor_1.JavaScriptVisitor {
872
1181
  * Create a new import statement
873
1182
  */
874
1183
  async createImportStatement(compilationUnit, insertionIndex, p) {
1184
+ var _a;
875
1185
  // Determine the appropriate prefix (spacing before the import)
876
1186
  const prefix = this.determineImportPrefix(compilationUnit, insertionIndex);
877
1187
  // Create the module specifier
878
1188
  // For side-effect imports, use emptySpace since space comes from LeftPadded.before
879
1189
  // For regular imports with import clause, use emptySpace since space comes from LeftPadded.before
880
1190
  // 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
1191
+ // Note: value is the unquoted module name; valueSource and unicodeEscapes are its printed form
1192
+ let valueSource = this.moduleValueSource;
1193
+ if (valueSource === undefined) {
1194
+ const quote = (_a = this.quoteStyle) !== null && _a !== void 0 ? _a : await detectQuote(compilationUnit);
1195
+ valueSource = `${quote}${this.module}${quote}`;
1196
+ }
882
1197
  const moduleSpecifier = {
883
1198
  id: (0, uuid_1.randomId)(),
884
1199
  kind: java_1.J.Kind.Literal,
885
1200
  prefix: this.sideEffectOnly ? java_1.emptySpace : java_1.singleSpace,
886
1201
  markers: markers_1.emptyMarkers,
887
1202
  value: this.module,
888
- valueSource: `'${this.module}'`,
889
- unicodeEscapes: [],
1203
+ valueSource,
1204
+ unicodeEscapes: this.moduleUnicodeEscapes,
890
1205
  type: undefined
891
1206
  };
892
1207
  let importClause;
@@ -912,7 +1227,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
912
1227
  prefix: java_1.singleSpace,
913
1228
  markers: markers_1.emptyMarkers,
914
1229
  annotations: [],
915
- simpleName: this.alias,
1230
+ simpleName: this.bindingName,
916
1231
  type: undefined,
917
1232
  fieldType: undefined
918
1233
  };
@@ -943,7 +1258,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
943
1258
  prefix: java_1.singleSpace,
944
1259
  markers: markers_1.emptyMarkers,
945
1260
  annotations: [],
946
- simpleName: this.alias || this.module,
1261
+ simpleName: this.bindingName,
947
1262
  type: undefined,
948
1263
  fieldType: undefined
949
1264
  };
@@ -1010,7 +1325,8 @@ class AddImport extends visitor_1.JavaScriptVisitor {
1010
1325
  */
1011
1326
  createImportSpecifier() {
1012
1327
  let specifier;
1013
- if (this.alias) {
1328
+ // An alias equal to the member says nothing `{member}` alone does not.
1329
+ if (this.bindingName !== this.member) {
1014
1330
  // Aliased import: import { member as alias } from 'module'
1015
1331
  const propertyName = {
1016
1332
  id: (0, uuid_1.randomId)(),
@@ -1028,7 +1344,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
1028
1344
  prefix: java_1.singleSpace,
1029
1345
  markers: markers_1.emptyMarkers,
1030
1346
  annotations: [],
1031
- simpleName: this.alias,
1347
+ simpleName: this.bindingName,
1032
1348
  type: undefined,
1033
1349
  fieldType: undefined
1034
1350
  };
@@ -1113,52 +1429,6 @@ class AddImport extends visitor_1.JavaScriptVisitor {
1113
1429
  // No imports found, insert at the beginning
1114
1430
  return 0;
1115
1431
  }
1116
- /**
1117
- * Get the module name from a require() call
1118
- */
1119
- getModuleNameFromRequire(methodInv) {
1120
- var _a, _b;
1121
- const args = (_a = methodInv.arguments) === null || _a === void 0 ? void 0 : _a.elements;
1122
- if (!args || args.length === 0) {
1123
- return undefined;
1124
- }
1125
- const firstArg = args[0].element;
1126
- if (!firstArg || firstArg.kind !== java_1.J.Kind.Literal || typeof firstArg.value !== 'string') {
1127
- return undefined;
1128
- }
1129
- return (_b = firstArg.value) === null || _b === void 0 ? void 0 : _b.toString();
1130
- }
1131
- /**
1132
- * Get the import name from an import specifier
1133
- */
1134
- getImportName(specifier) {
1135
- const spec = specifier.specifier;
1136
- if ((spec === null || spec === void 0 ? void 0 : spec.kind) === tree_1.JS.Kind.Alias) {
1137
- const alias = spec;
1138
- const propertyName = alias.propertyName.element;
1139
- if ((propertyName === null || propertyName === void 0 ? void 0 : propertyName.kind) === java_1.J.Kind.Identifier) {
1140
- return propertyName.simpleName;
1141
- }
1142
- }
1143
- else if ((spec === null || spec === void 0 ? void 0 : spec.kind) === java_1.J.Kind.Identifier) {
1144
- return spec.simpleName;
1145
- }
1146
- return '';
1147
- }
1148
- /**
1149
- * Get the import alias from an import specifier
1150
- */
1151
- getImportAlias(specifier) {
1152
- var _a;
1153
- const spec = specifier.specifier;
1154
- if ((spec === null || spec === void 0 ? void 0 : spec.kind) === tree_1.JS.Kind.Alias) {
1155
- const alias = spec;
1156
- if (((_a = alias.alias) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier) {
1157
- return alias.alias.simpleName;
1158
- }
1159
- }
1160
- return undefined;
1161
- }
1162
1432
  }
1163
1433
  exports.AddImport = AddImport;
1164
1434
  //# sourceMappingURL=add-import.js.map