@openrewrite/rewrite 8.92.16 → 8.92.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/java/formatting-utils.d.ts +2 -1
- package/dist/java/formatting-utils.d.ts.map +1 -1
- package/dist/java/formatting-utils.js +4 -3
- package/dist/java/formatting-utils.js.map +1 -1
- package/dist/java/rpc.d.ts.map +1 -1
- package/dist/java/rpc.js +2 -0
- package/dist/java/rpc.js.map +1 -1
- package/dist/java/tree.d.ts +8 -0
- package/dist/java/tree.d.ts.map +1 -1
- package/dist/java/tree.js +11 -1
- package/dist/java/tree.js.map +1 -1
- package/dist/java/type.d.ts +7 -1
- package/dist/java/type.d.ts.map +1 -1
- package/dist/java/type.js +16 -1
- package/dist/java/type.js.map +1 -1
- package/dist/javascript/add-import.d.ts +27 -21
- package/dist/javascript/add-import.d.ts.map +1 -1
- package/dist/javascript/add-import.js +303 -143
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/amd.d.ts.map +1 -1
- package/dist/javascript/amd.js +25 -10
- package/dist/javascript/amd.js.map +1 -1
- package/dist/javascript/autodetect.js +36 -45
- package/dist/javascript/autodetect.js.map +1 -1
- package/dist/javascript/binding.d.ts +6 -4
- package/dist/javascript/binding.d.ts.map +1 -1
- package/dist/javascript/binding.js +54 -18
- package/dist/javascript/binding.js.map +1 -1
- package/dist/javascript/comparator.d.ts +22 -5
- package/dist/javascript/comparator.d.ts.map +1 -1
- package/dist/javascript/comparator.js +120 -38
- package/dist/javascript/comparator.js.map +1 -1
- package/dist/javascript/format/format.d.ts +2 -0
- package/dist/javascript/format/format.d.ts.map +1 -1
- package/dist/javascript/format/format.js +11 -1
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.js +31 -4
- package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
- package/dist/javascript/index.d.ts +4 -2
- package/dist/javascript/index.d.ts.map +1 -1
- package/dist/javascript/index.js +10 -1
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/markers.d.ts +12 -0
- package/dist/javascript/markers.d.ts.map +1 -1
- package/dist/javascript/markers.js +81 -2
- package/dist/javascript/markers.js.map +1 -1
- package/dist/javascript/method-matcher.d.ts +13 -2
- package/dist/javascript/method-matcher.d.ts.map +1 -1
- package/dist/javascript/method-matcher.js +32 -19
- package/dist/javascript/method-matcher.js.map +1 -1
- package/dist/javascript/node-resolution-result.js +3 -2
- package/dist/javascript/node-resolution-result.js.map +1 -1
- package/dist/javascript/package-name.d.ts +6 -0
- package/dist/javascript/package-name.d.ts.map +1 -0
- package/dist/javascript/package-name.js +47 -0
- package/dist/javascript/package-name.js.map +1 -0
- package/dist/javascript/parser.d.ts +9 -0
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +185 -88
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/preconditions.d.ts +4 -1
- package/dist/javascript/preconditions.d.ts.map +1 -1
- package/dist/javascript/preconditions.js +7 -4
- package/dist/javascript/preconditions.js.map +1 -1
- package/dist/javascript/print.d.ts +10 -1
- package/dist/javascript/print.d.ts.map +1 -1
- package/dist/javascript/print.js +120 -77
- package/dist/javascript/print.js.map +1 -1
- package/dist/javascript/recipes/change-method-target-to-import.d.ts +29 -0
- package/dist/javascript/recipes/change-method-target-to-import.d.ts.map +1 -0
- package/dist/javascript/recipes/change-method-target-to-import.js +164 -0
- package/dist/javascript/recipes/change-method-target-to-import.js.map +1 -0
- package/dist/javascript/recipes/index.d.ts +1 -0
- package/dist/javascript/recipes/index.d.ts.map +1 -1
- package/dist/javascript/recipes/index.js +1 -0
- package/dist/javascript/recipes/index.js.map +1 -1
- package/dist/javascript/scope.d.ts +60 -16
- package/dist/javascript/scope.d.ts.map +1 -1
- package/dist/javascript/scope.js +596 -131
- package/dist/javascript/scope.js.map +1 -1
- package/dist/javascript/search/uses-method.d.ts +1 -1
- package/dist/javascript/search/uses-method.d.ts.map +1 -1
- package/dist/javascript/search/uses-method.js +2 -2
- package/dist/javascript/search/uses-method.js.map +1 -1
- package/dist/javascript/search/uses-type.d.ts +14 -1
- package/dist/javascript/search/uses-type.d.ts.map +1 -1
- package/dist/javascript/search/uses-type.js +24 -9
- package/dist/javascript/search/uses-type.js.map +1 -1
- package/dist/javascript/templating/bindings.d.ts +1 -1
- package/dist/javascript/templating/bindings.d.ts.map +1 -1
- package/dist/javascript/templating/bindings.js +10 -50
- package/dist/javascript/templating/bindings.js.map +1 -1
- package/dist/javascript/templating/comparator.d.ts +8 -11
- package/dist/javascript/templating/comparator.d.ts.map +1 -1
- package/dist/javascript/templating/comparator.js +12 -110
- package/dist/javascript/templating/comparator.js.map +1 -1
- package/dist/javascript/templating/engine.d.ts +34 -24
- package/dist/javascript/templating/engine.d.ts.map +1 -1
- package/dist/javascript/templating/engine.js +208 -115
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/pattern.d.ts +11 -5
- package/dist/javascript/templating/pattern.d.ts.map +1 -1
- package/dist/javascript/templating/pattern.js +86 -20
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.d.ts +34 -3
- package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.js +126 -60
- package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
- package/dist/javascript/templating/precedence.d.ts +3 -1
- package/dist/javascript/templating/precedence.d.ts.map +1 -1
- package/dist/javascript/templating/precedence.js +28 -8
- package/dist/javascript/templating/precedence.js.map +1 -1
- package/dist/javascript/templating/template.d.ts +7 -6
- package/dist/javascript/templating/template.d.ts.map +1 -1
- package/dist/javascript/templating/template.js +31 -28
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/templating/types.d.ts +6 -3
- package/dist/javascript/templating/types.d.ts.map +1 -1
- package/dist/javascript/templating/utils.d.ts +10 -1
- package/dist/javascript/templating/utils.d.ts.map +1 -1
- package/dist/javascript/templating/utils.js +22 -3
- package/dist/javascript/templating/utils.js.map +1 -1
- package/dist/javascript/tree-debug.d.ts +2 -0
- package/dist/javascript/tree-debug.d.ts.map +1 -1
- package/dist/javascript/tree-debug.js +6 -0
- package/dist/javascript/tree-debug.js.map +1 -1
- package/dist/javascript/tsconfig.d.ts.map +1 -1
- package/dist/javascript/tsconfig.js +7 -17
- package/dist/javascript/tsconfig.js.map +1 -1
- package/dist/javascript/type-mapping.d.ts +35 -16
- package/dist/javascript/type-mapping.d.ts.map +1 -1
- package/dist/javascript/type-mapping.js +271 -252
- package/dist/javascript/type-mapping.js.map +1 -1
- package/dist/javascript/type-report-cli.d.ts +7 -0
- package/dist/javascript/type-report-cli.d.ts.map +1 -0
- package/dist/javascript/type-report-cli.js +129 -0
- package/dist/javascript/type-report-cli.js.map +1 -0
- package/dist/javascript/type-report.d.ts +61 -0
- package/dist/javascript/type-report.d.ts.map +1 -0
- package/dist/javascript/type-report.js +488 -0
- package/dist/javascript/type-report.js.map +1 -0
- package/dist/markers.d.ts +4 -0
- package/dist/markers.d.ts.map +1 -1
- package/dist/markers.js +8 -0
- package/dist/markers.js.map +1 -1
- package/dist/print.d.ts +6 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +21 -7
- package/dist/print.js.map +1 -1
- package/dist/recipe.d.ts +5 -0
- package/dist/recipe.d.ts.map +1 -1
- package/dist/recipe.js +5 -0
- package/dist/recipe.js.map +1 -1
- package/dist/rewrite-javascript-version.txt +1 -1
- package/dist/rpc/java-rpc-client.d.ts +2 -0
- package/dist/rpc/java-rpc-client.d.ts.map +1 -1
- package/dist/rpc/java-rpc-client.js +1 -0
- package/dist/rpc/java-rpc-client.js.map +1 -1
- package/dist/rpc/queue.d.ts +24 -0
- package/dist/rpc/queue.d.ts.map +1 -1
- package/dist/rpc/queue.js +71 -11
- package/dist/rpc/queue.js.map +1 -1
- package/dist/rpc/request/get-object.d.ts +4 -0
- package/dist/rpc/request/get-object.d.ts.map +1 -1
- package/dist/rpc/request/get-object.js +23 -1
- package/dist/rpc/request/get-object.js.map +1 -1
- package/dist/rpc/request/parse.d.ts.map +1 -1
- package/dist/rpc/request/parse.js +3 -1
- package/dist/rpc/request/parse.js.map +1 -1
- package/dist/rpc/request/prepare-recipe.d.ts +3 -1
- package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
- package/dist/rpc/request/prepare-recipe.js +13 -6
- package/dist/rpc/request/prepare-recipe.js.map +1 -1
- package/dist/rpc/request/print.d.ts +8 -2
- package/dist/rpc/request/print.d.ts.map +1 -1
- package/dist/rpc/request/print.js +12 -9
- package/dist/rpc/request/print.js.map +1 -1
- package/dist/rpc/rewrite-rpc.d.ts +3 -2
- package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
- package/dist/rpc/rewrite-rpc.js +9 -3
- package/dist/rpc/rewrite-rpc.js.map +1 -1
- package/dist/rpc/server.d.ts.map +1 -1
- package/dist/rpc/server.js +19 -5
- package/dist/rpc/server.js.map +1 -1
- package/dist/search/is-source-file.d.ts +1 -0
- package/dist/search/is-source-file.d.ts.map +1 -1
- package/dist/search/is-source-file.js +7 -2
- package/dist/search/is-source-file.js.map +1 -1
- package/dist/test/java-rpc.d.ts.map +1 -1
- package/dist/test/java-rpc.js +3 -0
- package/dist/test/java-rpc.js.map +1 -1
- package/dist/test/rewrite-test.d.ts +5 -0
- package/dist/test/rewrite-test.d.ts.map +1 -1
- package/dist/test/rewrite-test.js +14 -3
- package/dist/test/rewrite-test.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +3 -1
- package/src/java/formatting-utils.ts +5 -4
- package/src/java/rpc.ts +2 -0
- package/src/java/tree.ts +15 -0
- package/src/java/type.ts +19 -2
- package/src/javascript/add-import.ts +338 -152
- package/src/javascript/amd.ts +28 -12
- package/src/javascript/autodetect.ts +32 -41
- package/src/javascript/binding.ts +64 -22
- package/src/javascript/comparator.ts +129 -43
- package/src/javascript/format/format.ts +9 -0
- package/src/javascript/format/tabs-and-indents-visitor.ts +30 -3
- package/src/javascript/index.ts +6 -3
- package/src/javascript/markers.ts +77 -5
- package/src/javascript/method-matcher.ts +34 -22
- package/src/javascript/node-resolution-result.ts +3 -2
- package/src/javascript/package-name.ts +45 -0
- package/src/javascript/parser.ts +200 -91
- package/src/javascript/preconditions.ts +7 -4
- package/src/javascript/print.ts +123 -76
- package/src/javascript/recipes/change-method-target-to-import.ts +178 -0
- package/src/javascript/recipes/index.ts +1 -0
- package/src/javascript/scope.ts +705 -169
- package/src/javascript/search/uses-method.ts +2 -2
- package/src/javascript/search/uses-type.ts +30 -9
- package/src/javascript/templating/bindings.ts +13 -38
- package/src/javascript/templating/comparator.ts +16 -127
- package/src/javascript/templating/engine.ts +236 -129
- package/src/javascript/templating/pattern.ts +107 -28
- package/src/javascript/templating/placeholder-replacement.ts +154 -62
- package/src/javascript/templating/precedence.ts +33 -11
- package/src/javascript/templating/template.ts +35 -30
- package/src/javascript/templating/types.ts +6 -3
- package/src/javascript/templating/utils.ts +24 -2
- package/src/javascript/tree-debug.ts +9 -0
- package/src/javascript/tsconfig.ts +7 -17
- package/src/javascript/type-mapping.ts +277 -255
- package/src/javascript/type-report-cli.ts +96 -0
- package/src/javascript/type-report.ts +575 -0
- package/src/markers.ts +8 -0
- package/src/print.ts +23 -8
- package/src/recipe.ts +6 -0
- package/src/rpc/java-rpc-client.ts +3 -0
- package/src/rpc/queue.ts +80 -7
- package/src/rpc/request/get-object.ts +24 -0
- package/src/rpc/request/parse.ts +4 -1
- package/src/rpc/request/prepare-recipe.ts +16 -6
- package/src/rpc/request/print.ts +12 -8
- package/src/rpc/rewrite-rpc.ts +16 -5
- package/src/rpc/server.ts +18 -6
- package/src/search/is-source-file.ts +8 -3
- package/src/test/java-rpc.ts +3 -0
- package/src/test/rewrite-test.ts +14 -3
|
@@ -11,16 +11,19 @@ exports.requiredModuleOf = requiredModuleOf;
|
|
|
11
11
|
exports.takenNames = takenNames;
|
|
12
12
|
exports.nameTaken = nameTaken;
|
|
13
13
|
exports.moduleNameOf = moduleNameOf;
|
|
14
|
+
exports.bindingShape = bindingShape;
|
|
14
15
|
exports.existingImportBinding = existingImportBinding;
|
|
15
16
|
const visitor_1 = require("./visitor");
|
|
16
17
|
const java_1 = require("../java");
|
|
17
18
|
const tree_1 = require("./tree");
|
|
18
19
|
const uuid_1 = require("../uuid");
|
|
20
|
+
const type_visitor_1 = require("../java/type-visitor");
|
|
21
|
+
const util_1 = require("../util");
|
|
22
|
+
const package_name_1 = require("./package-name");
|
|
19
23
|
const markers_1 = require("../markers");
|
|
20
24
|
const style_1 = require("./style");
|
|
21
25
|
const scope_1 = require("./scope");
|
|
22
26
|
const mutative_1 = require("mutative");
|
|
23
|
-
const type_visitor_1 = require("../java/type-visitor");
|
|
24
27
|
const format_1 = require("./format");
|
|
25
28
|
const prettier_format_1 = require("./format/prettier-format");
|
|
26
29
|
var ImportStyle;
|
|
@@ -37,7 +40,7 @@ var ImportStyle;
|
|
|
37
40
|
* without affecting whether an existing binding answers the request first.
|
|
38
41
|
*/
|
|
39
42
|
function bindImport(visitor, options, refuseCreate) {
|
|
40
|
-
var _a, _b;
|
|
43
|
+
var _a, _b, _c;
|
|
41
44
|
validate(options);
|
|
42
45
|
const module = moduleNameOf(options.module);
|
|
43
46
|
const sideEffectOnly = (_a = options.sideEffectOnly) !== null && _a !== void 0 ? _a : false;
|
|
@@ -45,8 +48,13 @@ function bindImport(visitor, options, refuseCreate) {
|
|
|
45
48
|
// A queued import binds the module as much as one already in the file, so it answers a later
|
|
46
49
|
// request the same way; a name a merged request never emits would be referenced but not bound.
|
|
47
50
|
for (const v of visitor.afterVisit || []) {
|
|
51
|
+
if (v instanceof RebindImport && !sideEffectOnly && v.to.module === module &&
|
|
52
|
+
memberName(v.to.member) === memberName(options.member) &&
|
|
53
|
+
(options.alias === undefined || options.alias === v.boundName)) {
|
|
54
|
+
return v.boundName;
|
|
55
|
+
}
|
|
48
56
|
if (!(v instanceof AddImport) || v.module !== module ||
|
|
49
|
-
v.sideEffectOnly !== sideEffectOnly || v.typeOnly
|
|
57
|
+
v.sideEffectOnly !== sideEffectOnly || !answersTypeOnly(v.typeOnly, typeOnly)) {
|
|
50
58
|
continue;
|
|
51
59
|
}
|
|
52
60
|
// How a specifier prints, or what name would be nice, does not say which binding is wanted.
|
|
@@ -89,7 +97,11 @@ function bindImport(visitor, options, refuseCreate) {
|
|
|
89
97
|
const scope = (0, scope_1.scopeOf)(cursor);
|
|
90
98
|
for (const binding of moduleScopeBindings(cu)) {
|
|
91
99
|
if (binding.module === module && binding.member === memberName(options.member) &&
|
|
92
|
-
|
|
100
|
+
scope.declaringScope(binding.name) === cu) {
|
|
101
|
+
if (!answersTypeOnly((_c = binding.typeOnly) !== null && _c !== void 0 ? _c : false, typeOnly)) {
|
|
102
|
+
// The queued request finds this binding and drops its `type`, so the name stays
|
|
103
|
+
visitor.afterVisit.push(new AddImport(options, binding.name));
|
|
104
|
+
}
|
|
93
105
|
return binding.name;
|
|
94
106
|
}
|
|
95
107
|
}
|
|
@@ -266,6 +278,54 @@ function requireBindings(pattern, module) {
|
|
|
266
278
|
? { name: bound.name }
|
|
267
279
|
: { name: bound.name, module, member: bound.member, typeOnly: false });
|
|
268
280
|
}
|
|
281
|
+
/** Whether a binding answers a request, given which of the two is type-only. A value import binds the type too. */
|
|
282
|
+
function answersTypeOnly(bindingTypeOnly, requestTypeOnly) {
|
|
283
|
+
return requestTypeOnly || !bindingTypeOnly;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* `jsImport` binding `member` as a value. A `type` on the member's specifier goes, and one on the
|
|
287
|
+
* clause moves onto the clause's other specifiers.
|
|
288
|
+
*/
|
|
289
|
+
function asValueImport(jsImport, member) {
|
|
290
|
+
var _a;
|
|
291
|
+
const clause = jsImport.importClause;
|
|
292
|
+
const named = ((_a = clause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.NamedImports ? clause.namedBindings : undefined;
|
|
293
|
+
const imports = (specifier) => { var _a; return specifier.kind === tree_1.JS.Kind.ImportSpecifier && ((_a = specifierBinding(specifier)) === null || _a === void 0 ? void 0 : _a.member) === member; };
|
|
294
|
+
if (!clause.typeOnly) {
|
|
295
|
+
return !named ? jsImport : (0, mutative_1.create)(jsImport, draft => {
|
|
296
|
+
for (const elem of draft.importClause.namedBindings.elements.elements) {
|
|
297
|
+
const specifier = elem.element;
|
|
298
|
+
if (member !== undefined && imports(elem.element) && specifier.importType.element) {
|
|
299
|
+
specifier.specifier.prefix = specifier.importType.before;
|
|
300
|
+
specifier.importType = Object.assign(Object.assign({}, specifier.importType), { before: java_1.emptySpace, element: false });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return (0, mutative_1.create)(jsImport, draft => {
|
|
306
|
+
const draftClause = draft.importClause;
|
|
307
|
+
draftClause.typeOnly = false;
|
|
308
|
+
// The space after `type` separates nothing once it is gone
|
|
309
|
+
if (draftClause.name) {
|
|
310
|
+
draftClause.name.element.prefix = java_1.emptySpace;
|
|
311
|
+
}
|
|
312
|
+
else if (draftClause.namedBindings) {
|
|
313
|
+
draftClause.namedBindings.prefix = java_1.emptySpace;
|
|
314
|
+
if (named) {
|
|
315
|
+
draftClause.namedBindings.elements.before = java_1.emptySpace;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (named) {
|
|
319
|
+
for (const elem of draftClause.namedBindings.elements.elements) {
|
|
320
|
+
const specifier = elem.element;
|
|
321
|
+
if (!imports(elem.element) && specifier.kind === tree_1.JS.Kind.ImportSpecifier) {
|
|
322
|
+
specifier.importType = Object.assign(Object.assign({}, specifier.importType), { before: java_1.emptySpace, element: true });
|
|
323
|
+
specifier.specifier.prefix = java_1.singleSpace;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
269
329
|
/** The member a specifier imports and the name it binds it under, which are the same absent an alias. */
|
|
270
330
|
function specifierBinding(specifier) {
|
|
271
331
|
var _a, _b, _c, _d, _e;
|
|
@@ -312,30 +372,34 @@ function importBindings(jsImport) {
|
|
|
312
372
|
? specifierBinding(elem.element)
|
|
313
373
|
: undefined;
|
|
314
374
|
if (bound) {
|
|
315
|
-
|
|
375
|
+
const specifier = elem.element;
|
|
376
|
+
bindings.push(Object.assign(Object.assign({}, bound), { module, typeOnly: typeOnly || specifier.importType.element }));
|
|
316
377
|
}
|
|
317
378
|
}
|
|
318
379
|
}
|
|
319
380
|
return bindings;
|
|
320
381
|
}
|
|
321
382
|
/**
|
|
322
|
-
* `names`, plus those pending `AddImport`s on the `afterVisit` queue have
|
|
323
|
-
* `RemoveImport` does not free one: it removes only what the file leaves unused,
|
|
324
|
-
* it keeps is an error, where an unnecessary suffix merely reads oddly.
|
|
383
|
+
* `names`, plus those pending `AddImport`s and `RebindImport`s on the `afterVisit` queue have
|
|
384
|
+
* claimed. A queued `RemoveImport` does not free one: it removes only what the file leaves unused,
|
|
385
|
+
* and binding a name it keeps is an error, where an unnecessary suffix merely reads oddly.
|
|
325
386
|
*/
|
|
326
387
|
function takenNames(names, visitor) {
|
|
327
388
|
const taken = new Set(names);
|
|
328
389
|
for (const v of visitor.afterVisit || []) {
|
|
329
|
-
|
|
330
|
-
|
|
390
|
+
const claimed = claimedName(v);
|
|
391
|
+
if (claimed) {
|
|
392
|
+
taken.add(claimed);
|
|
331
393
|
}
|
|
332
394
|
}
|
|
333
395
|
return taken;
|
|
334
396
|
}
|
|
335
397
|
/** As {@link takenNames}, for a caller asking about one name rather than probing repeatedly. */
|
|
336
398
|
function nameTaken(name, names, visitor) {
|
|
337
|
-
return names.has(name) ||
|
|
338
|
-
|
|
399
|
+
return names.has(name) || (visitor.afterVisit || []).some(v => claimedName(v) === name);
|
|
400
|
+
}
|
|
401
|
+
function claimedName(v) {
|
|
402
|
+
return v instanceof AddImport ? v.bindingName : v instanceof RebindImport ? v.boundName : undefined;
|
|
339
403
|
}
|
|
340
404
|
/**
|
|
341
405
|
* The parser lifts surrogate pairs out of `valueSource` into `unicodeEscapes` and, when it does,
|
|
@@ -733,6 +797,19 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
733
797
|
if (hasImport) {
|
|
734
798
|
return compilationUnit;
|
|
735
799
|
}
|
|
800
|
+
// A type-only binding of the member would leave a value use unbound, and a second binding
|
|
801
|
+
// of the same name would not compile, so the binding the file has loses its `type`
|
|
802
|
+
if (!this.typeOnly && !this.sideEffectOnly) {
|
|
803
|
+
const statements = compilationUnit.statements.map(stmt => {
|
|
804
|
+
const element = stmt.element;
|
|
805
|
+
return (element === null || element === void 0 ? void 0 : element.kind) === tree_1.JS.Kind.Import &&
|
|
806
|
+
importBindings(element).some(b => b.typeOnly && this.bindsSameName(b))
|
|
807
|
+
? Object.assign(Object.assign({}, stmt), { element: asValueImport(element, memberName(this.member)) }) : stmt;
|
|
808
|
+
});
|
|
809
|
+
if (statements.some((stmt, i) => stmt !== compilationUnit.statements[i])) {
|
|
810
|
+
return Object.assign(Object.assign({}, compilationUnit), { statements });
|
|
811
|
+
}
|
|
812
|
+
}
|
|
736
813
|
// If onlyIfReferenced is true, check if the identifier is actually used
|
|
737
814
|
// Skip this check for side-effect imports
|
|
738
815
|
if (!this.sideEffectOnly && this.onlyIfReferenced) {
|
|
@@ -816,35 +893,17 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
816
893
|
* Try to merge the new member into an existing import from the same module
|
|
817
894
|
*/
|
|
818
895
|
async tryMergeIntoExistingImport(compilationUnit, p) {
|
|
819
|
-
var _a;
|
|
820
896
|
for (let i = 0; i < compilationUnit.statements.length; i++) {
|
|
821
897
|
const stmt = compilationUnit.statements[i];
|
|
822
898
|
const statement = stmt.element;
|
|
823
899
|
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
|
|
824
900
|
const jsImport = statement;
|
|
825
|
-
|
|
826
|
-
if (!moduleSpecifier) {
|
|
827
|
-
continue;
|
|
828
|
-
}
|
|
829
|
-
const moduleName = this.getModuleName(moduleSpecifier);
|
|
830
|
-
// Check if this is an import from our target module
|
|
831
|
-
if (moduleName !== this.module) {
|
|
901
|
+
if (!acceptsNamedMember(jsImport, this.module, this.typeOnly)) {
|
|
832
902
|
continue;
|
|
833
903
|
}
|
|
834
904
|
const importClause = jsImport.importClause;
|
|
835
|
-
if (!importClause) {
|
|
836
|
-
continue;
|
|
837
|
-
}
|
|
838
|
-
// Only merge into imports with matching typeOnly - don't mix type and value imports
|
|
839
|
-
if (importClause.typeOnly !== this.typeOnly) {
|
|
840
|
-
continue;
|
|
841
|
-
}
|
|
842
905
|
// Case 1: Existing import has named bindings - merge into them
|
|
843
906
|
if (importClause.namedBindings) {
|
|
844
|
-
// Only merge into NamedImports, not namespace imports
|
|
845
|
-
if (importClause.namedBindings.kind !== tree_1.JS.Kind.NamedImports) {
|
|
846
|
-
continue;
|
|
847
|
-
}
|
|
848
907
|
// We found a matching import with named bindings - merge into it
|
|
849
908
|
return formatMergedImport(await this.produceJavaScript(compilationUnit, p, async (draft) => {
|
|
850
909
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -919,7 +978,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
919
978
|
}
|
|
920
979
|
// Case 2: Default import without named bindings - add named bindings
|
|
921
980
|
// Transform: import React from 'react' -> import React, { useState } from 'react'
|
|
922
|
-
if (importClause.name
|
|
981
|
+
if (importClause.name) {
|
|
923
982
|
return formatMergedImport(await this.produceJavaScript(compilationUnit, p, async (draft) => {
|
|
924
983
|
const newSpecifier = this.createImportSpecifier();
|
|
925
984
|
// Get the spaces style for brace spacing
|
|
@@ -1004,9 +1063,13 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
1004
1063
|
}
|
|
1005
1064
|
/** Whether a binding the file already has serves this request. */
|
|
1006
1065
|
answeredBy(binding) {
|
|
1066
|
+
var _a;
|
|
1067
|
+
return this.bindsSameName(binding) && answersTypeOnly((_a = binding.typeOnly) !== null && _a !== void 0 ? _a : false, this.typeOnly);
|
|
1068
|
+
}
|
|
1069
|
+
/** Whether `binding` binds this request's member under its name, whether or not it is type-only. */
|
|
1070
|
+
bindsSameName(binding) {
|
|
1007
1071
|
return binding.module === this.module &&
|
|
1008
1072
|
binding.member === memberName(this.member) &&
|
|
1009
|
-
binding.typeOnly === this.typeOnly &&
|
|
1010
1073
|
(this.anyNameAnswers || binding.name === this.bindingName);
|
|
1011
1074
|
}
|
|
1012
1075
|
/**
|
|
@@ -1551,6 +1614,13 @@ function namedSpecifierImports(specifier, key) {
|
|
|
1551
1614
|
}
|
|
1552
1615
|
return false;
|
|
1553
1616
|
}
|
|
1617
|
+
/** Whether `imp` binds `member` type-only, by its clause's `type` or the specifier's own. */
|
|
1618
|
+
function bindsTypeOnly(imp, member) {
|
|
1619
|
+
var _a, _b;
|
|
1620
|
+
const key = memberName(member);
|
|
1621
|
+
return ((_b = (_a = imp.importClause) === null || _a === void 0 ? void 0 : _a.typeOnly) !== null && _b !== void 0 ? _b : false) ||
|
|
1622
|
+
(key !== undefined && key !== '*' && namedSpecifierIsTypeOnly(imp, key));
|
|
1623
|
+
}
|
|
1554
1624
|
/** Whether the named specifier binding `key` carries its own inline `type`, as in `{type a, b}`. */
|
|
1555
1625
|
function namedSpecifierIsTypeOnly(imp, key) {
|
|
1556
1626
|
var _a;
|
|
@@ -1586,6 +1656,29 @@ function isOnlyMember(jsImport) {
|
|
|
1586
1656
|
const hasNamespace = ((_a = importClause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Alias;
|
|
1587
1657
|
return (hasDefault ? 1 : 0) + (hasNamespace ? 1 : 0) + namedImportCount(jsImport) === 1;
|
|
1588
1658
|
}
|
|
1659
|
+
function importedModule(jsImport) {
|
|
1660
|
+
var _a;
|
|
1661
|
+
const specifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
1662
|
+
return jsImport.importClause !== undefined && (specifier === null || specifier === void 0 ? void 0 : specifier.kind) === java_1.J.Kind.Literal
|
|
1663
|
+
? moduleNameOf(specifier)
|
|
1664
|
+
: undefined;
|
|
1665
|
+
}
|
|
1666
|
+
/** Whether `AddImport` merges a named member of `module` into `jsImport` rather than adding a statement. */
|
|
1667
|
+
function acceptsNamedMember(jsImport, module, typeOnly) {
|
|
1668
|
+
var _a;
|
|
1669
|
+
const clause = jsImport.importClause;
|
|
1670
|
+
const specifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
1671
|
+
if (!clause || clause.typeOnly !== typeOnly || (specifier === null || specifier === void 0 ? void 0 : specifier.kind) !== java_1.J.Kind.Literal ||
|
|
1672
|
+
moduleNameOf(specifier) !== module) {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
return clause.namedBindings ? clause.namedBindings.kind === tree_1.JS.Kind.NamedImports : clause.name !== undefined;
|
|
1676
|
+
}
|
|
1677
|
+
/** Which of an import clause's three slots `member` binds — `import`, `import *`, or `import {}`. */
|
|
1678
|
+
function bindingShape(member) {
|
|
1679
|
+
const key = memberName(member);
|
|
1680
|
+
return key === undefined ? "default" : key === "*" ? "namespace" : "named";
|
|
1681
|
+
}
|
|
1589
1682
|
/**
|
|
1590
1683
|
* The existing binding for `member` of `module`, read from `cu`'s own import statements — what
|
|
1591
1684
|
* `maybeRebind` reads before committing to a `RebindImport` edit.
|
|
@@ -1601,7 +1694,8 @@ function existingImportBinding(cu, module, member) {
|
|
|
1601
1694
|
return {
|
|
1602
1695
|
localName,
|
|
1603
1696
|
onlyMemberOfStatement: isOnlyMember(element),
|
|
1604
|
-
aliased: localName !== memberName(member)
|
|
1697
|
+
aliased: localName !== memberName(member),
|
|
1698
|
+
typeOnly: bindsTypeOnly(element, member)
|
|
1605
1699
|
};
|
|
1606
1700
|
}
|
|
1607
1701
|
}
|
|
@@ -1696,11 +1790,39 @@ function removeBinding(jsImport, member) {
|
|
|
1696
1790
|
const updatedNamedImports = Object.assign(Object.assign({}, namedImports), { elements: Object.assign(Object.assign({}, namedImports.elements), { elements: kept }) });
|
|
1697
1791
|
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { namedBindings: updatedNamedImports }) });
|
|
1698
1792
|
}
|
|
1793
|
+
/** `cu` without the statement `id`, its prefix carried onto the next one so a file header survives. */
|
|
1794
|
+
function withoutStatement(cu, id) {
|
|
1795
|
+
var _a;
|
|
1796
|
+
const formatter = new java_1.ElementRemovalFormatter(true);
|
|
1797
|
+
const statements = [];
|
|
1798
|
+
for (const stmt of cu.statements) {
|
|
1799
|
+
if (((_a = stmt.element) === null || _a === void 0 ? void 0 : _a.id) === id) {
|
|
1800
|
+
formatter.markRemoved(stmt.element);
|
|
1801
|
+
}
|
|
1802
|
+
else {
|
|
1803
|
+
const kept = stmt.element && formatter.processKept(stmt.element);
|
|
1804
|
+
statements.push(kept === stmt.element ? stmt : Object.assign(Object.assign({}, stmt), { element: kept }));
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
return Object.assign(Object.assign({}, cu), { statements });
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Whether moving the only binding of `jsImport` to `to` replaces the statement rather than rewriting
|
|
1811
|
+
* it in place. A different shape needs a different clause, and another import of `to` takes it in.
|
|
1812
|
+
*/
|
|
1813
|
+
function replacesStatement(cu, jsImport, from, to, typeOnly) {
|
|
1814
|
+
const shape = bindingShape(to.member);
|
|
1815
|
+
return shape !== bindingShape(from.member) || (shape === "named" && cu.statements.some(s => {
|
|
1816
|
+
var _a;
|
|
1817
|
+
return s.element !== jsImport && ((_a = s.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Import &&
|
|
1818
|
+
acceptsNamedMember(s.element, to.module, typeOnly);
|
|
1819
|
+
}));
|
|
1820
|
+
}
|
|
1821
|
+
const esmStyle = { default: ImportStyle.ES6Default, namespace: ImportStyle.ES6Namespace, named: ImportStyle.ES6Named };
|
|
1699
1822
|
/**
|
|
1700
|
-
* Moves the binding `from` names to `to`, binding it under `boundName
|
|
1701
|
-
*
|
|
1702
|
-
*
|
|
1703
|
-
* A `boundName` of its own renames the binding, and the file's references to it follow.
|
|
1823
|
+
* Moves the binding `from` names to `to`, binding it under `boundName`, and the file's references
|
|
1824
|
+
* follow a `boundName` of its own. Whether the statement is rewritten in place or replaced is decided
|
|
1825
|
+
* when this visitor runs, because a sibling rebind may empty the statement first.
|
|
1704
1826
|
*
|
|
1705
1827
|
* Not built on `RemoveImport`/`maybeUnbind`: those only drop a binding once nothing references
|
|
1706
1828
|
* it, but a rebind moves one that is still in use — removal here has to be unconditional.
|
|
@@ -1714,42 +1836,66 @@ class RebindImport extends visitor_1.JavaScriptVisitor {
|
|
|
1714
1836
|
this.boundName = boundName;
|
|
1715
1837
|
this.transformedInPlace = false;
|
|
1716
1838
|
this.typeOnly = false;
|
|
1717
|
-
this.movedTypes = new MovedTypes(this.from, this.to);
|
|
1718
|
-
/** Identifiers settled as references to the binding, so a parent need not settle it again. */
|
|
1719
|
-
this.references = new Set();
|
|
1720
1839
|
}
|
|
1721
1840
|
get renaming() {
|
|
1722
1841
|
return this.boundName !== this.localName;
|
|
1723
1842
|
}
|
|
1724
1843
|
async visitJsCompilationUnit(cu, p) {
|
|
1725
|
-
|
|
1844
|
+
this.cu = cu;
|
|
1845
|
+
const imports = cu.statements
|
|
1846
|
+
.filter(s => { var _a; return ((_a = s.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Import; })
|
|
1847
|
+
.map(s => s.element);
|
|
1848
|
+
const ofModule = imports.filter(imp => importedModule(imp) === this.from.module);
|
|
1849
|
+
const fromPackage = packageOf(this.from.module);
|
|
1850
|
+
const member = declaredMember(this.from);
|
|
1851
|
+
this.movedTypes = new MovedTypes(this.from, this.to, {
|
|
1852
|
+
module: ofModule.length > 1 || ofModule.some(imp => !isOnlyMember(imp)),
|
|
1853
|
+
// Same-named classes from two subpaths of one package share a name.
|
|
1854
|
+
className: member !== undefined && imports.filter(imp => {
|
|
1855
|
+
const module = importedModule(imp);
|
|
1856
|
+
return module !== undefined && packageOf(module) === fromPackage &&
|
|
1857
|
+
importBinds(imp, module, member) !== undefined;
|
|
1858
|
+
}).length > 1
|
|
1859
|
+
});
|
|
1860
|
+
let visited = await super.visitJsCompilationUnit(cu, p);
|
|
1861
|
+
if (this.dropped !== undefined) {
|
|
1862
|
+
visited = withoutStatement(visited, this.dropped);
|
|
1863
|
+
}
|
|
1726
1864
|
if (!this.transformedInPlace) {
|
|
1727
1865
|
bindImport(this, {
|
|
1728
1866
|
module: this.to.module,
|
|
1729
1867
|
member: this.to.member,
|
|
1730
1868
|
alias: this.boundName,
|
|
1731
1869
|
typeOnly: this.typeOnly,
|
|
1732
|
-
onlyIfReferenced: false
|
|
1870
|
+
onlyIfReferenced: false,
|
|
1871
|
+
quoteStyle: this.droppedQuote,
|
|
1872
|
+
// The binding was an ES import, though the file may no longer read as a module without it.
|
|
1873
|
+
style: esmStyle[bindingShape(this.to.member)]
|
|
1733
1874
|
});
|
|
1734
1875
|
}
|
|
1735
1876
|
return visited;
|
|
1736
1877
|
}
|
|
1737
1878
|
async visitImportDeclaration(jsImport, p) {
|
|
1738
|
-
var _a
|
|
1879
|
+
var _a;
|
|
1739
1880
|
const imp = await super.visitImportDeclaration(jsImport, p);
|
|
1740
1881
|
const key = memberName(this.from.member);
|
|
1741
|
-
// One call moves one binding, and no two
|
|
1742
|
-
// read from the matched statement is what picks it back out of the file.
|
|
1743
|
-
|
|
1882
|
+
// One call moves one module-scope binding, and no two of those share a local name, so the
|
|
1883
|
+
// name read from the matched statement is what picks it back out of the file.
|
|
1884
|
+
const cu = this.cu;
|
|
1885
|
+
if (!(cu === null || cu === void 0 ? void 0 : cu.statements.some(s => s.element === jsImport)) ||
|
|
1886
|
+
importBinds(imp, this.from.module, this.from.member) !== this.localName) {
|
|
1744
1887
|
return imp;
|
|
1745
1888
|
}
|
|
1746
|
-
//
|
|
1747
|
-
|
|
1748
|
-
this.typeOnly = ((_b = (_a = imp.importClause) === null || _a === void 0 ? void 0 : _a.typeOnly) !== null && _b !== void 0 ? _b : false) ||
|
|
1749
|
-
(key !== undefined && key !== '*' && namedSpecifierIsTypeOnly(imp, key));
|
|
1889
|
+
// The replacement takes the moved binding's `type` marking to stay type-safe.
|
|
1890
|
+
this.typeOnly = bindsTypeOnly(imp, this.from.member);
|
|
1750
1891
|
if (!isOnlyMember(imp)) {
|
|
1751
1892
|
return removeBinding(imp, this.from.member);
|
|
1752
1893
|
}
|
|
1894
|
+
if (replacesStatement(cu, jsImport, this.from, this.to, this.typeOnly)) {
|
|
1895
|
+
this.dropped = imp.id;
|
|
1896
|
+
this.droppedQuote = quoteOf((_a = imp.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element);
|
|
1897
|
+
return imp;
|
|
1898
|
+
}
|
|
1753
1899
|
this.transformedInPlace = true;
|
|
1754
1900
|
return (0, mutative_1.create)(imp, draft => {
|
|
1755
1901
|
var _a;
|
|
@@ -1771,53 +1917,13 @@ class RebindImport extends visitor_1.JavaScriptVisitor {
|
|
|
1771
1917
|
});
|
|
1772
1918
|
}
|
|
1773
1919
|
async visitIdentifier(identifier, p) {
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
}
|
|
1777
|
-
this.references.add(identifier.id);
|
|
1778
|
-
// The name follows the binding, and so does what the name is attributed to; an aliased
|
|
1779
|
-
// binding keeps its name and still resolves somewhere new.
|
|
1780
|
-
const type = await this.movedTypes.visit(identifier.type, undefined);
|
|
1781
|
-
const fieldType = await this.movedTypes.visit(identifier.fieldType, undefined);
|
|
1782
|
-
return !this.renaming && type === identifier.type && fieldType === identifier.fieldType
|
|
1783
|
-
? identifier
|
|
1784
|
-
: Object.assign(Object.assign({}, identifier), { simpleName: this.boundName, type, fieldType });
|
|
1785
|
-
}
|
|
1786
|
-
async visitMethodInvocation(method, p) {
|
|
1787
|
-
const m = await super.visitMethodInvocation(method, p);
|
|
1788
|
-
if (!this.referencesMovedBinding(m.name)) {
|
|
1789
|
-
return m;
|
|
1790
|
-
}
|
|
1791
|
-
const methodType = await this.movedTypes.visit(m.methodType, undefined);
|
|
1792
|
-
return methodType === m.methodType ? m : Object.assign(Object.assign({}, m), { methodType });
|
|
1793
|
-
}
|
|
1794
|
-
async visitNewClass(newClass, p) {
|
|
1795
|
-
const nc = await super.visitNewClass(newClass, p);
|
|
1796
|
-
if (!this.referencesMovedBinding(nc.class)) {
|
|
1797
|
-
return nc;
|
|
1798
|
-
}
|
|
1799
|
-
const type = await this.movedTypes.visit(nc.type, undefined);
|
|
1800
|
-
const methodType = await this.movedTypes.visit(nc.methodType, undefined);
|
|
1801
|
-
const constructorType = await this.movedTypes.visit(nc.constructorType, undefined);
|
|
1802
|
-
return type === nc.type && methodType === nc.methodType && constructorType === nc.constructorType
|
|
1803
|
-
? nc
|
|
1804
|
-
: Object.assign(Object.assign({}, nc), { type, methodType, constructorType });
|
|
1805
|
-
}
|
|
1806
|
-
async visitFunctionCall(functionCall, p) {
|
|
1807
|
-
var _a;
|
|
1808
|
-
const fc = await super.visitFunctionCall(functionCall, p);
|
|
1809
|
-
if (!this.referencesMovedBinding((_a = fc.function) === null || _a === void 0 ? void 0 : _a.element)) {
|
|
1810
|
-
return fc;
|
|
1811
|
-
}
|
|
1812
|
-
const methodType = await this.movedTypes.visit(fc.methodType, undefined);
|
|
1813
|
-
return methodType === fc.methodType ? fc : Object.assign(Object.assign({}, fc), { methodType });
|
|
1920
|
+
const renamed = this.renaming && this.referencesBinding(identifier);
|
|
1921
|
+
const visited = await super.visitIdentifier(identifier, p);
|
|
1922
|
+
return renamed ? Object.assign(Object.assign({}, visited), { simpleName: this.boundName }) : visited;
|
|
1814
1923
|
}
|
|
1815
|
-
/**
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
*/
|
|
1819
|
-
referencesMovedBinding(callee) {
|
|
1820
|
-
return (callee === null || callee === void 0 ? void 0 : callee.kind) === java_1.J.Kind.Identifier && this.references.has(callee.id);
|
|
1924
|
+
/** Any type in the file can name what moved, whether or not it references the binding. */
|
|
1925
|
+
async visitType(javaType, p) {
|
|
1926
|
+
return this.movedTypes.visit(javaType, undefined);
|
|
1821
1927
|
}
|
|
1822
1928
|
/**
|
|
1823
1929
|
* A decorator and the other type-name positions reach the tree through this hook, which the
|
|
@@ -1841,65 +1947,100 @@ class RebindImport extends visitor_1.JavaScriptVisitor {
|
|
|
1841
1947
|
}
|
|
1842
1948
|
const specifier = exportSpecifier.specifier;
|
|
1843
1949
|
if (specifier.kind === java_1.J.Kind.Identifier && specifier.simpleName === this.localName) {
|
|
1844
|
-
|
|
1950
|
+
const retyped = await this.retyped(specifier);
|
|
1951
|
+
const alias = aliasing(retyped, this.boundName);
|
|
1952
|
+
// The property name is the reference here, so it carries the binding's attribution.
|
|
1953
|
+
const reference = Object.assign(Object.assign({}, alias.propertyName.element), { type: retyped.type, fieldType: retyped.fieldType });
|
|
1954
|
+
return Object.assign(Object.assign({}, exportSpecifier), { specifier: Object.assign(Object.assign({}, alias), { propertyName: Object.assign(Object.assign({}, alias.propertyName), { element: reference }) }) });
|
|
1845
1955
|
}
|
|
1846
1956
|
if (specifier.kind === tree_1.JS.Kind.Alias) {
|
|
1847
1957
|
const alias = specifier;
|
|
1848
1958
|
const propertyName = alias.propertyName.element;
|
|
1849
1959
|
return propertyName.kind === java_1.J.Kind.Identifier && propertyName.simpleName === this.localName
|
|
1850
|
-
? Object.assign(Object.assign({}, exportSpecifier), { specifier: Object.assign(Object.assign({}, alias), { propertyName: Object.assign(Object.assign({}, alias.propertyName), { element: Object.assign(Object.assign({}, propertyName), { simpleName: this.boundName }) }) }) })
|
|
1960
|
+
? Object.assign(Object.assign({}, exportSpecifier), { specifier: Object.assign(Object.assign({}, alias), { propertyName: Object.assign(Object.assign({}, alias.propertyName), { element: Object.assign(Object.assign({}, await this.retyped(propertyName)), { simpleName: this.boundName }) }) }) })
|
|
1851
1961
|
: exportSpecifier;
|
|
1852
1962
|
}
|
|
1853
1963
|
return super.visitExportSpecifier(exportSpecifier, p);
|
|
1854
1964
|
}
|
|
1965
|
+
/** `identifier` attributed to what moved, for a rewrite that does not visit it again. */
|
|
1966
|
+
async retyped(identifier) {
|
|
1967
|
+
return Object.assign(Object.assign({}, identifier), { type: await this.movedTypes.visit(identifier.type, undefined), fieldType: await this.movedTypes.visit(identifier.fieldType, undefined) });
|
|
1968
|
+
}
|
|
1855
1969
|
/**
|
|
1856
1970
|
* Whether the identifier at the cursor stands for the moved binding: the right name, in a
|
|
1857
|
-
* position
|
|
1971
|
+
* position a rename may rewrite, resolving to the module scope that binds it.
|
|
1858
1972
|
*/
|
|
1859
1973
|
referencesBinding(identifier) {
|
|
1974
|
+
return identifier.simpleName === this.localName && this.readsModuleBinding(identifier);
|
|
1975
|
+
}
|
|
1976
|
+
readsModuleBinding(identifier) {
|
|
1860
1977
|
var _a;
|
|
1861
|
-
return identifier.
|
|
1862
|
-
// The specifier binding the name is the one edit that is not a reference to it.
|
|
1863
|
-
!this.cursor.firstEnclosing((v) => (v === null || v === void 0 ? void 0 : v.kind) === tree_1.JS.Kind.Import) &&
|
|
1864
|
-
(0, scope_1.isValueReference)(this.cursor, identifier) &&
|
|
1865
|
-
((_a = (0, scope_1.scopeOf)(this.cursor).declaringScope(this.localName)) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.CompilationUnit;
|
|
1978
|
+
return ((_a = (0, scope_1.resolve)(this.cursor, identifier)) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.CompilationUnit;
|
|
1866
1979
|
}
|
|
1867
|
-
/**
|
|
1980
|
+
/**
|
|
1981
|
+
* A shorthand property's name slot is also the reference to the binding: `{x}` becomes
|
|
1982
|
+
* `{x: y}`, and `{x = 1}` becomes `{x: y = 1}`.
|
|
1983
|
+
*/
|
|
1868
1984
|
async visitPropertyAssignment(propertyAssignment, p) {
|
|
1869
|
-
var _a;
|
|
1870
1985
|
const name = propertyAssignment.name.element;
|
|
1871
|
-
if (this.renaming && propertyAssignment.
|
|
1986
|
+
if (this.renaming && propertyAssignment.assigmentToken === tree_1.JS.PropertyAssignment.Token.Equals &&
|
|
1872
1987
|
name.kind === java_1.J.Kind.Identifier && name.simpleName === this.localName &&
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1988
|
+
this.readsModuleBinding(name)) {
|
|
1989
|
+
const reference = Object.assign(Object.assign({}, await this.retyped(name)), { simpleName: this.boundName });
|
|
1990
|
+
const fallback = propertyAssignment.initializer;
|
|
1991
|
+
// The key names a property rather than the binding, so it is a new node carrying no
|
|
1992
|
+
// attribution, the same way `aliasing` builds a property name that stands for nothing.
|
|
1993
|
+
return Object.assign(Object.assign({}, propertyAssignment), { name: Object.assign(Object.assign({}, propertyAssignment.name), { element: Object.assign(Object.assign({}, name), { id: (0, uuid_1.randomId)(), type: undefined, fieldType: undefined }), after: java_1.emptySpace }), assigmentToken: tree_1.JS.PropertyAssignment.Token.Colon, initializer: fallback === undefined ? Object.assign(Object.assign({}, reference), { prefix: java_1.singleSpace }) : {
|
|
1994
|
+
id: (0, uuid_1.randomId)(),
|
|
1995
|
+
kind: java_1.J.Kind.Assignment,
|
|
1996
|
+
prefix: java_1.singleSpace,
|
|
1997
|
+
markers: markers_1.emptyMarkers,
|
|
1998
|
+
variable: Object.assign(Object.assign({}, reference), { prefix: java_1.emptySpace }),
|
|
1999
|
+
assignment: {
|
|
2000
|
+
kind: java_1.J.Kind.LeftPadded,
|
|
2001
|
+
before: propertyAssignment.name.after,
|
|
2002
|
+
element: fallback,
|
|
2003
|
+
markers: markers_1.emptyMarkers
|
|
2004
|
+
},
|
|
2005
|
+
type: reference.type
|
|
2006
|
+
} });
|
|
1877
2007
|
}
|
|
1878
2008
|
return super.visitPropertyAssignment(propertyAssignment, p);
|
|
1879
2009
|
}
|
|
1880
2010
|
}
|
|
1881
2011
|
exports.RebindImport = RebindImport;
|
|
1882
|
-
/**
|
|
1883
|
-
* Rewrites the attribution a move invalidates, onto the module and member it moved to. Applied at
|
|
1884
|
-
* a reference to the moved binding. See CLAUDE.md: What a rebind's attribution follows.
|
|
1885
|
-
*/
|
|
2012
|
+
/** Rewrites a file's attribution onto the module and member a binding moved to. */
|
|
1886
2013
|
class MovedTypes extends type_visitor_1.TypeVisitor {
|
|
1887
|
-
|
|
2014
|
+
/**
|
|
2015
|
+
* `shared` says what another binding in the file shares with the moved one. A shared module
|
|
2016
|
+
* object or package-qualified class name stands for that binding too, so it keeps its name.
|
|
2017
|
+
*/
|
|
2018
|
+
constructor(from, to, shared) {
|
|
2019
|
+
var _a;
|
|
1888
2020
|
super();
|
|
2021
|
+
this.from = from;
|
|
2022
|
+
this.to = to;
|
|
1889
2023
|
this.onPath = new Set();
|
|
1890
2024
|
this.answered = new Map();
|
|
1891
|
-
|
|
1892
|
-
this.renamed = new Map([[from.module, to.module], [qualifiedName(from), qualifiedName(to)]]);
|
|
2025
|
+
this.modules = new Map();
|
|
1893
2026
|
this.fromMember = declaredMember(from);
|
|
1894
2027
|
this.toMember = declaredMember(to);
|
|
1895
|
-
this.
|
|
2028
|
+
if (this.fromMember === undefined) {
|
|
2029
|
+
this.classes = new Map(shared.module ? [] : [[from.module, qualifiedName(to)]]);
|
|
2030
|
+
}
|
|
2031
|
+
else {
|
|
2032
|
+
// A default export declares no member name, so the class keeps its own.
|
|
2033
|
+
const toClass = `${packageOf(to.module)}.${(_a = this.toMember) !== null && _a !== void 0 ? _a : this.fromMember}`;
|
|
2034
|
+
const packaged = `${packageOf(from.module)}.${this.fromMember}`;
|
|
2035
|
+
// The type mapper names an imported alias symbol after the specifier.
|
|
2036
|
+
this.classes = new Map([packaged, qualifiedName(from)]
|
|
2037
|
+
.filter(name => !shared.className || name !== packaged)
|
|
2038
|
+
.map(name => [name, toClass]));
|
|
2039
|
+
}
|
|
1896
2040
|
}
|
|
1897
2041
|
/**
|
|
1898
|
-
* A type reached while it is still being visited
|
|
1899
|
-
*
|
|
1900
|
-
* type visited is remembered by its answer, so a graph whose references fan out or rejoin is
|
|
1901
|
-
* walked once rather than once per path that reaches into it. An answer settled inside a cycle
|
|
1902
|
-
* stands for the path it was on, so a walk reusing it can leave a rename unapplied.
|
|
2042
|
+
* A type reached while it is still being visited answers with itself, which ends a cycle
|
|
2043
|
+
* through a type variable's bounds. An answer settled inside such a cycle can miss a rename.
|
|
1903
2044
|
*/
|
|
1904
2045
|
async visit(type, p) {
|
|
1905
2046
|
if (type === undefined || this.onPath.has(type)) {
|
|
@@ -1918,35 +2059,54 @@ class MovedTypes extends type_visitor_1.TypeVisitor {
|
|
|
1918
2059
|
this.onPath.delete(type);
|
|
1919
2060
|
}
|
|
1920
2061
|
}
|
|
2062
|
+
/** A class's members are left out, which keeps the walk to a type's signature, as in Java's `ChangeType`. */
|
|
1921
2063
|
async visitClass(aClass, p) {
|
|
1922
|
-
const visited =
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
:
|
|
2064
|
+
const visited = (0, util_1.updateIfChanged)(aClass, {
|
|
2065
|
+
supertype: await this.visit(aClass.supertype, p),
|
|
2066
|
+
owningClass: await this.visit(aClass.owningClass, p),
|
|
2067
|
+
interfaces: aClass.interfaces && await (0, util_1.mapAsync)(aClass.interfaces, i => this.visit(i, p)),
|
|
2068
|
+
typeParameters: aClass.typeParameters && await (0, util_1.mapAsync)(aClass.typeParameters, t => this.visit(t, p))
|
|
2069
|
+
});
|
|
2070
|
+
const moved = this.classes.get(visited.fullyQualifiedName);
|
|
2071
|
+
return moved === undefined ? visited : Object.assign(Object.assign({}, visited), { fullyQualifiedName: moved });
|
|
1927
2072
|
}
|
|
1928
2073
|
async visitMethod(method, p) {
|
|
2074
|
+
var _a;
|
|
1929
2075
|
const visited = await super.visitMethod(method, p);
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
2076
|
+
if (!this.isMovedMember(method.name, method.declaringType)) {
|
|
2077
|
+
return visited;
|
|
2078
|
+
}
|
|
2079
|
+
const declaringType = this.movedModule(method.declaringType);
|
|
2080
|
+
return Object.assign(Object.assign({}, visited), { declaringType, name: (_a = this.toMember) !== null && _a !== void 0 ? _a : visited.name });
|
|
1933
2081
|
}
|
|
1934
2082
|
async visitVariable(variable, p) {
|
|
2083
|
+
var _a;
|
|
1935
2084
|
const visited = await super.visitVariable(variable, p);
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
2085
|
+
if (!this.isMovedMember(variable.name, variable.owner)) {
|
|
2086
|
+
return visited;
|
|
2087
|
+
}
|
|
2088
|
+
return Object.assign(Object.assign({}, visited), { owner: this.movedModule(variable.owner), name: (_a = this.toMember) !== null && _a !== void 0 ? _a : visited.name });
|
|
1939
2089
|
}
|
|
1940
2090
|
/**
|
|
1941
|
-
* Whether `name
|
|
1942
|
-
*
|
|
1943
|
-
* default or namespace binding declares no member, so there is no name for one to take.
|
|
2091
|
+
* Whether `name` is the moved member as the module object `owner` declares it. That covers a
|
|
2092
|
+
* function, a constant and a moved class's constructor. A sibling declared beside it is not one.
|
|
1944
2093
|
*/
|
|
1945
|
-
|
|
1946
|
-
return this.
|
|
1947
|
-
owner
|
|
1948
|
-
java_1.Type.FullyQualified.getFullyQualifiedName(owner) === this.toModule;
|
|
2094
|
+
isMovedMember(name, owner) {
|
|
2095
|
+
return this.fromMember !== undefined && name === this.fromMember && owner !== undefined &&
|
|
2096
|
+
java_1.Type.isFullyQualified(owner) && java_1.Type.FullyQualified.getFullyQualifiedName(owner) === this.from.module;
|
|
1949
2097
|
}
|
|
2098
|
+
movedModule(owner) {
|
|
2099
|
+
let moved = this.modules.get(owner);
|
|
2100
|
+
if (moved === undefined) {
|
|
2101
|
+
moved = Object.assign(Object.assign({}, owner), { fullyQualifiedName: this.to.module });
|
|
2102
|
+
this.modules.set(owner, moved);
|
|
2103
|
+
}
|
|
2104
|
+
return moved;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
/** The package a class `module` exports is named after. A relative specifier names none, so it stands for itself. */
|
|
2108
|
+
function packageOf(module) {
|
|
2109
|
+
return module.startsWith('.') || module.startsWith('/') ? module : (0, package_name_1.packageNameOf)(module);
|
|
1950
2110
|
}
|
|
1951
2111
|
/** A member's qualified name, or the module's own where no member is named. */
|
|
1952
2112
|
function qualifiedName(binding) {
|