@@ -28,9 +28,12 @@ module.exports = {
28
28
}
29
29
30
30
if (
31
+ // no specifiers (import type {} from '') have no specifiers to mark as inline
31
32
node . specifiers . length === 0 ||
32
33
( node . specifiers . length === 1 &&
34
+ // default imports are both "inline" and "top-level"
33
35
( node . specifiers [ 0 ] . type === 'ImportDefaultSpecifier' ||
36
+ // namespace imports are both "inline" and "top-level"
34
37
node . specifiers [ 0 ] . type === 'ImportNamespaceSpecifier' ) )
35
38
) {
36
39
return ;
@@ -42,16 +45,19 @@ module.exports = {
42
45
data : {
43
46
kind : node . importKind ,
44
47
} ,
45
- * fix ( fixer ) {
46
- const kindToken = sourceCode . getFirstToken ( node , { skip : 1 } ) ;
48
+ fix ( fixer ) {
49
+ const fixes = [ ] ;
47
50
51
+ const kindToken = sourceCode . getFirstToken ( node , { skip : 1 } ) ;
48
52
if ( kindToken ) {
49
- yield fixer . remove ( kindToken ) ;
53
+ fixes . push ( fixer . remove ( kindToken ) ) ;
50
54
}
51
55
52
56
for ( const specifier of node . specifiers ) {
53
- yield fixer . insertTextBefore ( specifier , `${ node . importKind } ` ) ;
57
+ fixes . push ( fixer . insertTextBefore ( specifier , `${ node . importKind } ` ) ) ;
54
58
}
59
+
60
+ return fixes ;
55
61
} ,
56
62
} ) ;
57
63
} ,
@@ -62,30 +68,38 @@ module.exports = {
62
68
return {
63
69
ImportDeclaration ( node ) {
64
70
if (
71
+ // already top-level is valid
65
72
node . importKind === 'type' ||
66
73
node . importKind === 'typeof' ||
74
+ // no specifiers (import {} from '') cannot have inline - so is valid
67
75
node . specifiers . length === 0 ||
68
76
( node . specifiers . length === 1 &&
77
+ // default imports are both "inline" and "top-level"
69
78
( node . specifiers [ 0 ] . type === 'ImportDefaultSpecifier' ||
79
+ // namespace imports are both "inline" and "top-level"
70
80
node . specifiers [ 0 ] . type === 'ImportNamespaceSpecifier' ) )
71
81
) {
72
82
return ;
73
83
}
74
84
75
85
const typeSpecifiers = [ ] ;
76
86
const typeofSpecifiers = [ ] ;
87
+ const valueSpecifiers = [ ] ;
88
+ let defaultSpecifier = null ;
77
89
for ( const specifier of node . specifiers ) {
78
- // TODO - remove
79
- if ( specifier . type !== 'ImportSpecifier' ) {
90
+ if ( specifier . type === 'ImportDefaultSpecifier' ) {
91
+ defaultSpecifier = specifier ;
92
+ continue ;
93
+ } else if ( specifier . type !== 'ImportSpecifier' ) {
80
94
continue ;
81
95
}
82
96
83
97
if ( specifier . importKind === 'type' ) {
84
98
typeSpecifiers . push ( specifier ) ;
85
99
} else if ( specifier . importKind === 'typeof' ) {
86
100
typeofSpecifiers . push ( specifier ) ;
87
- } else {
88
- continue ;
101
+ } else if ( specifier . importKind === 'value' || specifier . importKind == null ) {
102
+ valueSpecifiers . push ( specifier ) ;
89
103
}
90
104
}
91
105
@@ -111,8 +125,8 @@ module.exports = {
111
125
data : {
112
126
kind : kind . join ( '/' ) ,
113
127
} ,
114
- * fix ( fixer ) {
115
- yield fixer . replaceText ( node , newImports ) ;
128
+ fix ( fixer ) {
129
+ return fixer . replaceText ( node , newImports ) ;
116
130
} ,
117
131
} ) ;
118
132
} else {
@@ -124,25 +138,59 @@ module.exports = {
124
138
data : {
125
139
kind : specifier . importKind ,
126
140
} ,
127
- * fix ( fixer ) {
128
- // remove just the specifiers and insert the new imports after
129
- yield * removeSpecifiers ( typeSpecifiers ) ;
130
- yield * removeSpecifiers ( typeofSpecifiers ) ;
131
- yield fixer . insertTextAfter ( node , `\n${ newImports } ` ) ;
132
-
133
- function * removeSpecifiers (
134
- specifiers ,
135
- ) {
141
+ fix ( fixer ) {
142
+ const fixes = [ ] ;
143
+
144
+ // if there are no value specifiers, then the other report fixer will be called, not this one
145
+
146
+ if ( valueSpecifiers . length > 0 ) {
147
+ // import { Value, type Type } from 'mod';
148
+
149
+ // we can just remove the type specifiers
150
+ removeSpecifiers ( typeSpecifiers ) ;
151
+ removeSpecifiers ( typeofSpecifiers ) ;
152
+
153
+ // make the import nicely formatted by also removing the trailing comma after the last value import
154
+ // eg
155
+ // import { Value, type Type } from 'mod';
156
+ // to
157
+ // import { Value } from 'mod';
158
+ // not
159
+ // import { Value, } from 'mod';
160
+ const maybeComma = sourceCode . getTokenAfter ( valueSpecifiers [ valueSpecifiers . length - 1 ] ) ;
161
+ if ( isComma ( maybeComma ) ) {
162
+ fixes . push ( fixer . remove ( maybeComma ) ) ;
163
+ }
164
+ } else if ( defaultSpecifier ) {
165
+ // import Default, { type Type } from 'mod';
166
+
167
+ // remove the entire curly block so we don't leave an empty one behind
168
+ // NOTE - the default specifier *must* be the first specifier always!
169
+ // so a comma exists that we also have to clean up or else it's bad syntax
170
+ const comma = sourceCode . getTokenAfter ( defaultSpecifier , isComma ) ;
171
+ const closingBrace = sourceCode . getTokenAfter (
172
+ node . specifiers [ node . specifiers . length - 1 ] ,
173
+ token => token . type === 'Punctuator' && token . value === '}' ,
174
+ ) ;
175
+ fixes . push ( fixer . removeRange ( [
176
+ comma . range [ 0 ] ,
177
+ closingBrace . range [ 1 ] ,
178
+ ] ) ) ;
179
+ }
180
+
181
+ // insert the new imports after the old declaration
182
+ fixes . push ( fixer . insertTextAfter ( node , `\n${ newImports } ` ) ) ;
183
+
184
+ return fixes ;
185
+
186
+ function removeSpecifiers ( specifiers ) {
136
187
for ( const specifier of specifiers ) {
137
188
// remove the trailing comma
138
- const comma = sourceCode . getTokenAfter (
139
- specifier ,
140
- token => token . type === 'Punctuator' && token . value === ',' ,
141
- ) ;
189
+ const comma = sourceCode . getTokenAfter ( specifier , isComma ) ;
142
190
if ( comma ) {
143
- yield fixer . remove ( comma ) ;
191
+ fixes . push ( fixer . remove ( comma ) ) ;
144
192
}
145
- yield fixer . remove ( specifier ) ;
193
+ fixes . push ( fixer . remove ( specifier ) ) ;
146
194
}
147
195
}
148
196
} ,
@@ -172,3 +220,8 @@ module.exports = {
172
220
} ;
173
221
} ,
174
222
} ;
223
+
224
+ function isComma ( token ) {
225
+ return token . type === 'Punctuator' && token . value === ',' ;
226
+ }
227
+
0 commit comments