@openrewrite/recipes-nodejs 0.52.0-20261009-102010 → 0.52.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 (60) hide show
  1. package/dist/index.d.ts.map +1 -1
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/migrate/code-style.d.ts +14 -0
  5. package/dist/migrate/code-style.d.ts.map +1 -0
  6. package/dist/migrate/code-style.js +70 -0
  7. package/dist/migrate/code-style.js.map +1 -0
  8. package/dist/migrate/hpagent/find-hpagent-manual-migrations.d.ts.map +1 -1
  9. package/dist/migrate/hpagent/find-hpagent-manual-migrations.js +36 -133
  10. package/dist/migrate/hpagent/find-hpagent-manual-migrations.js.map +1 -1
  11. package/dist/migrate/hpagent/hpagent-support.d.ts +36 -15
  12. package/dist/migrate/hpagent/hpagent-support.d.ts.map +1 -1
  13. package/dist/migrate/hpagent/hpagent-support.js +294 -55
  14. package/dist/migrate/hpagent/hpagent-support.js.map +1 -1
  15. package/dist/migrate/hpagent/replace-hpagent.d.ts.map +1 -1
  16. package/dist/migrate/hpagent/replace-hpagent.js +510 -153
  17. package/dist/migrate/hpagent/replace-hpagent.js.map +1 -1
  18. package/dist/migrate/source-map-support/enable-source-maps-at-launch.d.ts.map +1 -1
  19. package/dist/migrate/source-map-support/enable-source-maps-at-launch.js +8 -16
  20. package/dist/migrate/source-map-support/enable-source-maps-at-launch.js.map +1 -1
  21. package/dist/migrate/source-map-support/find-source-map-support-manual-migrations.d.ts.map +1 -1
  22. package/dist/migrate/source-map-support/find-source-map-support-manual-migrations.js +26 -9
  23. package/dist/migrate/source-map-support/find-source-map-support-manual-migrations.js.map +1 -1
  24. package/dist/migrate/source-map-support/migrate-source-map-support-to-native.d.ts.map +1 -1
  25. package/dist/migrate/source-map-support/migrate-source-map-support-to-native.js +7 -4
  26. package/dist/migrate/source-map-support/migrate-source-map-support-to-native.js.map +1 -1
  27. package/dist/migrate/source-map-support/replace-source-map-support-api.d.ts +9 -0
  28. package/dist/migrate/source-map-support/replace-source-map-support-api.d.ts.map +1 -0
  29. package/dist/migrate/source-map-support/replace-source-map-support-api.js +275 -0
  30. package/dist/migrate/source-map-support/replace-source-map-support-api.js.map +1 -0
  31. package/dist/migrate/source-map-support/replace-source-map-support-install.d.ts.map +1 -1
  32. package/dist/migrate/source-map-support/replace-source-map-support-install.js +2 -1
  33. package/dist/migrate/source-map-support/replace-source-map-support-install.js.map +1 -1
  34. package/dist/migrate/source-map-support/source-map-support-api-source.d.ts +14 -0
  35. package/dist/migrate/source-map-support/source-map-support-api-source.d.ts.map +1 -0
  36. package/dist/migrate/source-map-support/source-map-support-api-source.js +426 -0
  37. package/dist/migrate/source-map-support/source-map-support-api-source.js.map +1 -0
  38. package/dist/migrate/source-map-support/source-map-support-rewrites.d.ts.map +1 -1
  39. package/dist/migrate/source-map-support/source-map-support-rewrites.js +2 -0
  40. package/dist/migrate/source-map-support/source-map-support-rewrites.js.map +1 -1
  41. package/dist/migrate/source-map-support/source-map-support-support.d.ts +11 -3
  42. package/dist/migrate/source-map-support/source-map-support-support.d.ts.map +1 -1
  43. package/dist/migrate/source-map-support/source-map-support-support.js +69 -10
  44. package/dist/migrate/source-map-support/source-map-support-support.js.map +1 -1
  45. package/dist/resources/advisories-npm.csv +342 -6
  46. package/package.json +2 -2
  47. package/src/index.ts +2 -0
  48. package/src/migrate/code-style.ts +92 -0
  49. package/src/migrate/fs-extra/replace-fs-extra-native-methods.ts +2 -2
  50. package/src/migrate/hpagent/find-hpagent-manual-migrations.ts +45 -142
  51. package/src/migrate/hpagent/hpagent-support.ts +358 -60
  52. package/src/migrate/hpagent/replace-hpagent.ts +580 -189
  53. package/src/migrate/source-map-support/enable-source-maps-at-launch.ts +17 -26
  54. package/src/migrate/source-map-support/find-source-map-support-manual-migrations.ts +25 -9
  55. package/src/migrate/source-map-support/migrate-source-map-support-to-native.ts +7 -4
  56. package/src/migrate/source-map-support/replace-source-map-support-api.ts +281 -0
  57. package/src/migrate/source-map-support/replace-source-map-support-install.ts +2 -1
  58. package/src/migrate/source-map-support/source-map-support-api-source.ts +470 -0
  59. package/src/migrate/source-map-support/source-map-support-rewrites.ts +3 -0
  60. package/src/migrate/source-map-support/source-map-support-support.ts +79 -10
@@ -19,44 +19,24 @@ exports.ReplaceHpagent = void 0;
19
19
  const rewrite_1 = require("@openrewrite/rewrite");
20
20
  const java_1 = require("@openrewrite/rewrite/java");
21
21
  const javascript_1 = require("@openrewrite/rewrite/javascript");
22
+ const code_style_1 = require("../code-style");
22
23
  const module_bindings_1 = require("../module-bindings");
23
24
  const hpagent_support_1 = require("./hpagent-support");
