@openrewrite/rewrite 8.91.0 → 8.91.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/java/formatting-utils.d.ts +8 -5
- package/dist/java/formatting-utils.d.ts.map +1 -1
- package/dist/java/formatting-utils.js +14 -10
- package/dist/java/formatting-utils.js.map +1 -1
- package/dist/java/type.d.ts +2 -0
- package/dist/java/type.d.ts.map +1 -1
- package/dist/java/type.js +5 -0
- package/dist/java/type.js.map +1 -1
- package/dist/javascript/add-import.d.ts +96 -43
- package/dist/javascript/add-import.d.ts.map +1 -1
- package/dist/javascript/add-import.js +668 -236
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/amd.d.ts +138 -0
- package/dist/javascript/amd.d.ts.map +1 -0
- package/dist/javascript/amd.js +768 -0
- package/dist/javascript/amd.js.map +1 -0
- package/dist/javascript/assertions.d.ts +7 -0
- package/dist/javascript/assertions.d.ts.map +1 -1
- package/dist/javascript/assertions.js +31 -5
- package/dist/javascript/assertions.js.map +1 -1
- package/dist/javascript/binding.d.ts +94 -0
- package/dist/javascript/binding.d.ts.map +1 -0
- package/dist/javascript/binding.js +335 -0
- package/dist/javascript/binding.js.map +1 -0
- package/dist/javascript/comparator.d.ts +5 -0
- package/dist/javascript/comparator.d.ts.map +1 -1
- package/dist/javascript/comparator.js +34 -9
- package/dist/javascript/comparator.js.map +1 -1
- package/dist/javascript/format/format.d.ts.map +1 -1
- package/dist/javascript/format/format.js +8 -9
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.d.ts +2 -0
- package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.js +17 -11
- package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
- package/dist/javascript/index.d.ts +8 -1
- package/dist/javascript/index.d.ts.map +1 -1
- package/dist/javascript/index.js +26 -1
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/node-resolution-result.d.ts +19 -1
- package/dist/javascript/node-resolution-result.d.ts.map +1 -1
- package/dist/javascript/node-resolution-result.js +37 -2
- package/dist/javascript/node-resolution-result.js.map +1 -1
- package/dist/javascript/package-exported-types.d.ts.map +1 -1
- package/dist/javascript/package-exported-types.js +56 -72
- package/dist/javascript/package-exported-types.js.map +1 -1
- package/dist/javascript/parser-utils.d.ts.map +1 -1
- package/dist/javascript/parser-utils.js +2 -0
- package/dist/javascript/parser-utils.js.map +1 -1
- package/dist/javascript/parser.d.ts +7 -1
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +17 -4
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/recipes/change-import.d.ts +2 -4
- package/dist/javascript/recipes/change-import.d.ts.map +1 -1
- package/dist/javascript/recipes/change-import.js +8 -244
- package/dist/javascript/recipes/change-import.js.map +1 -1
- package/dist/javascript/remove-import.d.ts +2 -28
- package/dist/javascript/remove-import.d.ts.map +1 -1
- package/dist/javascript/remove-import.js +19 -57
- package/dist/javascript/remove-import.js.map +1 -1
- package/dist/javascript/scope.d.ts +49 -0
- package/dist/javascript/scope.d.ts.map +1 -0
- package/dist/javascript/scope.js +324 -0
- package/dist/javascript/scope.js.map +1 -0
- package/dist/javascript/style.d.ts.map +1 -1
- package/dist/javascript/style.js +3 -10
- package/dist/javascript/style.js.map +1 -1
- package/dist/javascript/templating/bindings.d.ts +8 -0
- package/dist/javascript/templating/bindings.d.ts.map +1 -0
- package/dist/javascript/templating/bindings.js +92 -0
- package/dist/javascript/templating/bindings.js.map +1 -0
- package/dist/javascript/templating/comparator.d.ts +10 -0
- package/dist/javascript/templating/comparator.d.ts.map +1 -1
- package/dist/javascript/templating/comparator.js +48 -20
- package/dist/javascript/templating/comparator.js.map +1 -1
- package/dist/javascript/templating/engine.d.ts +34 -10
- package/dist/javascript/templating/engine.d.ts.map +1 -1
- package/dist/javascript/templating/engine.js +109 -55
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/index.d.ts +1 -1
- package/dist/javascript/templating/index.d.ts.map +1 -1
- package/dist/javascript/templating/index.js.map +1 -1
- package/dist/javascript/templating/pattern.d.ts.map +1 -1
- package/dist/javascript/templating/pattern.js +13 -10
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.d.ts +4 -0
- package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.js +24 -10
- package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
- package/dist/javascript/templating/precedence.d.ts +12 -4
- package/dist/javascript/templating/precedence.d.ts.map +1 -1
- package/dist/javascript/templating/precedence.js +18 -11
- package/dist/javascript/templating/precedence.js.map +1 -1
- package/dist/javascript/templating/rewrite.d.ts.map +1 -1
- package/dist/javascript/templating/rewrite.js +19 -17
- package/dist/javascript/templating/rewrite.js.map +1 -1
- package/dist/javascript/templating/template.d.ts +14 -0
- package/dist/javascript/templating/template.d.ts.map +1 -1
- package/dist/javascript/templating/template.js +63 -3
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/templating/types.d.ts +39 -1
- package/dist/javascript/templating/types.d.ts.map +1 -1
- package/dist/javascript/templating/utils.d.ts +6 -1
- package/dist/javascript/templating/utils.d.ts.map +1 -1
- package/dist/javascript/templating/utils.js +20 -2
- package/dist/javascript/templating/utils.js.map +1 -1
- package/dist/javascript/type-mapping.d.ts +1 -0
- package/dist/javascript/type-mapping.d.ts.map +1 -1
- package/dist/javascript/type-mapping.js +52 -2
- package/dist/javascript/type-mapping.js.map +1 -1
- package/dist/rewrite-javascript-version.txt +1 -1
- package/dist/style.d.ts +2 -0
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +5 -0
- package/dist/style.js.map +1 -1
- package/dist/test/rewrite-test.d.ts +12 -0
- package/dist/test/rewrite-test.d.ts.map +1 -1
- package/dist/test/rewrite-test.js +40 -3
- package/dist/test/rewrite-test.js.map +1 -1
- package/package.json +2 -2
- package/src/java/formatting-utils.ts +14 -10
- package/src/java/type.ts +5 -0
- package/src/javascript/add-import.ts +751 -247
- package/src/javascript/amd.ts +915 -0
- package/src/javascript/assertions.ts +33 -5
- package/src/javascript/binding.ts +449 -0
- package/src/javascript/comparator.ts +39 -10
- package/src/javascript/format/format.ts +9 -10
- package/src/javascript/format/tabs-and-indents-visitor.ts +18 -12
- package/src/javascript/index.ts +12 -1
- package/src/javascript/node-resolution-result.ts +59 -4
- package/src/javascript/package-exported-types.ts +60 -74
- package/src/javascript/parser-utils.ts +2 -0
- package/src/javascript/parser.ts +23 -3
- package/src/javascript/recipes/change-import.ts +10 -263
- package/src/javascript/remove-import.ts +20 -56
- package/src/javascript/scope.ts +338 -0
- package/src/javascript/style.ts +3 -11
- package/src/javascript/templating/bindings.ts +99 -0
- package/src/javascript/templating/comparator.ts +57 -20
- package/src/javascript/templating/engine.ts +148 -68
- package/src/javascript/templating/index.ts +1 -0
- package/src/javascript/templating/pattern.ts +19 -16
- package/src/javascript/templating/placeholder-replacement.ts +32 -11
- package/src/javascript/templating/precedence.ts +21 -13
- package/src/javascript/templating/rewrite.ts +23 -17
- package/src/javascript/templating/template.ts +84 -9
- package/src/javascript/templating/types.ts +46 -1
- package/src/javascript/templating/utils.ts +21 -2
- package/src/javascript/type-mapping.ts +54 -2
- package/src/style.ts +5 -0
- package/src/test/rewrite-test.ts +61 -3
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AddImport = exports.ImportStyle = void 0;
|
|
4
|
-
exports.
|
|
3
|
+
exports.RebindImport = exports.AddImport = exports.ImportStyle = void 0;
|
|
4
|
+
exports.bindImport = bindImport;
|
|
5
|
+
exports.memberName = memberName;
|
|
6
|
+
exports.moduleScopeBindings = moduleScopeBindings;
|
|
7
|
+
exports.requiredModuleOf = requiredModuleOf;
|
|
8
|
+
exports.moduleNameOf = moduleNameOf;
|
|
9
|
+
exports.existingImportBinding = existingImportBinding;
|
|
5
10
|
const visitor_1 = require("./visitor");
|
|
6
11
|
const java_1 = require("../java");
|
|
7
12
|
const tree_1 = require("./tree");
|
|
8
13
|
const uuid_1 = require("../uuid");
|
|
9
14
|
const markers_1 = require("../markers");
|
|
10
15
|
const style_1 = require("./style");
|
|
16
|
+
const scope_1 = require("./scope");
|
|
17
|
+
const mutative_1 = require("mutative");
|
|
11
18
|
var ImportStyle;
|
|
12
19
|
(function (ImportStyle) {
|
|
13
20
|
ImportStyle[ImportStyle["ES6Named"] = 0] = "ES6Named";
|
|
@@ -16,96 +23,389 @@ var ImportStyle;
|
|
|
16
23
|
ImportStyle[ImportStyle["CommonJS"] = 3] = "CommonJS"; // const x = require('module')
|
|
17
24
|
})(ImportStyle || (exports.ImportStyle = ImportStyle = {}));
|
|
18
25
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* // Add a named import
|
|
25
|
-
* maybeAddImport(visitor, { module: 'fs', member: 'readFile' });
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* // Add a default import using the 'default' member specifier
|
|
29
|
-
* maybeAddImport(visitor, { module: 'react', member: 'default', alias: 'React' });
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* // Add a default import (legacy way, without specifying member)
|
|
33
|
-
* maybeAddImport(visitor, { module: 'react', alias: 'React' });
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* // Add a namespace import
|
|
37
|
-
* maybeAddImport(visitor, { module: 'crypto', member: '*', alias: 'crypto' });
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* // Add a side-effect import
|
|
41
|
-
* maybeAddImport(visitor, { module: 'core-js/stable', sideEffectOnly: true });
|
|
26
|
+
* Ensures an import for `options.module` exists, queuing an `AddImport` edit where none already
|
|
27
|
+
* serves the request. `maybeBind`'s ESM/CommonJS lane is this function; its own JSDoc carries the
|
|
28
|
+
* return-value contract. `refuseCreate` answers `undefined` instead of queuing a new import,
|
|
29
|
+
* without affecting whether an existing binding answers the request first.
|
|
42
30
|
*/
|
|
43
|
-
function
|
|
31
|
+
function bindImport(visitor, options, refuseCreate) {
|
|
44
32
|
var _a, _b;
|
|
33
|
+
validate(options);
|
|
34
|
+
const module = moduleNameOf(options.module);
|
|
35
|
+
const sideEffectOnly = (_a = options.sideEffectOnly) !== null && _a !== void 0 ? _a : false;
|
|
36
|
+
const typeOnly = (_b = options.typeOnly) !== null && _b !== void 0 ? _b : false;
|
|
37
|
+
// A queued import binds the module as much as one already in the file, so it answers a later
|
|
38
|
+
// request the same way; a name a merged request never emits would be referenced but not bound.
|
|
45
39
|
for (const v of visitor.afterVisit || []) {
|
|
46
|
-
if (v instanceof AddImport
|
|
47
|
-
v.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
if (!(v instanceof AddImport) || v.module !== module ||
|
|
41
|
+
v.sideEffectOnly !== sideEffectOnly || v.typeOnly !== typeOnly) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// How a specifier prints, or what name would be nice, does not say which binding is wanted.
|
|
45
|
+
// A pinned alias does: it asks for a binding of its own, which only the same request answers.
|
|
46
|
+
const answers = options.alias
|
|
47
|
+
? v.alias === options.alias && v.member === options.member
|
|
48
|
+
: memberName(v.member) === memberName(options.member);
|
|
49
|
+
if (answers) {
|
|
50
|
+
return v.bindingName;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (sideEffectOnly) {
|
|
54
|
+
if (refuseCreate) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
visitor.afterVisit.push(new AddImport(options));
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
// A pinned alias is the whole answer, so the file has no say and nothing below needs to read it.
|
|
61
|
+
if (options.alias) {
|
|
62
|
+
if (refuseCreate) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
visitor.afterVisit.push(new AddImport(options, options.alias));
|
|
66
|
+
return options.alias;
|
|
67
|
+
}
|
|
68
|
+
const derived = derivedName(options);
|
|
69
|
+
const cursor = (0, scope_1.cursorOf)(visitor);
|
|
70
|
+
const cu = cursor && (0, scope_1.compilationUnitOf)(cursor);
|
|
71
|
+
if (!cu) {
|
|
72
|
+
if (refuseCreate) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
visitor.afterVisit.push(new AddImport(options, derived));
|
|
76
|
+
return derived;
|
|
77
|
+
}
|
|
78
|
+
// An import already serving this request answers it; queuing one would, on the next cycle,
|
|
79
|
+
// derive a suffixed name from the binding this call just added. A caller that named a preference
|
|
80
|
+
// takes whatever comes back; one that did not assumes the name it derived, so a binding under
|
|
81
|
+
// any other name would leave the references it emits unbound.
|
|
82
|
+
for (const binding of moduleScopeBindings(cu)) {
|
|
83
|
+
if (binding.module === module && binding.member === memberName(options.member) &&
|
|
84
|
+
binding.typeOnly === typeOnly &&
|
|
85
|
+
(options.preferredName !== undefined || anyNameAnswers(options) ||
|
|
86
|
+
binding.name === derived)) {
|
|
87
|
+
return binding.name;
|
|
53
88
|
}
|
|
54
89
|
}
|
|
55
|
-
|
|
90
|
+
if (refuseCreate) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
// Only the module scope answers for a name, but any scope in the file occupies one. The queue
|
|
94
|
+
// gives every later request for this module the name chosen here, so it has to clear the scopes
|
|
95
|
+
// those references will sit in, which are not known yet.
|
|
96
|
+
const taken = takenNames((0, scope_1.namesDeclaredIn)(cu), visitor);
|
|
97
|
+
const name = (0, scope_1.deconflict)(derived, candidate => taken.has(candidate));
|
|
98
|
+
visitor.afterVisit.push(new AddImport(options, name));
|
|
99
|
+
return name;
|
|
56
100
|
}
|
|
57
|
-
|
|
58
|
-
|
|
101
|
+
/** Rejects a request on its own terms, whatever the queue already holds. */
|
|
102
|
+
function validate(options) {
|
|
103
|
+
// Validate that a name is provided when member is 'default'
|
|
104
|
+
if (options.member === 'default' && !options.alias && !options.preferredName) {
|
|
105
|
+
throw new Error("When member is 'default', the alias parameter is required");
|
|
106
|
+
}
|
|
107
|
+
// Validate that a name is provided when member is '*' (namespace import)
|
|
108
|
+
if (options.member === '*' && !options.alias && !options.preferredName) {
|
|
109
|
+
throw new Error("When member is '*', the alias parameter is required");
|
|
110
|
+
}
|
|
111
|
+
// Validate that sideEffectOnly is not combined with incompatible options
|
|
112
|
+
if (options.sideEffectOnly) {
|
|
113
|
+
if (options.member !== undefined) {
|
|
114
|
+
throw new Error("Cannot combine sideEffectOnly with member");
|
|
115
|
+
}
|
|
116
|
+
if (options.alias !== undefined) {
|
|
117
|
+
throw new Error("Cannot combine sideEffectOnly with alias");
|
|
118
|
+
}
|
|
119
|
+
if (options.preferredName !== undefined) {
|
|
120
|
+
throw new Error("Cannot combine sideEffectOnly with preferredName");
|
|
121
|
+
}
|
|
122
|
+
if (options.onlyIfReferenced !== undefined) {
|
|
123
|
+
throw new Error("Cannot combine sideEffectOnly with onlyIfReferenced");
|
|
124
|
+
}
|
|
125
|
+
if (options.typeOnly) {
|
|
126
|
+
throw new Error("Cannot combine sideEffectOnly with typeOnly");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* A request that named no local name and asks for no member of the module. Having expressed no
|
|
132
|
+
* preference it has none to disappoint, so whatever the file already calls that module answers it.
|
|
133
|
+
*/
|
|
134
|
+
function anyNameAnswers(options) {
|
|
135
|
+
return !options.sideEffectOnly && memberName(options.member) === undefined &&
|
|
136
|
+
options.alias === undefined && options.preferredName === undefined;
|
|
137
|
+
}
|
|
138
|
+
/** The local name a request asks for, before the file has a say in it. */
|
|
139
|
+
function derivedName(options) {
|
|
140
|
+
var _a, _b, _c;
|
|
141
|
+
return (_c = (_b = (_a = options.alias) !== null && _a !== void 0 ? _a : options.preferredName) !== null && _b !== void 0 ? _b : memberName(options.member)) !== null && _c !== void 0 ? _c : moduleNameOf(options.module);
|
|
142
|
+
}
|
|
143
|
+
/** `'default'` and an absent member both name a default import, which binds no member name of its own. */
|
|
144
|
+
function memberName(member) {
|
|
145
|
+
return member === 'default' ? undefined : member;
|
|
146
|
+
}
|
|
147
|
+
/** What the file's imports and `require`s bind at module scope, and the module each name comes from. */
|
|
148
|
+
function moduleScopeBindings(cu) {
|
|
149
|
+
const bindings = [];
|
|
150
|
+
const declaredByVariables = (varDecl) => {
|
|
59
151
|
var _a, _b, _c;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
// Validate that alias is provided when member is '*' (namespace import)
|
|
66
|
-
if (options.member === '*' && !options.alias) {
|
|
67
|
-
throw new Error("When member is '*', the alias parameter is required");
|
|
68
|
-
}
|
|
69
|
-
// Validate that sideEffectOnly is not combined with incompatible options
|
|
70
|
-
if (options.sideEffectOnly) {
|
|
71
|
-
if (options.member !== undefined) {
|
|
72
|
-
throw new Error("Cannot combine sideEffectOnly with member");
|
|
152
|
+
for (const variable of varDecl.variables) {
|
|
153
|
+
const required = requiredModule((_b = (_a = variable.element) === null || _a === void 0 ? void 0 : _a.initializer) === null || _b === void 0 ? void 0 : _b.element);
|
|
154
|
+
if (required !== undefined) {
|
|
155
|
+
bindings.push(...requireBindings((_c = variable.element) === null || _c === void 0 ? void 0 : _c.name, required));
|
|
73
156
|
}
|
|
74
|
-
|
|
75
|
-
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
for (const stmt of cu.statements) {
|
|
160
|
+
const statement = stmt.element;
|
|
161
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
|
|
162
|
+
bindings.push(...importBindings(statement));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
for (const declaration of (0, scope_1.declarationsOf)(statement)) {
|
|
166
|
+
declaredByVariables(declaration);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return bindings;
|
|
170
|
+
}
|
|
171
|
+
/** The module a `require('...')` initializer names, `undefined` for an initializer that is anything else. */
|
|
172
|
+
function requiredModule(initializer) {
|
|
173
|
+
return (initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation
|
|
174
|
+
? requiredModuleOf(initializer)
|
|
175
|
+
: undefined;
|
|
176
|
+
}
|
|
177
|
+
/** A `require(...)` call, whatever it is passed. `obj.require('x')` selects a method rather than loading a module. */
|
|
178
|
+
function isRequireCall(methodInv) {
|
|
179
|
+
var _a;
|
|
180
|
+
return !methodInv.select && ((_a = methodInv.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
|
|
181
|
+
methodInv.name.simpleName === 'require';
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The module a `require(...)` call loads. `obj.require('x')` selects a method rather than loading a
|
|
185
|
+
* module, and a specifier that is not a string literal names none that can be read here.
|
|
186
|
+
*/
|
|
187
|
+
function requiredModuleOf(methodInv) {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
if (!isRequireCall(methodInv)) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
const argument = (_b = (_a = methodInv.arguments) === null || _a === void 0 ? void 0 : _a.elements[0]) === null || _b === void 0 ? void 0 : _b.element;
|
|
193
|
+
return (argument === null || argument === void 0 ? void 0 : argument.kind) === java_1.J.Kind.Literal && typeof argument.value === 'string'
|
|
194
|
+
? moduleNameOf(argument)
|
|
195
|
+
: undefined;
|
|
196
|
+
}
|
|
197
|
+
/** A `require` binds a module the way an import does, so the pool records it the same way. */
|
|
198
|
+
function requireBindings(pattern, module) {
|
|
199
|
+
// A whole-module require binds no member, exactly as a default import does.
|
|
200
|
+
if ((pattern === null || pattern === void 0 ? void 0 : pattern.kind) === java_1.J.Kind.Identifier) {
|
|
201
|
+
return [{ name: pattern.simpleName, module, member: undefined, typeOnly: false }];
|
|
202
|
+
}
|
|
203
|
+
return (0, scope_1.bindingNames)(pattern).map(bound => bound.member === undefined
|
|
204
|
+
? { name: bound.name }
|
|
205
|
+
: { name: bound.name, module, member: bound.member, typeOnly: false });
|
|
206
|
+
}
|
|
207
|
+
/** The member a specifier imports and the name it binds it under, which are the same absent an alias. */
|
|
208
|
+
function specifierBinding(specifier) {
|
|
209
|
+
var _a, _b, _c, _d, _e;
|
|
210
|
+
if (((_a = specifier.specifier) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier) {
|
|
211
|
+
const name = specifier.specifier.simpleName;
|
|
212
|
+
return { name, member: name };
|
|
213
|
+
}
|
|
214
|
+
if (((_b = specifier.specifier) === null || _b === void 0 ? void 0 : _b.kind) !== tree_1.JS.Kind.Alias) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
const alias = specifier.specifier;
|
|
218
|
+
return ((_d = (_c = alias.propertyName) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.kind) === java_1.J.Kind.Identifier && ((_e = alias.alias) === null || _e === void 0 ? void 0 : _e.kind) === java_1.J.Kind.Identifier
|
|
219
|
+
? { name: alias.alias.simpleName, member: alias.propertyName.element.simpleName }
|
|
220
|
+
: undefined;
|
|
221
|
+
}
|
|
222
|
+
function importBindings(jsImport) {
|
|
223
|
+
var _a, _b, _c, _d;
|
|
224
|
+
const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
225
|
+
const module = (moduleSpecifier === null || moduleSpecifier === void 0 ? void 0 : moduleSpecifier.kind) === java_1.J.Kind.Literal
|
|
226
|
+
? moduleNameOf(moduleSpecifier)
|
|
227
|
+
: undefined;
|
|
228
|
+
const importClause = jsImport.importClause;
|
|
229
|
+
if (!importClause) {
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
const typeOnly = importClause.typeOnly;
|
|
233
|
+
const bindings = [];
|
|
234
|
+
if (((_c = (_b = importClause.name) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
|
|
235
|
+
bindings.push({ name: importClause.name.element.simpleName, module, member: undefined, typeOnly });
|
|
236
|
+
}
|
|
237
|
+
const namedBindings = importClause.namedBindings;
|
|
238
|
+
if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === java_1.J.Kind.Identifier) {
|
|
239
|
+
bindings.push({ name: namedBindings.simpleName, module, member: '*', typeOnly });
|
|
240
|
+
}
|
|
241
|
+
else if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.Alias) {
|
|
242
|
+
const alias = namedBindings.alias;
|
|
243
|
+
if ((alias === null || alias === void 0 ? void 0 : alias.kind) === java_1.J.Kind.Identifier) {
|
|
244
|
+
bindings.push({ name: alias.simpleName, module, member: '*', typeOnly });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.NamedImports) {
|
|
248
|
+
for (const elem of namedBindings.elements.elements) {
|
|
249
|
+
const bound = ((_d = elem.element) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.ImportSpecifier
|
|
250
|
+
? specifierBinding(elem.element)
|
|
251
|
+
: undefined;
|
|
252
|
+
if (bound) {
|
|
253
|
+
bindings.push(Object.assign(Object.assign({}, bound), { module, typeOnly }));
|
|
76
254
|
}
|
|
77
|
-
|
|
78
|
-
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return bindings;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Names in scope, plus those pending `AddImport`s on the `afterVisit` queue have claimed. A queued
|
|
261
|
+
* `RemoveImport` does not free one: it removes only what the file leaves unused, and binding a name
|
|
262
|
+
* it keeps is an error, where an unnecessary suffix merely reads oddly.
|
|
263
|
+
*/
|
|
264
|
+
function takenNames(inScope, visitor) {
|
|
265
|
+
const taken = new Set(inScope);
|
|
266
|
+
for (const v of visitor.afterVisit || []) {
|
|
267
|
+
if (v instanceof AddImport && v.bindingName) {
|
|
268
|
+
taken.add(v.bindingName);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return taken;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* The parser lifts surrogate pairs out of `valueSource` into `unicodeEscapes` and, when it does,
|
|
275
|
+
* sets `value` to the quoted source (`parser.ts` `mapLiteral`), so neither field alone is the
|
|
276
|
+
* module name. Reuniting them and stripping the quotes yields it for either shape of literal.
|
|
277
|
+
*/
|
|
278
|
+
function moduleNameOf(module) {
|
|
279
|
+
var _a;
|
|
280
|
+
if (typeof module === 'string') {
|
|
281
|
+
return module;
|
|
282
|
+
}
|
|
283
|
+
const source = module.valueSource;
|
|
284
|
+
if (source === undefined) {
|
|
285
|
+
return String(module.value);
|
|
286
|
+
}
|
|
287
|
+
let restored = '';
|
|
288
|
+
let cut = 0;
|
|
289
|
+
for (const escape of (_a = module.unicodeEscapes) !== null && _a !== void 0 ? _a : []) {
|
|
290
|
+
restored += source.slice(cut, escape.valueSourceIndex) + String.fromCharCode(parseInt(escape.codePoint, 16));
|
|
291
|
+
cut = escape.valueSourceIndex;
|
|
292
|
+
}
|
|
293
|
+
restored += source.slice(cut);
|
|
294
|
+
const quote = restored.charAt(0);
|
|
295
|
+
return (quote === "'" || quote === '"') && restored.endsWith(quote) && restored.length > 1
|
|
296
|
+
? restored.slice(1, -1)
|
|
297
|
+
: restored;
|
|
298
|
+
}
|
|
299
|
+
function quoteOf(expression) {
|
|
300
|
+
if ((expression === null || expression === void 0 ? void 0 : expression.kind) !== java_1.J.Kind.Literal) {
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
const source = expression.valueSource;
|
|
304
|
+
const quote = source === null || source === void 0 ? void 0 : source.charAt(0);
|
|
305
|
+
// JsxText carries raw text as its `valueSource`, so a leading quote alone does not make a
|
|
306
|
+
// literal quote-delimited; requiring a matching pair keeps prose out of the tally.
|
|
307
|
+
return (quote === "'" || quote === '"') && source.length > 1 && source.endsWith(quote)
|
|
308
|
+
? quote
|
|
309
|
+
: undefined;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Pick the quote character for a module specifier being added to `cu`, so that it agrees
|
|
313
|
+
* with the file it lands in. An existing specifier is the most direct precedent; a Prettier
|
|
314
|
+
* config states intent even where the file itself has not been formatted to match.
|
|
315
|
+
*/
|
|
316
|
+
async function detectQuote(cu) {
|
|
317
|
+
var _a, _b;
|
|
318
|
+
// Static imports are top-level, so the highest-ranked signal needs no traversal to find.
|
|
319
|
+
for (const statement of cu.statements) {
|
|
320
|
+
const element = statement.element;
|
|
321
|
+
const topLevelQuote = (element === null || element === void 0 ? void 0 : element.kind) === tree_1.JS.Kind.Import
|
|
322
|
+
? quoteOf((_a = element.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element)
|
|
323
|
+
: (element === null || element === void 0 ? void 0 : element.kind) === tree_1.JS.Kind.ExportDeclaration
|
|
324
|
+
? quoteOf((_b = element.moduleSpecifier) === null || _b === void 0 ? void 0 : _b.element)
|
|
325
|
+
: undefined;
|
|
326
|
+
if (topLevelQuote) {
|
|
327
|
+
return topLevelQuote;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
let importQuote;
|
|
331
|
+
let requireQuote;
|
|
332
|
+
let single = 0;
|
|
333
|
+
let double = 0;
|
|
334
|
+
await new class extends visitor_1.JavaScriptVisitor {
|
|
335
|
+
async visitImportDeclaration(jsImport, p) {
|
|
336
|
+
var _a;
|
|
337
|
+
importQuote !== null && importQuote !== void 0 ? importQuote : (importQuote = quoteOf((_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element));
|
|
338
|
+
return super.visitImportDeclaration(jsImport, p);
|
|
339
|
+
}
|
|
340
|
+
async visitExportDeclaration(exportDeclaration, p) {
|
|
341
|
+
var _a;
|
|
342
|
+
importQuote !== null && importQuote !== void 0 ? importQuote : (importQuote = quoteOf((_a = exportDeclaration.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element));
|
|
343
|
+
return super.visitExportDeclaration(exportDeclaration, p);
|
|
344
|
+
}
|
|
345
|
+
async visitMethodInvocation(method, p) {
|
|
346
|
+
var _a, _b, _c;
|
|
347
|
+
if (!method.select && ((_a = method.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
|
|
348
|
+
method.name.simpleName === 'require') {
|
|
349
|
+
requireQuote !== null && requireQuote !== void 0 ? requireQuote : (requireQuote = quoteOf((_c = (_b = method.arguments) === null || _b === void 0 ? void 0 : _b.elements[0]) === null || _c === void 0 ? void 0 : _c.element));
|
|
79
350
|
}
|
|
80
|
-
|
|
81
|
-
|
|
351
|
+
return super.visitMethodInvocation(method, p);
|
|
352
|
+
}
|
|
353
|
+
async visitJsxAttribute(attribute, p) {
|
|
354
|
+
// JSX attribute quoting answers to Prettier's `jsxSingleQuote`, so it is no evidence
|
|
355
|
+
// about the quote style of ordinary strings.
|
|
356
|
+
return attribute;
|
|
357
|
+
}
|
|
358
|
+
async visitLiteral(literal, p) {
|
|
359
|
+
const quote = quoteOf(literal);
|
|
360
|
+
if (quote === "'") {
|
|
361
|
+
single++;
|
|
82
362
|
}
|
|
363
|
+
else if (quote === '"') {
|
|
364
|
+
double++;
|
|
365
|
+
}
|
|
366
|
+
return super.visitLiteral(literal, p);
|
|
367
|
+
}
|
|
368
|
+
}().visit(cu, undefined);
|
|
369
|
+
// Imports outrank requires; that ordering is what makes the import-only scan above sound.
|
|
370
|
+
const specifierQuote = importQuote !== null && importQuote !== void 0 ? importQuote : requireQuote;
|
|
371
|
+
if (specifierQuote) {
|
|
372
|
+
return specifierQuote;
|
|
373
|
+
}
|
|
374
|
+
const prettier = (0, style_1.getStyle)(style_1.StyleKind.PrettierStyle, cu);
|
|
375
|
+
if ((prettier === null || prettier === void 0 ? void 0 : prettier.kind) === style_1.StyleKind.PrettierStyle && !prettier.ignored) {
|
|
376
|
+
const singleQuote = prettier.config.singleQuote;
|
|
377
|
+
if (typeof singleQuote === 'boolean') {
|
|
378
|
+
return singleQuote ? "'" : '"';
|
|
83
379
|
}
|
|
84
|
-
|
|
380
|
+
}
|
|
381
|
+
return double > single ? '"' : "'";
|
|
382
|
+
}
|
|
383
|
+
class AddImport extends visitor_1.JavaScriptVisitor {
|
|
384
|
+
constructor(options, bindingName) {
|
|
385
|
+
var _a, _b, _c;
|
|
386
|
+
super();
|
|
387
|
+
validate(options);
|
|
388
|
+
this.module = moduleNameOf(options.module);
|
|
389
|
+
this.moduleValueSource = typeof options.module === 'string' ? undefined : options.module.valueSource;
|
|
390
|
+
this.moduleUnicodeEscapes = typeof options.module === 'string' ? undefined : options.module.unicodeEscapes;
|
|
85
391
|
this.member = options.member;
|
|
86
392
|
this.alias = options.alias;
|
|
87
393
|
this.onlyIfReferenced = (_a = options.onlyIfReferenced) !== null && _a !== void 0 ? _a : true;
|
|
88
394
|
this.sideEffectOnly = (_b = options.sideEffectOnly) !== null && _b !== void 0 ? _b : false;
|
|
89
395
|
this.typeOnly = (_c = options.typeOnly) !== null && _c !== void 0 ? _c : false;
|
|
90
396
|
this.style = options.style;
|
|
397
|
+
this.quoteStyle = options.quoteStyle;
|
|
398
|
+
this.bindingName = this.sideEffectOnly ? undefined : bindingName !== null && bindingName !== void 0 ? bindingName : derivedName(options);
|
|
399
|
+
this.anyNameAnswers = anyNameAnswers(options);
|
|
91
400
|
}
|
|
92
401
|
/**
|
|
93
402
|
* Extract module name from a module specifier literal
|
|
94
403
|
*/
|
|
95
404
|
getModuleName(moduleSpecifier) {
|
|
96
|
-
var _a;
|
|
97
405
|
if (moduleSpecifier.kind !== java_1.J.Kind.Literal) {
|
|
98
406
|
return undefined;
|
|
99
407
|
}
|
|
100
|
-
return (
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Check if a method invocation is a require() call
|
|
104
|
-
*/
|
|
105
|
-
isRequireCall(methodInv) {
|
|
106
|
-
var _a;
|
|
107
|
-
return ((_a = methodInv.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
|
|
108
|
-
methodInv.name.simpleName === 'require';
|
|
408
|
+
return moduleNameOf(moduleSpecifier);
|
|
109
409
|
}
|
|
110
410
|
/**
|
|
111
411
|
* Determine the appropriate import style based on file type and existing imports
|
|
@@ -177,7 +477,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
177
477
|
const namedVar = varDecl.variables[0].element;
|
|
178
478
|
const initializer = (_a = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
|
|
179
479
|
if ((initializer === null || initializer === void 0 ? void 0 : initializer.kind) === java_1.J.Kind.MethodInvocation &&
|
|
180
|
-
|
|
480
|
+
isRequireCall(initializer)) {
|
|
181
481
|
hasCommonJSRequires = true;
|
|
182
482
|
}
|
|
183
483
|
}
|
|
@@ -246,12 +546,8 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
246
546
|
if (varDecl.variables.length === 1) {
|
|
247
547
|
const namedVar = varDecl.variables[0].element;
|
|
248
548
|
const initializer = (_b = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _b === void 0 ? void 0 : _b.element;
|
|
249
|
-
if ((initializer ===
|
|
250
|
-
|
|
251
|
-
const moduleName = this.getModuleNameFromRequire(initializer);
|
|
252
|
-
if (moduleName === this.module) {
|
|
253
|
-
return ImportStyle.CommonJS;
|
|
254
|
-
}
|
|
549
|
+
if (requiredModule(initializer) === this.module) {
|
|
550
|
+
return ImportStyle.CommonJS;
|
|
255
551
|
}
|
|
256
552
|
}
|
|
257
553
|
}
|
|
@@ -382,11 +678,11 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
382
678
|
const namedImports = importClause.namedBindings;
|
|
383
679
|
const existingElements = namedImports.elements.elements;
|
|
384
680
|
// Find the correct insertion position (alphabetical, case-insensitive)
|
|
385
|
-
const newName =
|
|
681
|
+
const newName = this.bindingName.toLowerCase();
|
|
386
682
|
let insertIndex = existingElements.findIndex(elem => {
|
|
387
|
-
var _a;
|
|
683
|
+
var _a, _b, _c;
|
|
388
684
|
if (((_a = elem.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.ImportSpecifier) {
|
|
389
|
-
const name =
|
|
685
|
+
const name = (_c = (_b = specifierBinding(elem.element)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : '';
|
|
390
686
|
return newName.localeCompare(name.toLowerCase()) < 0;
|
|
391
687
|
}
|
|
392
688
|
return false;
|
|
@@ -511,135 +807,40 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
511
807
|
* Check if the import matches what we're trying to add
|
|
512
808
|
*/
|
|
513
809
|
isMatchingImport(jsImport) {
|
|
514
|
-
var _a
|
|
515
|
-
// Check module specifier
|
|
810
|
+
var _a;
|
|
516
811
|
const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
517
|
-
if (!moduleSpecifier) {
|
|
518
|
-
return false;
|
|
519
|
-
}
|
|
520
|
-
const moduleName = this.getModuleName(moduleSpecifier);
|
|
521
|
-
if (moduleName !== this.module) {
|
|
812
|
+
if (!moduleSpecifier || this.getModuleName(moduleSpecifier) !== this.module) {
|
|
522
813
|
return false;
|
|
523
814
|
}
|
|
815
|
+
// A side-effect import is the clause-less one, and no import carrying bindings stands in
|
|
816
|
+
// for it — nor it for them.
|
|
524
817
|
const importClause = jsImport.importClause;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
// If we're trying to add a side-effect import and one already exists, it's a match
|
|
528
|
-
return this.sideEffectOnly;
|
|
818
|
+
if (!importClause || this.sideEffectOnly) {
|
|
819
|
+
return !importClause && this.sideEffectOnly;
|
|
529
820
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
// Check if the specific member or default import already exists
|
|
540
|
-
if (this.member === '*') {
|
|
541
|
-
// We're adding a namespace import, check if one exists
|
|
542
|
-
const namedBindings = importClause.namedBindings;
|
|
543
|
-
if (!namedBindings) {
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
// Namespace imports can be represented as J.Identifier or JS.Alias
|
|
547
|
-
if (namedBindings.kind === java_1.J.Kind.Identifier) {
|
|
548
|
-
const identifier = namedBindings;
|
|
549
|
-
return identifier.simpleName === this.alias;
|
|
550
|
-
}
|
|
551
|
-
else if (namedBindings.kind === tree_1.JS.Kind.Alias) {
|
|
552
|
-
const alias = namedBindings;
|
|
553
|
-
if (((_b = alias.alias) === null || _b === void 0 ? void 0 : _b.kind) === java_1.J.Kind.Identifier) {
|
|
554
|
-
return alias.alias.simpleName === this.alias;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
return false;
|
|
558
|
-
}
|
|
559
|
-
else if (this.member === undefined || this.member === 'default') {
|
|
560
|
-
// We're adding a default import, check if one exists
|
|
561
|
-
// For member === 'default', also verify the alias matches if specified
|
|
562
|
-
if (importClause.name === undefined) {
|
|
563
|
-
return false;
|
|
564
|
-
}
|
|
565
|
-
// If we have an alias, check that it matches
|
|
566
|
-
if (this.alias && ((_c = importClause.name.element) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
|
|
567
|
-
const existingName = importClause.name.element.simpleName;
|
|
568
|
-
return existingName === this.alias;
|
|
569
|
-
}
|
|
570
|
-
return true;
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
// We're adding a named import, check if it exists
|
|
574
|
-
const namedBindings = importClause.namedBindings;
|
|
575
|
-
if (!namedBindings) {
|
|
576
|
-
return false;
|
|
577
|
-
}
|
|
578
|
-
if (namedBindings.kind === tree_1.JS.Kind.NamedImports) {
|
|
579
|
-
const namedImports = namedBindings;
|
|
580
|
-
for (const elem of namedImports.elements.elements) {
|
|
581
|
-
if (((_d = elem.element) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.ImportSpecifier) {
|
|
582
|
-
const specifier = elem.element;
|
|
583
|
-
const importName = this.getImportName(specifier);
|
|
584
|
-
const aliasName = this.getImportAlias(specifier);
|
|
585
|
-
if (importName === this.member && aliasName === this.alias) {
|
|
586
|
-
return true;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
return false;
|
|
821
|
+
return importBindings(jsImport).some(binding => this.answeredBy(binding));
|
|
822
|
+
}
|
|
823
|
+
/** Whether a binding the file already has serves this request. */
|
|
824
|
+
answeredBy(binding) {
|
|
825
|
+
return binding.module === this.module &&
|
|
826
|
+
binding.member === memberName(this.member) &&
|
|
827
|
+
binding.typeOnly === this.typeOnly &&
|
|
828
|
+
(this.anyNameAnswers || binding.name === this.bindingName);
|
|
593
829
|
}
|
|
594
830
|
/**
|
|
595
831
|
* Check if this is a matching CommonJS require statement
|
|
596
832
|
*/
|
|
597
833
|
isMatchingRequire(varDecl) {
|
|
598
|
-
var _a
|
|
834
|
+
var _a;
|
|
599
835
|
if (varDecl.variables.length !== 1) {
|
|
600
836
|
return false;
|
|
601
837
|
}
|
|
602
838
|
const namedVar = varDecl.variables[0].element;
|
|
603
|
-
|
|
839
|
+
const module = requiredModule((_a = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element);
|
|
840
|
+
if (module !== this.module) {
|
|
604
841
|
return false;
|
|
605
842
|
}
|
|
606
|
-
|
|
607
|
-
if (!initializer || initializer.kind !== java_1.J.Kind.MethodInvocation) {
|
|
608
|
-
return false;
|
|
609
|
-
}
|
|
610
|
-
const methodInv = initializer;
|
|
611
|
-
if (!this.isRequireCall(methodInv)) {
|
|
612
|
-
return false;
|
|
613
|
-
}
|
|
614
|
-
const moduleName = this.getModuleNameFromRequire(methodInv);
|
|
615
|
-
if (moduleName !== this.module) {
|
|
616
|
-
return false;
|
|
617
|
-
}
|
|
618
|
-
// Check if the variable name matches what we're trying to add
|
|
619
|
-
const pattern = namedVar.name;
|
|
620
|
-
if ((this.member === undefined || this.member === 'default') && (pattern === null || pattern === void 0 ? void 0 : pattern.kind) === java_1.J.Kind.Identifier) {
|
|
621
|
-
// Default import style: const fs = require('fs')
|
|
622
|
-
// For member === 'default', also check the alias matches if specified
|
|
623
|
-
if (this.alias) {
|
|
624
|
-
const varName = pattern.simpleName;
|
|
625
|
-
return varName === this.alias;
|
|
626
|
-
}
|
|
627
|
-
return true;
|
|
628
|
-
}
|
|
629
|
-
else if (this.member !== undefined && this.member !== 'default' && (pattern === null || pattern === void 0 ? void 0 : pattern.kind) === tree_1.JS.Kind.ObjectBindingPattern) {
|
|
630
|
-
// Destructured import: const { member } = require('module')
|
|
631
|
-
const objectPattern = pattern;
|
|
632
|
-
for (const elem of objectPattern.bindings.elements) {
|
|
633
|
-
if (((_b = elem.element) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.BindingElement) {
|
|
634
|
-
const bindingElem = elem.element;
|
|
635
|
-
const name = (_c = bindingElem.name) === null || _c === void 0 ? void 0 : _c.simpleName;
|
|
636
|
-
if (name === (this.alias || this.member)) {
|
|
637
|
-
return true;
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
return false;
|
|
843
|
+
return requireBindings(namedVar.name, module).some(binding => this.answeredBy(binding));
|
|
643
844
|
}
|
|
644
845
|
/**
|
|
645
846
|
* Extract the module name from a class type by traversing the owningClass chain
|
|
@@ -754,7 +955,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
754
955
|
}
|
|
755
956
|
}
|
|
756
957
|
// Step 2: Look for references that match
|
|
757
|
-
const targetName = this.
|
|
958
|
+
const targetName = this.bindingName;
|
|
758
959
|
const targetModule = this.module;
|
|
759
960
|
let found = false;
|
|
760
961
|
const self = this;
|
|
@@ -872,21 +1073,27 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
872
1073
|
* Create a new import statement
|
|
873
1074
|
*/
|
|
874
1075
|
async createImportStatement(compilationUnit, insertionIndex, p) {
|
|
1076
|
+
var _a;
|
|
875
1077
|
// Determine the appropriate prefix (spacing before the import)
|
|
876
1078
|
const prefix = this.determineImportPrefix(compilationUnit, insertionIndex);
|
|
877
1079
|
// Create the module specifier
|
|
878
1080
|
// For side-effect imports, use emptySpace since space comes from LeftPadded.before
|
|
879
1081
|
// For regular imports with import clause, use emptySpace since space comes from LeftPadded.before
|
|
880
1082
|
// However, the printer expects the space after 'from' in the literal's prefix
|
|
881
|
-
// Note: value
|
|
1083
|
+
// Note: value is the unquoted module name; valueSource and unicodeEscapes are its printed form
|
|
1084
|
+
let valueSource = this.moduleValueSource;
|
|
1085
|
+
if (valueSource === undefined) {
|
|
1086
|
+
const quote = (_a = this.quoteStyle) !== null && _a !== void 0 ? _a : await detectQuote(compilationUnit);
|
|
1087
|
+
valueSource = `${quote}${this.module}${quote}`;
|
|
1088
|
+
}
|
|
882
1089
|
const moduleSpecifier = {
|
|
883
1090
|
id: (0, uuid_1.randomId)(),
|
|
884
1091
|
kind: java_1.J.Kind.Literal,
|
|
885
1092
|
prefix: this.sideEffectOnly ? java_1.emptySpace : java_1.singleSpace,
|
|
886
1093
|
markers: markers_1.emptyMarkers,
|
|
887
1094
|
value: this.module,
|
|
888
|
-
valueSource
|
|
889
|
-
unicodeEscapes:
|
|
1095
|
+
valueSource,
|
|
1096
|
+
unicodeEscapes: this.moduleUnicodeEscapes,
|
|
890
1097
|
type: undefined
|
|
891
1098
|
};
|
|
892
1099
|
let importClause;
|
|
@@ -912,7 +1119,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
912
1119
|
prefix: java_1.singleSpace,
|
|
913
1120
|
markers: markers_1.emptyMarkers,
|
|
914
1121
|
annotations: [],
|
|
915
|
-
simpleName: this.
|
|
1122
|
+
simpleName: this.bindingName,
|
|
916
1123
|
type: undefined,
|
|
917
1124
|
fieldType: undefined
|
|
918
1125
|
};
|
|
@@ -943,7 +1150,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
943
1150
|
prefix: java_1.singleSpace,
|
|
944
1151
|
markers: markers_1.emptyMarkers,
|
|
945
1152
|
annotations: [],
|
|
946
|
-
simpleName: this.
|
|
1153
|
+
simpleName: this.bindingName,
|
|
947
1154
|
type: undefined,
|
|
948
1155
|
fieldType: undefined
|
|
949
1156
|
};
|
|
@@ -1010,7 +1217,8 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
1010
1217
|
*/
|
|
1011
1218
|
createImportSpecifier() {
|
|
1012
1219
|
let specifier;
|
|
1013
|
-
|
|
1220
|
+
// An alias equal to the member says nothing `{member}` alone does not.
|
|
1221
|
+
if (this.bindingName !== this.member) {
|
|
1014
1222
|
// Aliased import: import { member as alias } from 'module'
|
|
1015
1223
|
const propertyName = {
|
|
1016
1224
|
id: (0, uuid_1.randomId)(),
|
|
@@ -1028,7 +1236,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
1028
1236
|
prefix: java_1.singleSpace,
|
|
1029
1237
|
markers: markers_1.emptyMarkers,
|
|
1030
1238
|
annotations: [],
|
|
1031
|
-
simpleName: this.
|
|
1239
|
+
simpleName: this.bindingName,
|
|
1032
1240
|
type: undefined,
|
|
1033
1241
|
fieldType: undefined
|
|
1034
1242
|
};
|
|
@@ -1113,52 +1321,276 @@ class AddImport extends visitor_1.JavaScriptVisitor {
|
|
|
1113
1321
|
// No imports found, insert at the beginning
|
|
1114
1322
|
return 0;
|
|
1115
1323
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1324
|
+
}
|
|
1325
|
+
exports.AddImport = AddImport;
|
|
1326
|
+
/**
|
|
1327
|
+
* The local name `jsImport` binds `member` of `module` to, or `undefined` where it binds
|
|
1328
|
+
* something else. `'default'` and an absent `member` both mean the default import, matching
|
|
1329
|
+
* {@link memberName}.
|
|
1330
|
+
*/
|
|
1331
|
+
function importBinds(jsImport, module, member) {
|
|
1332
|
+
var _a, _b;
|
|
1333
|
+
const specifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
|
|
1334
|
+
if ((specifier === null || specifier === void 0 ? void 0 : specifier.kind) !== java_1.J.Kind.Literal || specifier.value !== module) {
|
|
1335
|
+
return undefined;
|
|
1336
|
+
}
|
|
1337
|
+
const importClause = jsImport.importClause;
|
|
1338
|
+
if (!importClause) {
|
|
1339
|
+
return undefined;
|
|
1340
|
+
}
|
|
1341
|
+
const key = memberName(member);
|
|
1342
|
+
if (key === undefined) {
|
|
1343
|
+
const nameElem = (_b = importClause.name) === null || _b === void 0 ? void 0 : _b.element;
|
|
1344
|
+
return nameElem && (0, java_1.isIdentifier)(nameElem) ? nameElem.simpleName : undefined;
|
|
1345
|
+
}
|
|
1346
|
+
if (key === '*') {
|
|
1347
|
+
const namedBindings = importClause.namedBindings;
|
|
1348
|
+
return (namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.Alias && (0, java_1.isIdentifier)(namedBindings.alias)
|
|
1349
|
+
? namedBindings.alias.simpleName
|
|
1350
|
+
: undefined;
|
|
1351
|
+
}
|
|
1352
|
+
const namedBindings = importClause.namedBindings;
|
|
1353
|
+
if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) !== tree_1.JS.Kind.NamedImports) {
|
|
1354
|
+
return undefined;
|
|
1355
|
+
}
|
|
1356
|
+
for (const elem of namedBindings.elements.elements) {
|
|
1357
|
+
const specifierNode = elem.element.specifier;
|
|
1358
|
+
if (!namedSpecifierImports(specifierNode, key)) {
|
|
1359
|
+
continue;
|
|
1124
1360
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1361
|
+
if ((0, java_1.isIdentifier)(specifierNode)) {
|
|
1362
|
+
return specifierNode.simpleName;
|
|
1363
|
+
}
|
|
1364
|
+
const alias = specifierNode.alias;
|
|
1365
|
+
if ((0, java_1.isIdentifier)(alias)) {
|
|
1366
|
+
return alias.simpleName;
|
|
1128
1367
|
}
|
|
1129
|
-
return (_b = firstArg.value) === null || _b === void 0 ? void 0 : _b.toString();
|
|
1130
1368
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1369
|
+
return undefined;
|
|
1370
|
+
}
|
|
1371
|
+
/** Whether `specifier` imports the member `key`, under whatever local name it binds it to. */
|
|
1372
|
+
function namedSpecifierImports(specifier, key) {
|
|
1373
|
+
if ((0, java_1.isIdentifier)(specifier)) {
|
|
1374
|
+
return specifier.simpleName === key;
|
|
1375
|
+
}
|
|
1376
|
+
if (specifier.kind === tree_1.JS.Kind.Alias) {
|
|
1377
|
+
const propertyName = specifier.propertyName.element;
|
|
1378
|
+
return (0, java_1.isIdentifier)(propertyName) && propertyName.simpleName === key;
|
|
1379
|
+
}
|
|
1380
|
+
return false;
|
|
1381
|
+
}
|
|
1382
|
+
/** Whether the named specifier binding `key` carries its own inline `type`, as in `{type a, b}`. */
|
|
1383
|
+
function namedSpecifierIsTypeOnly(imp, key) {
|
|
1384
|
+
var _a;
|
|
1385
|
+
const namedBindings = (_a = imp.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings;
|
|
1386
|
+
if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) !== tree_1.JS.Kind.NamedImports) {
|
|
1387
|
+
return false;
|
|
1388
|
+
}
|
|
1389
|
+
for (const elem of namedBindings.elements.elements) {
|
|
1390
|
+
if (namedSpecifierImports(elem.element.specifier, key)) {
|
|
1391
|
+
return elem.element.importType.element;
|
|
1142
1392
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1393
|
+
}
|
|
1394
|
+
return false;
|
|
1395
|
+
}
|
|
1396
|
+
/** How many named specifiers `jsImport` carries, `0` for a default, namespace or side-effect import. */
|
|
1397
|
+
function namedImportCount(jsImport) {
|
|
1398
|
+
var _a;
|
|
1399
|
+
const namedBindings = (_a = jsImport.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings;
|
|
1400
|
+
return (namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.NamedImports ? namedBindings.elements.elements.length : 0;
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Whether `jsImport`'s clause binds exactly one thing — a default, a namespace, or one named
|
|
1404
|
+
* specifier. That is the only shape a module-only move can rewrite in place: whichever binding
|
|
1405
|
+
* `importBinds` already matched is this one, so nothing else the clause carries goes along with it.
|
|
1406
|
+
*/
|
|
1407
|
+
function isOnlyMember(jsImport) {
|
|
1408
|
+
var _a;
|
|
1409
|
+
const importClause = jsImport.importClause;
|
|
1410
|
+
if (!importClause) {
|
|
1411
|
+
return false;
|
|
1412
|
+
}
|
|
1413
|
+
const hasDefault = importClause.name !== undefined;
|
|
1414
|
+
const hasNamespace = ((_a = importClause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Alias;
|
|
1415
|
+
return (hasDefault ? 1 : 0) + (hasNamespace ? 1 : 0) + namedImportCount(jsImport) === 1;
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* The existing binding for `member` of `module`, read from `cu`'s own import statements — what
|
|
1419
|
+
* `maybeRebind` reads before committing to a `RebindImport` edit.
|
|
1420
|
+
*/
|
|
1421
|
+
function existingImportBinding(cu, module, member) {
|
|
1422
|
+
for (const stmt of cu.statements) {
|
|
1423
|
+
const element = stmt.element;
|
|
1424
|
+
if ((element === null || element === void 0 ? void 0 : element.kind) !== tree_1.JS.Kind.Import) {
|
|
1425
|
+
continue;
|
|
1426
|
+
}
|
|
1427
|
+
const localName = importBinds(element, module, member);
|
|
1428
|
+
if (localName !== undefined) {
|
|
1429
|
+
return { localName, onlyMemberOfStatement: isOnlyMember(element) };
|
|
1145
1430
|
}
|
|
1146
|
-
return '';
|
|
1147
1431
|
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1432
|
+
return undefined;
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Binds `member` under the name `local` already carries, so the file's references to it still
|
|
1436
|
+
* resolve. `local` itself becomes the alias, keeping the type attribution it holds, and the alias
|
|
1437
|
+
* takes its prefix: that whitespace separates the specifier from a `type` keyword before it.
|
|
1438
|
+
*/
|
|
1439
|
+
function aliasing(local, member) {
|
|
1440
|
+
const propertyName = {
|
|
1441
|
+
id: (0, uuid_1.randomId)(),
|
|
1442
|
+
kind: java_1.J.Kind.Identifier,
|
|
1443
|
+
prefix: java_1.emptySpace,
|
|
1444
|
+
markers: markers_1.emptyMarkers,
|
|
1445
|
+
annotations: [],
|
|
1446
|
+
simpleName: member,
|
|
1447
|
+
type: undefined,
|
|
1448
|
+
fieldType: undefined
|
|
1449
|
+
};
|
|
1450
|
+
return {
|
|
1451
|
+
id: (0, uuid_1.randomId)(),
|
|
1452
|
+
kind: tree_1.JS.Kind.Alias,
|
|
1453
|
+
prefix: local.prefix,
|
|
1454
|
+
markers: markers_1.emptyMarkers,
|
|
1455
|
+
propertyName: (0, java_1.rightPadded)(propertyName, java_1.singleSpace),
|
|
1456
|
+
alias: Object.assign(Object.assign({}, local), { prefix: java_1.singleSpace })
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Drops the binding for `member` from `jsImport`'s clause — the default, the namespace alias, or
|
|
1461
|
+
* one entry of the named list, whichever `member` names — keeping everything else the clause
|
|
1462
|
+
* binds. `ElementRemovalFormatter` carries the dropped binding's prefix onto whatever prints
|
|
1463
|
+
* next, the same way `RemoveImport` keeps formatting sane when trimming a list.
|
|
1464
|
+
*/
|
|
1465
|
+
function removeBinding(jsImport, member) {
|
|
1466
|
+
var _a;
|
|
1467
|
+
const importClause = jsImport.importClause;
|
|
1468
|
+
if (!importClause) {
|
|
1469
|
+
return jsImport;
|
|
1470
|
+
}
|
|
1471
|
+
const key = memberName(member);
|
|
1472
|
+
if (key === undefined) {
|
|
1473
|
+
if (!importClause.name) {
|
|
1474
|
+
return jsImport;
|
|
1159
1475
|
}
|
|
1160
|
-
|
|
1476
|
+
const namedBindings = importClause.namedBindings;
|
|
1477
|
+
if ((namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === tree_1.JS.Kind.NamedImports) {
|
|
1478
|
+
// `NamedImports` keeps the space before its own `{` on the container's `before`,
|
|
1479
|
+
// not on its own prefix, so the removed default's prefix has to land there instead.
|
|
1480
|
+
const namedImports = namedBindings;
|
|
1481
|
+
const updated = Object.assign(Object.assign({}, namedImports), { elements: Object.assign(Object.assign({}, namedImports.elements), { before: importClause.name.element.prefix }) });
|
|
1482
|
+
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { name: undefined, namedBindings: updated }) });
|
|
1483
|
+
}
|
|
1484
|
+
if (namedBindings) {
|
|
1485
|
+
const formatter = new java_1.ElementRemovalFormatter();
|
|
1486
|
+
formatter.markRemoved(importClause.name.element);
|
|
1487
|
+
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { name: undefined, namedBindings: formatter.processKept(namedBindings) }) });
|
|
1488
|
+
}
|
|
1489
|
+
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { name: undefined }) });
|
|
1490
|
+
}
|
|
1491
|
+
if (key === '*') {
|
|
1492
|
+
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { namedBindings: undefined }) });
|
|
1161
1493
|
}
|
|
1494
|
+
if (((_a = importClause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) !== tree_1.JS.Kind.NamedImports) {
|
|
1495
|
+
return jsImport;
|
|
1496
|
+
}
|
|
1497
|
+
const namedImports = importClause.namedBindings;
|
|
1498
|
+
const formatter = new java_1.ElementRemovalFormatter();
|
|
1499
|
+
const kept = [];
|
|
1500
|
+
for (const entry of namedImports.elements.elements) {
|
|
1501
|
+
if (namedSpecifierImports(entry.element.specifier, key)) {
|
|
1502
|
+
formatter.markRemoved(entry.element);
|
|
1503
|
+
}
|
|
1504
|
+
else {
|
|
1505
|
+
kept.push(Object.assign(Object.assign({}, entry), { element: formatter.processKept(entry.element) }));
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
if (kept.length === 0) {
|
|
1509
|
+
// An emptied brace list still prints, as `import D, {} from "m"`, so it goes with its
|
|
1510
|
+
// last member; the caller drops the whole statement when no default remains either.
|
|
1511
|
+
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { namedBindings: undefined }) });
|
|
1512
|
+
}
|
|
1513
|
+
const updatedNamedImports = Object.assign(Object.assign({}, namedImports), { elements: Object.assign(Object.assign({}, namedImports.elements), { elements: kept }) });
|
|
1514
|
+
return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { namedBindings: updatedNamedImports }) });
|
|
1162
1515
|
}
|
|
1163
|
-
|
|
1516
|
+
/**
|
|
1517
|
+
* Moves the binding `from` names to `to`, keeping the local name it already had. In place when
|
|
1518
|
+
* the statement that carries it binds nothing else — module and member specifier rewritten there
|
|
1519
|
+
* directly; otherwise the old specifier drops and {@link bindImport} queues the replacement,
|
|
1520
|
+
* aliased to the preserved name.
|
|
1521
|
+
*
|
|
1522
|
+
* Not built on `RemoveImport`/`maybeUnbind`: those only drop a binding once nothing references
|
|
1523
|
+
* it, but a rebind moves one that is still in use — removal here has to be unconditional.
|
|
1524
|
+
*/
|
|
1525
|
+
class RebindImport extends visitor_1.JavaScriptVisitor {
|
|
1526
|
+
constructor(from, to, localName) {
|
|
1527
|
+
super();
|
|
1528
|
+
this.from = from;
|
|
1529
|
+
this.to = to;
|
|
1530
|
+
this.localName = localName;
|
|
1531
|
+
this.transformedInPlace = false;
|
|
1532
|
+
this.typeOnly = false;
|
|
1533
|
+
}
|
|
1534
|
+
async visitJsCompilationUnit(cu, p) {
|
|
1535
|
+
const visited = await super.visitJsCompilationUnit(cu, p);
|
|
1536
|
+
if (!this.transformedInPlace) {
|
|
1537
|
+
bindImport(this, {
|
|
1538
|
+
module: this.to.module,
|
|
1539
|
+
member: this.to.member,
|
|
1540
|
+
alias: this.localName,
|
|
1541
|
+
typeOnly: this.typeOnly,
|
|
1542
|
+
onlyIfReferenced: false
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
return visited;
|
|
1546
|
+
}
|
|
1547
|
+
async visitImportDeclaration(jsImport, p) {
|
|
1548
|
+
var _a, _b;
|
|
1549
|
+
const imp = await super.visitImportDeclaration(jsImport, p);
|
|
1550
|
+
const key = memberName(this.from.member);
|
|
1551
|
+
if (importBinds(imp, this.from.module, this.from.member) === undefined) {
|
|
1552
|
+
return imp;
|
|
1553
|
+
}
|
|
1554
|
+
// A moved named specifier's own inline `type` marks it type-only even where the clause
|
|
1555
|
+
// it's leaving is not — the replacement needs the same answer to stay type-safe.
|
|
1556
|
+
this.typeOnly = ((_b = (_a = imp.importClause) === null || _a === void 0 ? void 0 : _a.typeOnly) !== null && _b !== void 0 ? _b : false) ||
|
|
1557
|
+
(key !== undefined && key !== '*' && namedSpecifierIsTypeOnly(imp, key));
|
|
1558
|
+
if (!isOnlyMember(imp)) {
|
|
1559
|
+
return removeBinding(imp, this.from.member);
|
|
1560
|
+
}
|
|
1561
|
+
this.transformedInPlace = true;
|
|
1562
|
+
return (0, mutative_1.create)(imp, draft => {
|
|
1563
|
+
var _a;
|
|
1564
|
+
const literal = draft.moduleSpecifier.element;
|
|
1565
|
+
literal.value = this.to.module;
|
|
1566
|
+
const originalSource = literal.valueSource || `"${this.from.module}"`;
|
|
1567
|
+
const quoteChar = originalSource.startsWith("'") ? "'" : '"';
|
|
1568
|
+
literal.valueSource = `${quoteChar}${this.to.module}${quoteChar}`;
|
|
1569
|
+
// A named specifier's local name has to stay put in the source, since it is what the
|
|
1570
|
+
// rest of the file already reads; default and namespace imports carry that name on
|
|
1571
|
+
// the clause itself, which needs no edit for a module-only move.
|
|
1572
|
+
const toKey = memberName(this.to.member);
|
|
1573
|
+
if (key !== undefined && key !== '*' && toKey !== undefined && toKey !== key) {
|
|
1574
|
+
const importClause = draft.importClause;
|
|
1575
|
+
if (((_a = importClause === null || importClause === void 0 ? void 0 : importClause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.NamedImports) {
|
|
1576
|
+
const namedImports = importClause.namedBindings;
|
|
1577
|
+
for (const elem of namedImports.elements.elements) {
|
|
1578
|
+
const specifier = elem.element;
|
|
1579
|
+
if (specifier.specifier.kind === java_1.J.Kind.Identifier && specifier.specifier.simpleName === key) {
|
|
1580
|
+
specifier.specifier = aliasing(specifier.specifier, toKey);
|
|
1581
|
+
}
|
|
1582
|
+
else if (specifier.specifier.kind === tree_1.JS.Kind.Alias) {
|
|
1583
|
+
const aliasNode = specifier.specifier;
|
|
1584
|
+
const propertyName = aliasNode.propertyName.element;
|
|
1585
|
+
if (propertyName.kind === java_1.J.Kind.Identifier && propertyName.simpleName === key) {
|
|
1586
|
+
propertyName.simpleName = toKey;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
exports.RebindImport = RebindImport;
|
|
1164
1596
|
//# sourceMappingURL=add-import.js.map
|