Skip to content

Commit 0b9dc64

Browse files
committed
Refactor updating imports
1 parent 898959c commit 0b9dc64

File tree

5 files changed

+135
-113
lines changed

5 files changed

+135
-113
lines changed

polaris-migrator/src/migrations/replace-text-component/replace-text-component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {replaceOther} from './steps/replace-other';
77
import {replaceTextStyle} from './steps/replace-text-style';
88

99
export interface MigrationOptions extends Options {
10-
relative: string;
10+
relative: boolean;
1111
}
1212

1313
export default function replaceTextComponent(

polaris-migrator/src/migrations/replace-text-component/steps/replace-display-text.ts

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,9 @@ import {
77
insertJSXAttribute,
88
} from '../../../utilities/jsx';
99
import {
10-
renameImportSpecifier,
1110
getImportSpecifierName,
12-
hasImportSpecifier,
13-
removeImportSpecifier,
14-
getImportSourcePaths,
15-
renameImportDeclaration,
16-
removeImportDeclaration,
11+
normalizeImportSourcePaths,
12+
updateImports,
1713
} from '../../../utilities/imports';
1814
import type {MigrationOptions} from '../replace-text-component';
1915

@@ -32,10 +28,10 @@ export function replaceDisplayText<NodeType = ASTNode>(
3228
source: Collection<NodeType>,
3329
options: MigrationOptions,
3430
) {
35-
const sourcePaths = getImportSourcePaths(j, source, {
36-
relative: Boolean(options.relative),
37-
currentFileName: 'DisplayText',
38-
nextFileName: 'Text',
31+
const sourcePaths = normalizeImportSourcePaths(j, source, {
32+
relative: options.relative,
33+
from: 'DisplayText',
34+
to: 'Text',
3935
});
4036

4137
if (!sourcePaths) return;
@@ -44,18 +40,12 @@ export function replaceDisplayText<NodeType = ASTNode>(
4440
getImportSpecifierName(j, source, 'DisplayText', sourcePaths.current) ||
4541
'DisplayText';
4642

47-
if (hasImportSpecifier(j, source, 'Text', sourcePaths.next)) {
48-
if (options.relative) {
49-
removeImportDeclaration(j, source, sourcePaths.current);
50-
} else {
51-
removeImportSpecifier(j, source, 'DisplayText', sourcePaths.current);
52-
}
53-
} else {
54-
if (options.relative) {
55-
renameImportDeclaration(j, source, sourcePaths.current, sourcePaths.next);
56-
}
57-
renameImportSpecifier(j, source, 'DisplayText', 'Text', sourcePaths.next);
58-
}
43+
updateImports(j, source, {
44+
fromSpecifier: 'DisplayText',
45+
toSpecifier: 'Text',
46+
fromSourcePath: sourcePaths.from,
47+
toSourcePath: sourcePaths.to,
48+
});
5949

6050
source.findJSXElements(localElementName).forEach((element) => {
6151
replaceJSXElement(j, element, 'Text');

polaris-migrator/src/migrations/replace-text-component/steps/replace-other.ts

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,9 @@ import {
77
insertJSXAttribute,
88
} from '../../../utilities/jsx';
99
import {
10-
renameImportSpecifier,
1110
getImportSpecifierName,
12-
hasImportSpecifier,
13-
removeImportSpecifier,
14-
getImportSourcePaths,
15-
removeImportDeclaration,
16-
renameImportDeclaration,
11+
normalizeImportSourcePaths,
12+
updateImports,
1713
} from '../../../utilities/imports';
1814
import type {MigrationOptions} from '../replace-text-component';
1915

@@ -44,38 +40,27 @@ export function replaceOther<NodeType = ASTNode>(
4440
source: Collection<NodeType>,
4541
options: MigrationOptions,
4642
) {
47-
const relative = Boolean(options.relative);
43+
const relative = options.relative;
4844

4945
Object.entries(components).forEach(([componentName, {variant, as}]) => {
50-
const sourcePaths = getImportSourcePaths(j, source, {
46+
const sourcePaths = normalizeImportSourcePaths(j, source, {
5147
relative,
52-
currentFileName: componentName,
53-
nextFileName: 'Text',
48+
from: componentName,
49+
to: 'Text',
5450
});
5551

5652
if (!sourcePaths) return;
5753

5854
const localElementName =
59-
getImportSpecifierName(j, source, componentName, sourcePaths.current) ||
55+
getImportSpecifierName(j, source, componentName, sourcePaths.from) ||
6056
componentName;
6157

62-
if (hasImportSpecifier(j, source, 'Text', sourcePaths.next)) {
63-
if (options.relative) {
64-
removeImportDeclaration(j, source, sourcePaths.current);
65-
} else {
66-
removeImportSpecifier(j, source, componentName, sourcePaths.current);
67-
}
68-
} else {
69-
if (options.relative) {
70-
renameImportDeclaration(
71-
j,
72-
source,
73-
sourcePaths.current,
74-
sourcePaths.next,
75-
);
76-
}
77-
renameImportSpecifier(j, source, componentName, 'Text', sourcePaths.next);
78-
}
58+
updateImports(j, source, {
59+
fromSpecifier: componentName,
60+
toSpecifier: 'Text',
61+
fromSourcePath: sourcePaths.from,
62+
toSourcePath: sourcePaths.to,
63+
});
7964

8065
source.findJSXElements(localElementName).forEach((element) => {
8166
replaceJSXElement(j, element, 'Text');

polaris-migrator/src/migrations/replace-text-component/steps/replace-text-style.ts

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,11 @@ import {
1010
} from '../../../utilities/jsx';
1111
import {
1212
insertImportSpecifier,
13-
renameImportSpecifier,
1413
getImportSpecifierName,
1514
hasImportSpecifier,
16-
removeImportSpecifier,
17-
getImportSourcePaths,
18-
renameImportDeclaration,
19-
removeImportDeclaration,
2015
insertImportDeclaration,
16+
normalizeImportSourcePaths,
17+
updateImports,
2118
} from '../../../utilities/imports';
2219
import type {MigrationOptions} from '../replace-text-component';
2320

@@ -38,30 +35,24 @@ export function replaceTextStyle<NodeType = ASTNode>(
3835
source: Collection<NodeType>,
3936
options: MigrationOptions,
4037
) {
41-
const sourcePaths = getImportSourcePaths(j, source, {
42-
relative: Boolean(options.relative),
43-
currentFileName: 'TextStyle',
44-
nextFileName: 'Text',
38+
const sourcePaths = normalizeImportSourcePaths(j, source, {
39+
relative: options.relative,
40+
from: 'TextStyle',
41+
to: 'Text',
4542
});
4643

4744
if (!sourcePaths) return;
4845

4946
const localElementName =
50-
getImportSpecifierName(j, source, 'TextStyle', sourcePaths.current) ||
47+
getImportSpecifierName(j, source, 'TextStyle', sourcePaths.from) ||
5148
'TextStyle';
5249

53-
if (hasImportSpecifier(j, source, 'Text', sourcePaths.next)) {
54-
if (options.relative) {
55-
removeImportDeclaration(j, source, sourcePaths.current);
56-
} else {
57-
removeImportSpecifier(j, source, 'TextStyle', sourcePaths.current);
58-
}
59-
} else {
60-
if (options.relative) {
61-
renameImportDeclaration(j, source, sourcePaths.current, sourcePaths.next);
62-
}
63-
renameImportSpecifier(j, source, 'TextStyle', 'Text', sourcePaths.next);
64-
}
50+
updateImports(j, source, {
51+
fromSpecifier: 'TextStyle',
52+
toSpecifier: 'Text',
53+
fromSourcePath: sourcePaths.from,
54+
toSourcePath: sourcePaths.to,
55+
});
6556

6657
source.findJSXElements(localElementName).forEach((element) => {
6758
replaceJSXElement(j, element, 'Text');
@@ -72,7 +63,7 @@ export function replaceTextStyle<NodeType = ASTNode>(
7263
const currentValue = literal.node.value as keyof typeof variationMap;
7364
if (currentValue === 'code') {
7465
const inlineTextSourcePath = options.relative
75-
? sourcePaths.current.replace('TextStyle', 'InlineCode')
66+
? sourcePaths.from.replace('TextStyle', 'InlineCode')
7667
: '@shopify/polaris';
7768

7869
if (
@@ -84,7 +75,7 @@ export function replaceTextStyle<NodeType = ASTNode>(
8475
source,
8576
'InlineCode',
8677
inlineTextSourcePath,
87-
sourcePaths.next,
78+
sourcePaths.to,
8879
);
8980
} else {
9081
insertImportSpecifier(

polaris-migrator/src/utilities/imports.ts

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -76,41 +76,17 @@ export function insertImportDeclaration(
7676
sourcePath: string,
7777
afterSourcePath: string,
7878
) {
79-
getImportDeclaration(j, source, afterSourcePath).insertAfter(
80-
j.importDeclaration.from({
81-
source: j.literal(sourcePath),
82-
specifiers: [j.importSpecifier(j.identifier(importSpecifier))],
83-
}),
84-
);
85-
}
86-
87-
export function getImportSourcePaths(
88-
j: core.JSCodeshift,
89-
source: Collection<any>,
90-
options = {
91-
relative: false,
92-
currentFileName: '',
93-
nextFileName: '',
94-
},
95-
) {
96-
const {relative, currentFileName, nextFileName} = options;
97-
const sourcePaths = {
98-
current: '@shopify/polaris',
99-
next: '@shopify/polaris',
100-
};
101-
102-
if (relative) {
103-
sourcePaths.current =
104-
getRelativeImportDeclarationValue(j, source, currentFileName) || '';
105-
106-
if (!sourcePaths.current) return null;
107-
108-
sourcePaths.next =
109-
getRelativeImportDeclarationValue(j, source, nextFileName) ||
110-
sourcePaths.current.replace(currentFileName, nextFileName);
79+
const isSameModuleSpecifier = sourcePath === afterSourcePath;
80+
if (isSameModuleSpecifier) {
81+
insertImportSpecifier(j, source, sourcePath, importSpecifier);
82+
} else {
83+
getImportDeclaration(j, source, afterSourcePath).insertAfter(
84+
j.importDeclaration.from({
85+
source: j.literal(sourcePath),
86+
specifiers: [j.importSpecifier(j.identifier(importSpecifier))],
87+
}),
88+
);
11189
}
112-
113-
return sourcePaths;
11490
}
11591

11692
export function getDefaultImportSpecifier(
@@ -152,17 +128,26 @@ export function hasDefaultImportSpecifier(
152128
return Boolean(getDefaultImportSpecifier(j, source, sourcePath).length);
153129
}
154130

155-
export function getImportSpecifier(
131+
export function getImportAllSpecifiers(
156132
j: core.JSCodeshift,
157133
source: Collection<any>,
158-
specifier: string,
159134
sourcePath: string,
160135
) {
161136
return source
162137
.find(j.ImportDeclaration)
163138
.filter((path) => path.node.source.value === sourcePath)
164-
.find(j.ImportSpecifier)
165-
.filter((path) => path.value.imported.name === specifier);
139+
.find(j.ImportSpecifier);
140+
}
141+
142+
export function getImportSpecifier(
143+
j: core.JSCodeshift,
144+
source: Collection<any>,
145+
specifier: string,
146+
sourcePath: string,
147+
) {
148+
return getImportAllSpecifiers(j, source, sourcePath).filter(
149+
(path) => path.value.imported.name === specifier,
150+
);
166151
}
167152

168153
export function getImportSpecifierName(
@@ -176,6 +161,14 @@ export function getImportSpecifierName(
176161
return specifiers.length > 0 ? specifiers.nodes()[0]!.local!.name : null;
177162
}
178163

164+
export function hasImportSpecifiers(
165+
j: core.JSCodeshift,
166+
source: Collection<any>,
167+
sourcePath: string,
168+
) {
169+
return Boolean(getImportAllSpecifiers(j, source, sourcePath)?.length);
170+
}
171+
179172
export function hasImportSpecifier(
180173
j: core.JSCodeshift,
181174
source: Collection<any>,
@@ -225,3 +218,66 @@ export function removeImportSpecifier(
225218
) {
226219
getImportSpecifier(j, source, specifier, sourcePath).remove();
227220
}
221+
222+
export function normalizeImportSourcePaths(
223+
j: core.JSCodeshift,
224+
source: Collection<any>,
225+
options = {
226+
relative: false,
227+
from: '',
228+
to: '',
229+
},
230+
) {
231+
const {relative, from, to} = options;
232+
const sourcePaths = {
233+
from: '@shopify/polaris',
234+
to: '@shopify/polaris',
235+
};
236+
237+
if (relative) {
238+
sourcePaths.from = getRelativeImportDeclarationValue(j, source, from) || '';
239+
240+
if (!sourcePaths.from) return null;
241+
242+
sourcePaths.to =
243+
getRelativeImportDeclarationValue(j, source, to) ||
244+
sourcePaths.from.replace(from, to);
245+
}
246+
247+
return sourcePaths;
248+
}
249+
250+
export function updateImports(
251+
j: core.JSCodeshift,
252+
source: Collection<any>,
253+
options: {
254+
fromSpecifier: string;
255+
toSpecifier: string;
256+
fromSourcePath: string;
257+
toSourcePath: string;
258+
},
259+
) {
260+
const {fromSpecifier, toSpecifier, fromSourcePath, toSourcePath} = options;
261+
262+
// Insert new import
263+
if (!hasImportDeclaration(j, source, toSourcePath)) {
264+
insertImportDeclaration(
265+
j,
266+
source,
267+
toSpecifier,
268+
toSourcePath,
269+
fromSourcePath,
270+
);
271+
}
272+
if (!hasImportSpecifier(j, source, toSpecifier, toSourcePath)) {
273+
insertImportSpecifier(j, source, toSpecifier, toSourcePath);
274+
}
275+
276+
// Remove old import
277+
if (hasImportSpecifier(j, source, fromSpecifier, fromSourcePath)) {
278+
removeImportSpecifier(j, source, fromSpecifier, fromSourcePath);
279+
}
280+
if (!hasImportSpecifiers(j, source, fromSourcePath)) {
281+
removeImportDeclaration(j, source, fromSourcePath);
282+
}
283+
}

0 commit comments

Comments
 (0)