24
- function requireBoundNames(cu) {
25
- var _a, _b;
26
- const names = new Set();
27
- for (const padded of cu.statements) {
28
- for (const decl of (0, javascript_1.declarationsOf)(padded.element)) {
29
- for (const v of decl.variables) {
30
- const variable = v.element;
31
- if (!hpagent_support_1.HPAGENT_MODULES.has((_b = (0, module_bindings_1.requiredModule)((_a = variable.initializer) === null || _a === void 0 ? void 0 : _a.element)) !== null && _b !== void 0 ? _b : ''))
32
- continue;
33
- for (const name of boundNames(variable.name))
34
- names.add(name);
35
- }
36
- }
37
- }
38
- return names;
39
- }
40
- function boundNames(target) {
41
- if ((0, java_1.isIdentifier)(target))
42
- return [target.simpleName];
43
- if (target.kind !== javascript_1.JS.Kind.ObjectBindingPattern)
44
- return [];
45
- return target.bindings.elements.flatMap(padded => {
46
- const binding = padded.element;
47
- if ((0, java_1.isIdentifier)(binding))
48
- return [binding.simpleName];
49
- if (binding.kind !== javascript_1.JS.Kind.BindingElement)
50
- return [];
51
- const name = binding.name;
52
- return (0, java_1.isIdentifier)(name) ? [name.simpleName] : [];
53
- });
25
+ function boundLocal(binding) {
26
+ if ((0, java_1.isIdentifier)(binding))
27
+ return binding.simpleName;
28
+ if (binding.kind !== javascript_1.JS.Kind.BindingElement)
29
+ return undefined;
30
+ const name = binding.name;
31
+ return (0, java_1.isIdentifier)(name) ? name.simpleName : undefined;
54
32
  }
55
- function renameBindings(target, targetLocals) {
33
+ function renameBindings(target, targetLocals, merged) {
56
34
  if (target.kind !== javascript_1.JS.Kind.ObjectBindingPattern)
57
35
  return target;
58
36
  const pattern = target;
59
- const elements = pattern.bindings.elements.map(padded => {
37
+ const original = pattern.bindings.elements;
38
+ const kept = original.filter(padded => { var _a; return !merged.has((_a = boundLocal(padded.element)) !== null && _a !== void 0 ? _a : ''); });
39
+ const elements = kept.map(padded => {
60
40
  var _a;
61
41
  const binding = padded.element;
62
42
  if ((0, java_1.isIdentifier)(binding)) {
@@ -76,18 +56,71 @@ function renameBindings(target, targetLocals) {
76
56
  if (!(0, java_1.isIdentifier)(name))
77
57
  return padded;
78
58
  const renamed = targetLocals.get(name.simpleName);
79
- return renamed && renamed !== name.simpleName
80
- ? Object.assign(Object.assign({}, padded), { element: Object.assign(Object.assign({}, element), { name: Object.assign(Object.assign({}, name), { simpleName: renamed }) }) }) : padded;
59
+ if (!renamed || renamed === name.simpleName)
60
+ return padded;
61
+ if (renamed === hpagent_support_1.TARGET_CLASS)
62
+ return Object.assign(Object.assign({}, padded), { element: Object.assign(Object.assign({}, element), { name: Object.assign(Object.assign({}, name), { simpleName: renamed }) }) });
63
+ return Object.assign(Object.assign({}, padded), { element: Object.assign(Object.assign({}, element), { propertyName: (0, java_1.rightPadded)(Object.assign(Object.assign({}, name), { id: (0, rewrite_1.randomId)(), simpleName: hpagent_support_1.TARGET_CLASS }), java_1.emptySpace), name: Object.assign(Object.assign({}, name), { prefix: (0, java_1.space)(' '), simpleName: renamed }) }) });
81
64
  });
65
+ if (elements.length > 0 && kept[kept.length - 1] !== original[original.length - 1]) {
66
+ elements[elements.length - 1] = Object.assign(Object.assign({}, elements[elements.length - 1]), { after: original[original.length - 1].after });
67
+ }
82
68
  return Object.assign(Object.assign({}, pattern), { bindings: Object.assign(Object.assign({}, pattern.bindings), { elements }) });
83
69
  }
70
+ function retargeted(literal) {
71
+ var _a;
72
+ const quote = ((_a = literal.valueSource) !== null && _a !== void 0 ? _a : "'").charAt(0);
73
+ return Object.assign(Object.assign({}, literal), { value: hpagent_support_1.TARGET_MODULE, valueSource: `${quote}${hpagent_support_1.TARGET_MODULE}${quote}` });
74
+ }
75
+ function movedRequireCall(e) {
76
+ if (e.kind === javascript_1.JS.Kind.As) {
77
+ const as = e;
78
+ return Object.assign(Object.assign({}, as), { left: Object.assign(Object.assign({}, as.left), { element: movedRequireCall(as.left.element) }), right: movedImportType(as.right) });
79
+ }
80
+ const call = e;
81
+ const specifier = call.arguments.elements[0];
82
+ return Object.assign(Object.assign({}, call), { arguments: Object.assign(Object.assign({}, call.arguments), { elements: [Object.assign(Object.assign({}, specifier), { element: retargeted(specifier.element) })] }) });
83
+ }
84
+ function movedImportType(type) {
85
+ if (type.kind !== javascript_1.JS.Kind.ImportType)
86
+ return type;
87
+ const importType = type;
88
+ const elements = importType.argumentAndAttributes.elements.map(padded => {
89
+ var _a;
90
+ const argument = padded.element;
91
+ if (argument.kind !== javascript_1.JS.Kind.LiteralType)
92
+ return padded;
93
+ const literal = argument.literal;
94
+ return hpagent_support_1.HPAGENT_MODULES.has((_a = (0, hpagent_support_1.stringLiteral)(literal)) !== null && _a !== void 0 ? _a : '')
95
+ ? Object.assign(Object.assign({}, padded), { element: Object.assign(Object.assign({}, argument), { literal: retargeted(literal) }) }) : padded;
96
+ });
97
+ return Object.assign(Object.assign({}, importType), { argumentAndAttributes: Object.assign(Object.assign({}, importType.argumentAndAttributes), { elements }) });
98
+ }
84
99
  function typeKey(type) {
100
+ var _a, _b;
85
101
  if ((0, java_1.isIdentifier)(type))
86
102
  return type.simpleName;
103
+ if (type.kind === java_1.J.Kind.FieldAccess) {
104
+ const access = type;
105
+ return (0, java_1.isIdentifier)(access.target) ? `${access.target.simpleName}.${access.name.element.simpleName}` : undefined;
106
+ }
107
+ if (type.kind === javascript_1.JS.Kind.ImportType) {
108
+ const importType = type;
109
+ const module = (_a = importType.argumentAndAttributes.elements[0]) === null || _a === void 0 ? void 0 : _a.element;
110
+ const name = (_b = importType.qualifier) === null || _b === void 0 ? void 0 : _b.element;
111
+ return (module === null || module === void 0 ? void 0 : module.kind) === javascript_1.JS.Kind.LiteralType && name && (0, java_1.isIdentifier)(name)
112
+ ? `import(${(0, hpagent_support_1.stringLiteral)(module.literal)}).${name.simpleName}`
113
+ : undefined;
114
+ }
87
115
  if (type.kind !== java_1.J.Kind.ParameterizedType)
88
116
  return undefined;
89
117
  const clazz = type.class;
90
- return (0, java_1.isIdentifier)(clazz) ? `${clazz.simpleName}<>` : undefined;
118
+ if ((0, java_1.isIdentifier)(clazz))
119
+ return `${clazz.simpleName}<>`;
120
+ if (clazz.kind !== java_1.J.Kind.FieldAccess)
121
+ return undefined;
122
+ const access = clazz;
123
+ return (0, java_1.isIdentifier)(access.target) ? `${access.target.simpleName}.${access.name.element.simpleName}<>` : undefined;
91
124
  }
92
125
  function alwaysDefined(proxy) {
93
126
  switch (proxy.kind) {
@@ -151,6 +184,54 @@ function paddedMembers(literal) {
151
184
  var _a, _b;
152
185
  return ((_b = (_a = literal.body) === null || _a === void 0 ? void 0 : _a.statements) !== null && _b !== void 0 ? _b : []).filter(padded => padded.element.kind !== java_1.J.Kind.Empty);
153
186
  }
187
+ function builtinSpecifier(cu, module) {
188
+ const prefixed = cu.statements.some(padded => {
189
+ const statement = padded.element;
190
+ const specifier = (statement === null || statement === void 0 ? void 0 : statement.kind) === javascript_1.JS.Kind.Import
191
+ ? (0, module_bindings_1.importModule)(statement)
192
+ : (0, javascript_1.declarationsOf)(statement).map(d => d.variables.map(v => { var _a; return (0, module_bindings_1.requiredModule)((_a = v.element.initializer) === null || _a === void 0 ? void 0 : _a.element); }).find(Boolean)).find(Boolean);
193
+ return specifier === null || specifier === void 0 ? void 0 : specifier.startsWith('node:');
194
+ });
195
+ return prefixed ? `node:${module}` : module;
196
+ }
197
+ function isOptionType(member) {
198
+ return hpagent_support_1.ADAPTED_TYPES.has(member) || member === 'ProxyAgentRequestOptions';
199
+ }
200
+ function isAmbientHpagent(statement) {
201
+ var _a;
202
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) !== javascript_1.JS.Kind.NamespaceDeclaration)
203
+ return false;
204
+ const declaration = statement;
205
+ return declaration.keywordType.element === "Module" &&
206
+ hpagent_support_1.HPAGENT_MODULES.has((_a = (0, hpagent_support_1.stringLiteral)(declaration.name.element)) !== null && _a !== void 0 ? _a : '');
207
+ }
208
+ function constructorOptionsOf(type) {
209
+ var _a;
210
+ const index = type.indexType.element.element;
211
+ if (index.kind !== javascript_1.JS.Kind.LiteralType || index.literal.kind !== java_1.J.Kind.Literal ||
212
+ index.literal.value !== 0) {
213
+ return undefined;
214
+ }
215
+ if (type.objectType.kind !== java_1.J.Kind.ParameterizedType)
216
+ return undefined;
217
+ const parameterized = type.objectType;
218
+ const query = (_a = parameterized.typeParameters) === null || _a === void 0 ? void 0 : _a.elements;
219
+ if (!(0, java_1.isIdentifier)(parameterized.class) || parameterized.class.simpleName !== 'ConstructorParameters' ||
220
+ (query === null || query === void 0 ? void 0 : query.length) !== 1 || query[0].element.kind !== javascript_1.JS.Kind.TypeQuery) {
221
+ return undefined;
222
+ }
223
+ return query[0].element.typeExpression;
224
+ }
225
+ function literalProxy(options) {
226
+ if (!(0, hpagent_support_1.isObjectLiteral)(options))
227
+ return undefined;
228
+ for (const padded of paddedMembers(options)) {
229
+ const option = (0, hpagent_support_1.classifyOption)(padded.element);
230
+ if (option.kind === 'proxy')
231
+ return option.value;
232
+ }
233
+ return undefined;
234
+ }
154
235
  class ReplaceHpagent extends rewrite_1.Recipe {
155
236
  constructor(options) {
156
237
  super(options);
@@ -163,11 +244,19 @@ class ReplaceHpagent extends rewrite_1.Recipe {
163
244
  "`https:` target, so one class serves both. `proxyRequestOptions` members move up into the options object, " +
164
245
  "where `https-proxy-agent` applies them to the connection to the proxy. hpagent accepted a missing proxy until " +
165
246
  "a request needed it, but `https-proxy-agent` reads it in the constructor, so in JavaScript a proxy that may be " +
166
- "missing, such as `process.env.HTTP_PROXY`, guards the construction: `proxy ? new HttpsProxyAgent(proxy) : undefined`. " +
167
- "Calls whose options aren't an object " +
168
- "literal, or that set a TLS option for the destination handshake (`ca`, `rejectUnauthorized`, `cert`, ...), " +
169
- "are left alone: `https-proxy-agent` would apply those to the proxy hop instead. " +
170
- "`FindHpagentManualMigrations` reports every usage left behind.";
247
+ "missing, such as `process.env.HTTP_PROXY`, guards the construction: `proxy ? new HttpsProxyAgent(proxy) : undefined`.\n\n" +
248
+ "A construction that can't take the two-argument form — options that aren't an object literal, a spread " +
249
+ "that can't be checked, or a TLS option for the destination handshake (`ca`, `rejectUnauthorized`, `cert`, " +
250
+ "...), which `https-proxy-agent` would apply to the proxy hop — calls a `createProxyAgent` adapter written " +
251
+ "into the same file instead. It takes hpagent's options object as it was, gives the proxy hop what hpagent " +
252
+ "gave it, and puts every other option on the agent's per-request options, which is where hpagent's " +
253
+ "`https.Agent` kept them for the destination. hpagent's option types become the adapter's own " +
254
+ "`ProxyAgentOptions`, `ConstructorParameters<typeof HttpProxyAgent>[0]` included, and `ProxyAgentRequestOptions` " +
255
+ "a `ProxyRequestOptions` of its own; `instanceof` checks and type references move to the new class. A default " +
256
+ "import becomes a namespace import, since `https-proxy-agent` has no default export; a block's " +
257
+ "`const {...} = require('hpagent')`, and `({...} = require('hpagent'))` into a `let`, move like a top-level one; " +
258
+ "`jest.mock`/`vi.mock` and `spyOn` follow the module in a file whose hpagent bindings all moved; and a " +
259
+ "`declare module 'hpagent'` is deleted. `FindHpagentManualMigrations` reports every usage left behind.";
171
260
  this.tags = ["hpagent", "https-proxy-agent"];
172
261
  }
173
262
  editor() {
@@ -177,62 +266,94 @@ class ReplaceHpagent extends rewrite_1.Recipe {
177
266
  return new class extends javascript_1.JavaScriptVisitor {
178
267
  constructor() {
179
268
  super(...arguments);
269
+ this.found = (0, hpagent_support_1.emptyHpagentBindings)();
180
270
  this.bindings = new Map();
181
271
  this.migrated = new Set();
182
272
  this.stranded = new Set();
183
273
  this.targetLocals = new Map();
184
- this.requireBound = new Set();
185
274
  this.surveying = false;
186
275
  this.merged = new Set();
187
276
  this.folds = [];
188
- this.typeUses = new Set();
277
+ this.adapterLocals = new Set();
278
+ this.referenced = new Set();
279
+ this.builtinLocals = new Map();
280
+ this.producedTypes = new Set();
281
+ this.adapterName = hpagent_support_1.ADAPTER_FUNCTION;
282
+ this.typeName = hpagent_support_1.ADAPTER_TYPE;
283
+ this.requestTypeName = hpagent_support_1.REQUEST_TYPE;
284
+ this.adapterNeeded = false;
285
+ this.typeNeeded = false;
286
+ this.requestTypeNeeded = false;
287
+ this.movedInPlace = new Set();
189
288
  }
190
289
  visitJsCompilationUnit(cu, p) {
191
290
  const _super = Object.create(null, {
192
291
  visitJsCompilationUnit: { get: () => super.visitJsCompilationUnit }
193
292
  });
194
293
  return __awaiter(this, void 0, void 0, function* () {
195
- this.bindings = (0, hpagent_support_1.bindingsOf)(cu, hpagent_support_1.HPAGENT_MODULES);
294
+ if (!this.surveying && cu.statements.some(padded => isAmbientHpagent(padded.element))) {
295
+ cu = Object.assign(Object.assign({}, cu), { statements: cu.statements.filter(padded => !isAmbientHpagent(padded.element)) });
296
+ }
297
+ this.found = (0, hpagent_support_1.hpagentBindings)(cu);
298
+ this.bindings = this.found.bindings;
196
299
  this.migrated = new Set();
197
300
  this.stranded = new Set();
198
301
  this.targetLocals = new Map();
199
302
  this.merged = new Set();
200
303
  this.folds = [];
201
- this.typeUses = new Set();
202
- this.requireBound = requireBoundNames(cu);
304
+ this.adapterLocals = new Set();
305
+ this.referenced = new Set();
306
+ this.producedTypes = new Set();
307
+ this.builtinLocals = new Map();
308
+ this.adapterNeeded = false;
309
+ this.typeNeeded = false;
310
+ this.requestTypeNeeded = false;
311
+ this.movedInPlace = new Set();
203
312
  if (this.bindings.size === 0)
204
313
  return cu;
205
314
  this.planNames(cu);
315
+ for (const module of ['http', 'https']) {
316
+ const whole = [...(0, module_bindings_1.bindingsOf)(cu, new Set([module, `node:${module}`]))].find(([, member]) => member === undefined);
317
+ if (whole)
318
+ this.builtinLocals.set(module, whole[0]);
319
+ }
320
+ const used = (0, javascript_1.namesUsedIn)(cu);
321
+ this.adapterName = (0, javascript_1.deconflict)(hpagent_support_1.ADAPTER_FUNCTION, name => used.has(name));
322
+ this.typeName = (0, javascript_1.deconflict)(hpagent_support_1.ADAPTER_TYPE, name => used.has(name));
323
+ this.requestTypeName = (0, javascript_1.deconflict)(hpagent_support_1.REQUEST_TYPE, name => used.has(name));
206
324
  this.surveying = true;
207
325
  yield _super.visitJsCompilationUnit.call(this, cu, p);
208
326
  this.surveying = false;
209
- for (const local of this.typeUses)
327
+ for (const local of this.targetLocals.keys())
210
328
  this.migrated.add(local);
211
329
  for (const fold of this.folds) {
212
- if (fold.some(local => this.stranded.has(local) || !this.migrated.has(local))) {
330
+ if (fold.some(local => this.referenced.has(local)))
331
+ for (const local of fold)
332
+ this.referenced.add(local);
333
+ if (fold.some(local => this.stranded.has(local))) {
213
334
  for (const local of fold)
214
335
  this.stranded.add(local);
215
336
  }
216
337
  }
217
- if ([...this.migrated].every(local => this.stranded.has(local)))
338
+ const optionTypes = [...this.bindings.values()].some(member => member !== undefined && isOptionType(member));
339
+ if ([...this.migrated].every(local => this.stranded.has(local)) && !optionTypes)
218
340
  return cu;
219
- const result = yield _super.visitJsCompilationUnit.call(this, cu, p);
341
+ let result = yield _super.visitJsCompilationUnit.call(this, cu, p);
342
+ if (this.adapterNeeded || this.typeNeeded || this.requestTypeNeeded)
343
+ result = yield this.withAdapter(result, p);
220
344
  this.rebindMigrated();
221
- return this.rewriteRequires(result);
345
+ return result;
222
346
  });
223
347
  }
224
348
  planNames(cu) {
225
349
  var _a, _b;
226
- const declared = (0, javascript_1.namesDeclaredIn)(cu);
227
- const classes = [...this.bindings].filter(([, member]) => member !== undefined && hpagent_support_1.HPAGENT_CLASSES.has(member));
228
- const foldable = new Set(classes.filter(([local, member]) => local === member).map(([local]) => local));
350
+ const used = (0, javascript_1.namesUsedIn)(cu);
351
+ const movable = [...this.bindings].filter(([, member]) => member === undefined || hpagent_support_1.HPAGENT_CLASSES.has(member));
352
+ const foldable = new Set(movable.filter(([local, member]) => local === member).map(([local]) => local));
353
+ const targetClass = (0, javascript_1.deconflict)(hpagent_support_1.TARGET_CLASS, name => used.has(name) && !foldable.has(name));
229
354
  const targets = new Map();
230
- for (const [local, member] of this.bindings) {
231
- const target = member !== undefined && local === member ? hpagent_support_1.TARGET_CLASS : local;
232
- if (target !== local && declared.has(target) && !foldable.has(target)) {
233
- this.stranded.add(local);
234
- continue;
235
- }
355
+ for (const [local, member] of movable) {
356
+ const target = member !== undefined && local === member && !this.found.assigned.has(local) ? targetClass : local;
236
357
  this.targetLocals.set(local, target);
237
358
  targets.set(target, [...((_a = targets.get(target)) !== null && _a !== void 0 ? _a : []), local]);
238
359
  }
@@ -253,23 +374,72 @@ class ReplaceHpagent extends rewrite_1.Recipe {
253
374
  }
254
375
  rebindMigrated() {
255
376
  for (const local of this.migrated) {
256
- if (this.stranded.has(local) || this.requireBound.has(local))
377
+ if (this.stranded.has(local) || this.found.requireBound.has(local) || this.movedInPlace.has(local))
257
378
  continue;
258
379
  const member = this.bindings.get(local);
259
380
  if (this.merged.has(local)) {
260
381
  (0, javascript_1.maybeUnbind)(this, { module: 'hpagent', member });
261
382
  continue;
262
383
  }
384
+ if (!this.referenced.has(local)) {
385
+ (0, javascript_1.maybeUnbind)(this, member === undefined ? { module: 'hpagent' } : { module: 'hpagent', member });
386
+ continue;
387
+ }
263
388
  if (member === undefined) {
264
389
  (0, javascript_1.maybeRebind)(this, { from: { module: 'hpagent' }, to: { module: hpagent_support_1.TARGET_MODULE } });
265
390
  }
266
391
  else {
392
+ const target = this.targetLocals.get(local);
267
393
  (0, javascript_1.maybeRebind)(this, {
268
394
  from: { module: 'hpagent', member },
269
- to: Object.assign({ module: hpagent_support_1.TARGET_MODULE, member: hpagent_support_1.TARGET_CLASS }, (local === member ? {} : { alias: local }))
395
+ to: Object.assign({ module: hpagent_support_1.TARGET_MODULE, member: hpagent_support_1.TARGET_CLASS }, (target === hpagent_support_1.TARGET_CLASS ? {} : { alias: target }))
270
396
  });
271
397
  }
272
398
  }
399
+ for (const [local, member] of this.bindings) {
400
+ if (member !== undefined && isOptionType(member) && !this.found.requireBound.has(local)) {
401
+ (0, javascript_1.maybeUnbind)(this, { module: 'hpagent', member });
402
+ }
403
+ }
404
+ }
405
+ visitImportDeclaration(jsImport, p) {
406
+ const _super = Object.create(null, {
407
+ visitImportDeclaration: { get: () => super.visitImportDeclaration }
408
+ });
409
+ return __awaiter(this, void 0, void 0, function* () {
410
+ var _a, _b;
411
+ const imp = yield _super.visitImportDeclaration.call(this, jsImport, p);
412
+ const clause = imp === null || imp === void 0 ? void 0 : imp.importClause;
413
+ if (this.surveying || (imp === null || imp === void 0 ? void 0 : imp.kind) !== javascript_1.JS.Kind.Import || !clause || clause.typeOnly ||
414
+ !hpagent_support_1.HPAGENT_MODULES.has((_a = (0, module_bindings_1.importModule)(imp)) !== null && _a !== void 0 ? _a : '')) {
415
+ return imp;
416
+ }
417
+ const named = clause.namedBindings;
418
+ const namespace = (named === null || named === void 0 ? void 0 : named.kind) === javascript_1.JS.Kind.Alias ? named : undefined;
419
+ const defaultName = !named ? (_b = clause.name) === null || _b === void 0 ? void 0 : _b.element : undefined;
420
+ const local = defaultName !== null && defaultName !== void 0 ? defaultName : (!clause.name && namespace && (0, java_1.isIdentifier)(namespace.alias) ? namespace.alias : undefined);
421
+ if (!local || !this.migrated.has(local.simpleName) || this.stranded.has(local.simpleName) ||
422
+ !this.referenced.has(local.simpleName)) {
423
+ return imp;
424
+ }
425
+ this.movedInPlace.add(local.simpleName);
426
+ const moved = Object.assign(Object.assign({}, imp), { moduleSpecifier: Object.assign(Object.assign({}, imp.moduleSpecifier), { element: retargeted(imp.moduleSpecifier.element) }) });
427
+ if (!defaultName)
428
+ return moved;
429
+ const star = { kind: java_1.J.Kind.Identifier, id: (0, rewrite_1.randomId)(), prefix: java_1.emptySpace, markers: rewrite_1.emptyMarkers, annotations: [], simpleName: '*' };
430
+ const alias = {
431
+ kind: javascript_1.JS.Kind.Alias, id: (0, rewrite_1.randomId)(), prefix: defaultName.prefix, markers: rewrite_1.emptyMarkers,
432
+ propertyName: (0, java_1.rightPadded)(star, (0, java_1.space)(' ')), alias: Object.assign(Object.assign({}, defaultName), { prefix: (0, java_1.space)(' ') })
433
+ };
434
+ return Object.assign(Object.assign({}, moved), { importClause: Object.assign(Object.assign({}, clause), { name: undefined, namedBindings: alias }), moduleSpecifier: Object.assign(Object.assign({}, moved.moduleSpecifier), { before: clause.name.after }) });
435
+ });
436
+ }
437
+ isWholeModule(name) {
438
+ return this.bindings.has(name) && this.bindings.get(name) === undefined && (0, hpagent_support_1.resolvesToBinding)(this.cursor, name, this.found);
439
+ }
440
+ isClass(name) {
441
+ const member = this.bindings.get(name);
442
+ return member !== undefined && hpagent_support_1.HPAGENT_CLASSES.has(member) && (0, hpagent_support_1.resolvesToBinding)(this.cursor, name, this.found);
273
443
  }
274
444
  visitNewClass(newClass, p) {
275
445
  const _super = Object.create(null, {
@@ -283,95 +453,276 @@ class ReplaceHpagent extends rewrite_1.Recipe {
283
453
  if (!site)
284
454
  return n;
285
455
  const rewrite = this.rewriteOf(n);
456
+ const adaptable = !rewrite && (0, hpagent_support_1.constructionArgument)(n) !== undefined;
286
457
  if (this.surveying) {
287
- (rewrite ? this.migrated : this.stranded).add(site.local);
458
+ (rewrite || adaptable ? this.migrated : this.stranded).add(site.local);
459
+ if (rewrite || adaptable)
460
+ this.referenced.add(site.local);
461
+ if (adaptable)
462
+ this.adapterLocals.add(site.local);
288
463
  return n;
289
464
  }
290
- if (!rewrite || this.stranded.has(site.local))
465
+ if (this.stranded.has(site.local) || !(rewrite || adaptable))
291
466
  return n;
292
- const migrated = this.applyRewrite(n, site, rewrite);
293
- return isJavaScript((0, javascript_1.compilationUnitOf)(this).sourcePath) && !alwaysDefined(rewrite.proxy) && readsOnly(rewrite.proxy)
294
- ? whenDefined(rewrite.proxy, migrated)
467
+ const migrated = rewrite ? this.applyRewrite(n, site, rewrite) : this.adapterCall(n);
468
+ const proxy = rewrite ? rewrite.proxy : literalProxy((0, hpagent_support_1.constructionArgument)(n));
469
+ return proxy && isJavaScript((0, javascript_1.compilationUnitOf)(this).sourcePath) && !alwaysDefined(proxy) && readsOnly(proxy)
470
+ ? whenDefined(proxy, migrated)
295
471
  : migrated;
296
472
  });
297
473
  }
474
+ adapterCall(n) {
475
+ this.adapterNeeded = true;
476
+ this.typeNeeded = true;
477
+ return {
478
+ kind: java_1.J.Kind.MethodInvocation,
479
+ id: (0, rewrite_1.randomId)(),
480
+ prefix: n.prefix,
481
+ markers: rewrite_1.emptyMarkers,
482
+ name: {
483
+ kind: java_1.J.Kind.Identifier, id: (0, rewrite_1.randomId)(), prefix: java_1.emptySpace, markers: rewrite_1.emptyMarkers,
484
+ annotations: [], simpleName: this.adapterName
485
+ },
486
+ arguments: n.arguments,
487
+ };
488
+ }
489
+ visitInstanceOf(instanceOf, p) {
490
+ const _super = Object.create(null, {
491
+ visitInstanceOf: { get: () => super.visitInstanceOf }
492
+ });
493
+ return __awaiter(this, void 0, void 0, function* () {
494
+ const i = yield _super.visitInstanceOf.call(this, instanceOf, p);
495
+ if ((i === null || i === void 0 ? void 0 : i.kind) !== java_1.J.Kind.InstanceOf)
496
+ return i;
497
+ const site = this.hpagentSite(i.class);
498
+ if (!site)
499
+ return i;
500
+ if (this.surveying) {
501
+ this.referenced.add(site.local);
502
+ return i;
503
+ }
504
+ return this.stranded.has(site.local) ? i : Object.assign(Object.assign({}, i), { class: this.migratedCallee(i.class, site) });
505
+ });
506
+ }
507
+ visitIdentifier(identifier, p) {
508
+ const _super = Object.create(null, {
509
+ visitIdentifier: { get: () => super.visitIdentifier }
510
+ });
511
+ return __awaiter(this, void 0, void 0, function* () {
512
+ const id = yield _super.visitIdentifier.call(this, identifier, p);
513
+ if ((id === null || id === void 0 ? void 0 : id.kind) !== java_1.J.Kind.Identifier || !this.bindings.has(id.simpleName))
514
+ return id;
515
+ if (this.found.assignmentTargets.has(identifier.id))
516
+ return id;
517
+ if (!(0, javascript_1.isReference)(this.cursor, identifier) || !(0, hpagent_support_1.resolvesToBinding)(this.cursor, id.simpleName, this.found))
518
+ return id;
519
+ const member = this.bindings.get(id.simpleName);
520
+ if (member !== undefined && isOptionType(member))
521
+ return this.optionType(id);
522
+ if (member !== undefined && !hpagent_support_1.HPAGENT_CLASSES.has(member))
523
+ return id;
524
+ if (member !== undefined && ((0, hpagent_support_1.inTypePosition)(this.cursor) || this.found.typeOnly.has(id.simpleName))) {
525
+ return this.typeReference(id, id.simpleName);
526
+ }
527
+ if (member === undefined && this.isSpiedModule(id)) {
528
+ if (this.surveying)
529
+ this.referenced.add(id.simpleName);
530
+ return id;
531
+ }
532
+ if (this.surveying && (0, hpagent_support_1.isValueUse)(this.cursor))
533
+ this.stranded.add(id.simpleName);
534
+ return id;
535
+ });
536
+ }
537
+ optionType(type) {
538
+ if (this.surveying)
539
+ return type;
540
+ const request = type.kind === java_1.J.Kind.FieldAccess
541
+ ? type.name.element.simpleName === 'ProxyAgentRequestOptions'
542
+ : this.bindings.get(type.simpleName) === 'ProxyAgentRequestOptions';
543
+ if (request)
544
+ this.requestTypeNeeded = true;
545
+ else
546
+ this.typeNeeded = true;
547
+ return {
548
+ kind: java_1.J.Kind.Identifier, id: (0, rewrite_1.randomId)(), prefix: type.prefix, markers: rewrite_1.emptyMarkers,
549
+ annotations: [], simpleName: request ? this.requestTypeName : this.typeName
550
+ };
551
+ }
552
+ isSpiedModule(id) {
553
+ var _a, _b;
554
+ const parent = (_a = this.cursor.parentTree()) === null || _a === void 0 ? void 0 : _a.value;
555
+ return (parent === null || parent === void 0 ? void 0 : parent.kind) === java_1.J.Kind.MethodInvocation && (0, hpagent_support_1.spiedClass)(parent) !== undefined &&
556
+ ((_b = parent.arguments.elements[0]) === null || _b === void 0 ? void 0 : _b.element) === this.cursor.value;
557
+ }
558
+ visitFieldAccess(fieldAccess, p) {
559
+ const _super = Object.create(null, {
560
+ visitFieldAccess: { get: () => super.visitFieldAccess }
561
+ });
562
+ return __awaiter(this, void 0, void 0, function* () {
563
+ const fa = yield _super.visitFieldAccess.call(this, fieldAccess, p);
564
+ if ((fa === null || fa === void 0 ? void 0 : fa.kind) !== java_1.J.Kind.FieldAccess || !(0, java_1.isIdentifier)(fa.target) || !this.isWholeModule(fa.target.simpleName))
565
+ return fa;
566
+ const local = fa.target.simpleName;
567
+ const name = fa.name.element.simpleName;
568
+ if (isOptionType(name) && (0, hpagent_support_1.inTypePosition)(this.cursor))
569
+ return this.optionType(fa);
570
+ if (!hpagent_support_1.HPAGENT_CLASSES.has(name))
571
+ return fa;
572
+ if ((0, hpagent_support_1.inTypePosition)(this.cursor) || this.found.typeOnly.has(local))
573
+ return this.typeReference(fa, local);
574
+ if (this.surveying && (0, hpagent_support_1.isValueUse)(this.cursor))
575
+ this.stranded.add(local);
576
+ return fa;
577
+ });
578
+ }
579
+ typeReference(type, local) {
580
+ var _a, _b;
581
+ const typeQuery = ((_b = (_a = this.cursor.parentTree()) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.kind) === javascript_1.JS.Kind.TypeQuery;
582
+ if (this.surveying) {
583
+ if (typeQuery)
584
+ this.referenced.add(local);
585
+ return type;
586
+ }
587
+ if (this.stranded.has(local))
588
+ return type;
589
+ const memberAccess = type.kind === java_1.J.Kind.FieldAccess ? type : undefined;
590
+ if (typeQuery)
591
+ return this.migratedCallee(type, { local, memberAccess });
592
+ const member = memberAccess ? memberAccess.name.element.simpleName : this.bindings.get(local);
593
+ const module = (0, hpagent_support_1.builtinAgentModule)(member);
594
+ const agent = (0, hpagent_support_1.builtinAgentType)(this.builtinLocals.get(module), builtinSpecifier((0, javascript_1.compilationUnitOf)(this), module), type.prefix);
595
+ this.producedTypes.add(agent.id);
596
+ return agent;
597
+ }
298
598
  visitUnion(union, p) {
299
599
  const _super = Object.create(null, {
300
600
  visitUnion: { get: () => super.visitUnion }
301
601
  });
302
602
  return __awaiter(this, void 0, void 0, function* () {
303
603
  const u = yield _super.visitUnion.call(this, union, p);
304
- if ((u === null || u === void 0 ? void 0 : u.kind) !== javascript_1.JS.Kind.Union)
604
+ if ((u === null || u === void 0 ? void 0 : u.kind) !== javascript_1.JS.Kind.Union || this.surveying)
305
605
  return u;
306
- let changed = false;
307
606
  const seen = new Set();
308
607
  const types = [];
309
608
  for (const padded of u.types) {
310
- const replacement = this.migratedTypeReference(padded.element);
311
- if (replacement)
312
- changed = true;
313
- const element = replacement !== null && replacement !== void 0 ? replacement : padded.element;
314
- const key = typeKey(element);
315
- if (key !== undefined && seen.has(key)) {
316
- changed = true;
609
+ const key = typeKey(padded.element);
610
+ if (key !== undefined && this.producedTypes.has(padded.element.id) && seen.has(key))
317
611
  continue;
318
- }
319
612
  if (key !== undefined)
320
613
  seen.add(key);
321
- types.push(replacement ? Object.assign(Object.assign({}, padded), { element: replacement }) : padded);
614
+ types.push(padded);
322
615
  }
323
- if (!changed)
616
+ if (types.length === u.types.length)
324
617
  return u;
325
618
  types[types.length - 1] = Object.assign(Object.assign({}, types[types.length - 1]), { after: u.types[u.types.length - 1].after });
326
619
  return Object.assign(Object.assign({}, u), { types });
327
620
  });
328
621
  }
329
- visitTypeInfo(typeInfo, p) {
622
+ visitIndexedAccessType(indexedAccessType, p) {
330
623
  const _super = Object.create(null, {
331
- visitTypeInfo: { get: () => super.visitTypeInfo }
624
+ visitIndexedAccessType: { get: () => super.visitIndexedAccessType }
332
625
  });
333
626
  return __awaiter(this, void 0, void 0, function* () {
334
- const t = yield _super.visitTypeInfo.call(this, typeInfo, p);
335
- if ((t === null || t === void 0 ? void 0 : t.kind) !== javascript_1.JS.Kind.TypeInfo)
336
- return t;
337
- const replacement = this.migratedTypeReference(t.typeIdentifier);
338
- return replacement ? Object.assign(Object.assign({}, t), { typeIdentifier: replacement }) : t;
627
+ const operand = constructorOptionsOf(indexedAccessType);
628
+ const site = operand && this.hpagentSite(operand);
629
+ if (!site || this.surveying || this.stranded.has(site.local))
630
+ return _super.visitIndexedAccessType.call(this, indexedAccessType, p);
631
+ this.typeNeeded = true;
632
+ return {
633
+ kind: java_1.J.Kind.Identifier, id: (0, rewrite_1.randomId)(), prefix: indexedAccessType.prefix, markers: rewrite_1.emptyMarkers,
634
+ annotations: [], simpleName: this.typeName
635
+ };
339
636
  });
340
637
  }
341
- migratedTypeReference(type) {
342
- var _a;
343
- if (!(0, java_1.isIdentifier)(type))
344
- return undefined;
345
- const member = this.bindings.get(type.simpleName);
346
- if (member === undefined || !hpagent_support_1.HPAGENT_CLASSES.has(member) || !(0, hpagent_support_1.isModuleScoped)(this.cursor, type.simpleName)) {
347
- return undefined;
348
- }
349
- if (this.surveying) {
350
- this.typeUses.add(type.simpleName);
351
- return undefined;
352
- }
353
- if (this.stranded.has(type.simpleName))
354
- return undefined;
355
- const local = (_a = this.targetLocals.get(type.simpleName)) !== null && _a !== void 0 ? _a : type.simpleName;
356
- return (0, hpagent_support_1.targetTypeReference)(local, type.prefix);
638
+ visitAssignment(assignment, p) {
639
+ const _super = Object.create(null, {
640
+ visitAssignment: { get: () => super.visitAssignment }
641
+ });
642
+ return __awaiter(this, void 0, void 0, function* () {
643
+ const a = yield _super.visitAssignment.call(this, assignment, p);
644
+ if (this.surveying || (a === null || a === void 0 ? void 0 : a.kind) !== java_1.J.Kind.Assignment || !(0, hpagent_support_1.isHpagentRequire)(a.assignment.element) ||
645
+ !(0, hpagent_support_1.isObjectLiteral)(a.variable)) {
646
+ return a;
647
+ }
648
+ const pattern = a.variable;
649
+ const members = (0, hpagent_support_1.objectMembers)(pattern);
650
+ const locals = members.map(m => { var _a; return ((_a = m.initializer) !== null && _a !== void 0 ? _a : m.name.element); });
651
+ if (!locals.every(l => this.found.assigned.has(l.simpleName) && !this.stranded.has(l.simpleName)))
652
+ return a;
653
+ const statements = pattern.body.statements.map(padded => {
654
+ const prop = padded.element;
655
+ if (prop.kind !== javascript_1.JS.Kind.PropertyAssignment || (0, hpagent_support_1.propertyName)(prop) === hpagent_support_1.TARGET_CLASS)
656
+ return padded;
657
+ const name = prop.name.element;
658
+ const element = prop.initializer
659
+ ? Object.assign(Object.assign({}, prop), { name: Object.assign(Object.assign({}, prop.name), { element: Object.assign(Object.assign({}, name), { simpleName: hpagent_support_1.TARGET_CLASS }) }) }) : Object.assign(Object.assign({}, prop), { name: Object.assign(Object.assign({}, prop.name), { element: Object.assign(Object.assign({}, name), { id: (0, rewrite_1.randomId)(), simpleName: hpagent_support_1.TARGET_CLASS }) }), assigmentToken: "Colon", initializer: Object.assign(Object.assign({}, name), { prefix: (0, java_1.space)(' ') }) });
660
+ return Object.assign(Object.assign({}, padded), { element });
661
+ });
662
+ return Object.assign(Object.assign({}, a), { variable: Object.assign(Object.assign({}, pattern), { body: Object.assign(Object.assign({}, pattern.body), { statements }) }), assignment: Object.assign(Object.assign({}, a.assignment), { element: movedRequireCall(a.assignment.element) }) });
663
+ });
664
+ }
665
+ visitMethodInvocation(method, p) {
666
+ const _super = Object.create(null, {
667
+ visitMethodInvocation: { get: () => super.visitMethodInvocation }
668
+ });
669
+ return __awaiter(this, void 0, void 0, function* () {
670
+ var _a, _b, _c;
671
+ const m = yield _super.visitMethodInvocation.call(this, method, p);
672
+ if (this.surveying || (m === null || m === void 0 ? void 0 : m.kind) !== java_1.J.Kind.MethodInvocation)
673
+ return m;
674
+ const args = m.arguments.elements;
675
+ const first = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.element;
676
+ if ((0, hpagent_support_1.isMockCall)(m) && (first === null || first === void 0 ? void 0 : first.kind) === java_1.J.Kind.Literal && hpagent_support_1.HPAGENT_MODULES.has((_b = (0, hpagent_support_1.stringLiteral)(first)) !== null && _b !== void 0 ? _b : '') &&
677
+ [...this.bindings.keys()].every(local => !this.stranded.has(local))) {
678
+ return Object.assign(Object.assign({}, m), { arguments: Object.assign(Object.assign({}, m.arguments), { elements: [Object.assign(Object.assign({}, args[0]), { element: retargeted(first) }), ...args.slice(1)] }) });
679
+ }
680
+ const spied = (0, hpagent_support_1.spiedClass)(m);
681
+ if (spied && spied !== hpagent_support_1.TARGET_CLASS && first && (0, java_1.isIdentifier)(first) && this.bindings.has(first.simpleName) &&
682
+ this.bindings.get(first.simpleName) === undefined && !this.stranded.has(first.simpleName)) {
683
+ const literal = args[1].element;
684
+ const quote = ((_c = literal.valueSource) !== null && _c !== void 0 ? _c : "'").charAt(0);
685
+ const renamed = Object.assign(Object.assign({}, literal), { value: hpagent_support_1.TARGET_CLASS, valueSource: `${quote}${hpagent_support_1.TARGET_CLASS}${quote}` });
686
+ return Object.assign(Object.assign({}, m), { arguments: Object.assign(Object.assign({}, m.arguments), { elements: [args[0], Object.assign(Object.assign({}, args[1]), { element: renamed }), ...args.slice(2)] }) });
687
+ }
688
+ return m;
689
+ });
690
+ }
691
+ visitVariableDeclarations(varDecls, p) {
692
+ const _super = Object.create(null, {
693
+ visitVariableDeclarations: { get: () => super.visitVariableDeclarations }
694
+ });
695
+ return __awaiter(this, void 0, void 0, function* () {
696
+ const v = yield _super.visitVariableDeclarations.call(this, varDecls, p);
697
+ if (this.surveying || (v === null || v === void 0 ? void 0 : v.kind) !== java_1.J.Kind.VariableDeclarations)
698
+ return v;
699
+ let changed = false;
700
+ const variables = v.variables.map(padded => {
701
+ var _a;
702
+ const variable = padded.element;
703
+ const initializer = (_a = variable.initializer) === null || _a === void 0 ? void 0 : _a.element;
704
+ if (!(0, hpagent_support_1.isHpagentRequire)(initializer))
705
+ return padded;
706
+ const pattern = variable.name;
707
+ const names = (0, java_1.isIdentifier)(pattern) ? [pattern.simpleName] : (0, javascript_1.bindingNames)(pattern).map(b => b.name);
708
+ if (names.length === 0 || names.some(n => !this.migrated.has(n) || this.stranded.has(n)))
709
+ return padded;
710
+ changed = true;
711
+ return Object.assign(Object.assign({}, padded), { element: Object.assign(Object.assign({}, variable), { name: renameBindings(pattern, this.targetLocals, this.merged), initializer: Object.assign(Object.assign({}, variable.initializer), { element: movedRequireCall(initializer) }) }) });
712
+ });
713
+ return changed ? Object.assign(Object.assign({}, v), { variables }) : v;
714
+ });
357
715
  }
358
716
  hpagentSite(clazz) {
359
- if ((0, java_1.isIdentifier)(clazz)) {
360
- const member = this.bindings.get(clazz.simpleName);
361
- return member !== undefined && hpagent_support_1.HPAGENT_CLASSES.has(member) && (0, hpagent_support_1.isModuleScoped)(this.cursor, clazz.simpleName)
362
- ? { local: clazz.simpleName }
363
- : undefined;
364
- }
717
+ if ((0, java_1.isIdentifier)(clazz))
718
+ return this.isClass(clazz.simpleName) ? { local: clazz.simpleName } : undefined;
365
719
  if (clazz.kind !== java_1.J.Kind.FieldAccess)
366
720
  return undefined;
367
721
  const access = clazz;
368
722
  const target = access.target;
369
723
  if (!(0, java_1.isIdentifier)(target) || !hpagent_support_1.HPAGENT_CLASSES.has(access.name.element.simpleName))
370
724
  return undefined;
371
- return this.bindings.has(target.simpleName) && this.bindings.get(target.simpleName) === undefined &&
372
- (0, hpagent_support_1.isModuleScoped)(this.cursor, target.simpleName)
373
- ? { local: target.simpleName, memberAccess: access }
374
- : undefined;
725
+ return this.isWholeModule(target.simpleName) ? { local: target.simpleName, memberAccess: access } : undefined;
375
726
  }
376
727
  rewriteOf(n) {
377
728
  const args = n.arguments.elements.map(a => a.element).filter(a => a.kind !== java_1.J.Kind.Empty);
@@ -418,41 +769,6 @@ class ReplaceHpagent extends rewrite_1.Recipe {
418
769
  return undefined;
419
770
  return { proxy, members, literal };
420
771
  }
421
- rewriteRequires(cu) {
422
- if (this.requireBound.size === 0)
423
- return cu;
424
- let changed = false;
425
- const statements = cu.statements.map(padded => {
426
- const names = requireBoundNames(Object.assign(Object.assign({}, cu), { statements: [padded] }));
427
- if (names.size === 0 || [...names].some(n => !this.migrated.has(n) || this.stranded.has(n)))
428
- return padded;
429
- const moved = this.movedRequire(padded.element);
430
- if (moved === padded.element)
431
- return padded;
432
- changed = true;
433
- return Object.assign(Object.assign({}, padded), { element: moved });
434
- });
435
- return changed ? Object.assign(Object.assign({}, cu), { statements }) : cu;
436
- }
437
- movedRequire(statement) {
438
- const decls = statement;
439
- if ((decls === null || decls === void 0 ? void 0 : decls.kind) !== java_1.J.Kind.VariableDeclarations)
440
- return statement;
441
- const variables = decls.variables.map(padded => {
442
- var _a, _b;
443
- const variable = padded.element;
444
- const initializer = (_a = variable.initializer) === null || _a === void 0 ? void 0 : _a.element;
445
- if ((0, module_bindings_1.requiredModule)(initializer) === undefined)
446
- return padded;
447
- const call = initializer;
448
- const specifier = call.arguments.elements[0];
449
- const literal = specifier.element;
450
- const quote = ((_b = literal.valueSource) !== null && _b !== void 0 ? _b : "'").charAt(0);
451
- const moved = Object.assign(Object.assign({}, literal), { value: hpagent_support_1.TARGET_MODULE, valueSource: `${quote}${hpagent_support_1.TARGET_MODULE}${quote}` });
452
- return Object.assign(Object.assign({}, padded), { element: Object.assign(Object.assign({}, variable), { name: renameBindings(variable.name, this.targetLocals), initializer: Object.assign(Object.assign({}, variable.initializer), { element: Object.assign(Object.assign({}, call), { arguments: Object.assign(Object.assign({}, call.arguments), { elements: [Object.assign(Object.assign({}, specifier), { element: moved })] }) }) }) }) });
453
- });
454
- return Object.assign(Object.assign({}, decls), { variables });
455
- }
456
772
  applyRewrite(n, site, rewrite) {
457
773
  const argument = n.arguments.elements[0];
458
774
  const proxy = Object.assign(Object.assign({}, rewrite.proxy), { prefix: rewrite.literal.prefix });
@@ -466,10 +782,16 @@ class ReplaceHpagent extends rewrite_1.Recipe {
466
782
  }
467
783
  withMembers(rewrite) {
468
784
  const original = paddedMembers(rewrite.literal);
469
- const members = [...rewrite.members];
785
+ const trailing = (padded) => padded.markers.markers.some(m => m.kind === java_1.J.Markers.TrailingComma);
786
+ const members = rewrite.members.map((m, i) => i < rewrite.members.length - 1 && trailing(m)
787
+ ? Object.assign(Object.assign({}, m), { markers: Object.assign(Object.assign({}, m.markers), { markers: m.markers.markers.filter(k => k.kind !== java_1.J.Markers.TrailingComma) }) }) : m);
470
788
  if (members[0] !== original[0]) {
471
789
  members[0] = Object.assign(Object.assign({}, members[0]), { element: Object.assign(Object.assign({}, members[0].element), { prefix: original[0].element.prefix }) });
472
790
  }
791
+ const last = original[original.length - 1];
792
+ if (rewrite.members[rewrite.members.length - 1] !== last) {
793
+ members[members.length - 1] = Object.assign(Object.assign({}, members[members.length - 1]), { after: last.after, markers: last.markers });
794
+ }
473
795
  return Object.assign(Object.assign({}, rewrite.literal), { prefix: (0, java_1.space)(' '), body: Object.assign(Object.assign({}, rewrite.literal.body), { statements: members }) });
474
796
  }
475
797
  migratedCallee(clazz, site) {
@@ -481,6 +803,41 @@ class ReplaceHpagent extends rewrite_1.Recipe {
481
803
  const local = (_a = this.targetLocals.get(site.local)) !== null && _a !== void 0 ? _a : site.local;
482
804
  return Object.assign(Object.assign({}, clazz), { simpleName: local });
483
805
  }
806
+ agentClass() {
807
+ var _a;
808
+ const local = [...this.adapterLocals].find(l => !this.stranded.has(l));
809
+ return this.bindings.get(local) === undefined
810
+ ? `${local}.${hpagent_support_1.TARGET_CLASS}`
811
+ : (_a = this.targetLocals.get(local)) !== null && _a !== void 0 ? _a : local;
812
+ }
813
+ withAdapter(cu, p) {
814
+ return __awaiter(this, void 0, void 0, function* () {
815
+ const typeScript = !isJavaScript(cu.sourcePath);
816
+ const style = (0, code_style_1.detectCodeStyle)(yield rewrite_1.TreePrinters.print(cu));
817
+ const sources = [];
818
+ if (this.adapterNeeded)
819
+ sources.push((0, hpagent_support_1.adapterSource)(this.adapterName, this.typeName, this.agentClass(), typeScript, style));
820
+ if (typeScript) {
821
+ sources.push(...(0, hpagent_support_1.adapterTypeSource)(this.typeNeeded ? this.typeName : undefined, this.requestTypeNeeded ? this.requestTypeName : undefined, module => builtinSpecifier(cu, module), style));
822
+ }
823
+ const prettier = (0, rewrite_1.findMarker)(cu, javascript_1.StyleKind.PrettierStyle) !== undefined;
824
+ let result = cu;
825
+ for (const { doc, code } of sources) {
826
+ const parsed = yield new javascript_1.JavaScriptParser().parseOnly({
827
+ text: `/*${doc}*/\n${code}\n`, sourcePath: typeScript ? 'adapter.ts' : 'adapter.js'
828
+ });
829
+ if (parsed.kind !== javascript_1.JS.Kind.CompilationUnit || parsed.statements.length !== 1)
830
+ continue;
831
+ const statement = parsed.statements[0];
832
+ const parent = new rewrite_1.Cursor(result, this.cursor);
833
+ let declaration = Object.assign(Object.assign({}, statement.element), { prefix: Object.assign(Object.assign({}, parsed.prefix), { whitespace: '\n\n' }) });
834
+ if (prettier)
835
+ declaration = yield (0, javascript_1.autoFormat)(declaration, p, undefined, parent);
836
+ result = Object.assign(Object.assign({}, result), { statements: [...result.statements, Object.assign(Object.assign({}, statement), { element: declaration })] });
837
+ }
838
+ return result;
839
+ });
840
+ }
484
841
  };
485
842
  });
486
843
  }
@@ -489,12 +846,12 @@ exports.ReplaceHpagent = ReplaceHpagent;
489
846
  __decorate([
490
847
  (0, rewrite_1.Option)({
491
848
  displayName: "Migrate spread options",
492
- description: "Also migrate options that spread another object, as in `{...shared, proxy: url}`, passing the " +
493
- "spread through to the new options object. Left off by default: the spread may itself carry a " +
494
- "`proxyRequestOptions`, which has to be flattened, or a TLS option for the destination handshake, which " +
495
- "`https-proxy-agent` would apply to the proxy connection instead. Enable it once the spread objects in " +
496
- "the codebase are known to hold plain agent options. A spread that resolves to a literal of plain " +
497
- "agent options in the same file is migrated either way, since there it can be checked rather than assumed.",
849
+ description: "Rewrite options that spread another object, as in `{...shared, proxy: url}`, to the " +
850
+ "two-argument form, passing the spread through to the new options object, instead of calling the " +
851
+ "adapter. Left off by default: the spread may itself carry a `proxyRequestOptions`, which has to be " +
852
+ "flattened, or a TLS option for the destination handshake, which `https-proxy-agent` would apply to the " +
853
+ "proxy connection instead. A spread that resolves to a literal of plain agent options in the same file " +
854
+ "takes the two-argument form either way, since there it can be checked rather than assumed.",
498
855
  required: false
499
856
  })
500
857
  ], ReplaceHpagent.prototype, "migrateSpreadOptions", void 0);