@@ -5,6 +5,8 @@ const methodSelector = require('./utils/method-selector');
5
5
const needsSemicolon = require ( './utils/needs-semicolon' ) ;
6
6
const getParentheses = require ( './utils/get-parentheses' ) ;
7
7
const shouldAddParenthesesToSpreadElementArgument = require ( './utils/should-add-parentheses-to-spread-element-argument' ) ;
8
+ const replaceNodeOrTokenAndSpacesBefore = require ( './utils/replace-node-or-token-and-spaces-before' ) ;
9
+ const removeSpacesAfter = require ( './utils/remove-spaces-after' ) ;
8
10
9
11
const ERROR_ARRAY_FROM = 'array-from' ;
10
12
const ERROR_ARRAY_CONCAT = 'array-concat' ;
@@ -230,28 +232,63 @@ function getConcatFixableArguments(argumentsList, scope) {
230
232
return fixableArguments ;
231
233
}
232
234
235
+ function fixArrayFrom ( node , sourceCode ) {
236
+ const [ object ] = node . arguments ;
237
+
238
+ function getObjectText ( ) {
239
+ if ( isArrayLiteral ( object ) ) {
240
+ return sourceCode . getText ( object ) ;
241
+ }
242
+
243
+ const [ start , end ] = getParenthesizedRange ( object , sourceCode ) ;
244
+ let text = sourceCode . text . slice ( start , end ) ;
245
+
246
+ if (
247
+ ! isParenthesized ( object , sourceCode ) &&
248
+ shouldAddParenthesesToSpreadElementArgument ( object )
249
+ ) {
250
+ text = `(${ text } )` ;
251
+ }
252
+
253
+ return `[...${ text } ]` ;
254
+ }
255
+
256
+ function * removeObject ( fixer ) {
257
+ yield * replaceNodeOrTokenAndSpacesBefore ( object , '' , fixer , sourceCode ) ;
258
+ const commaToken = sourceCode . getTokenAfter ( object , isCommaToken ) ;
259
+ yield * replaceNodeOrTokenAndSpacesBefore ( commaToken , '' , fixer , sourceCode ) ;
260
+ yield removeSpacesAfter ( commaToken , sourceCode , fixer ) ;
261
+ }
262
+
263
+ return function * ( fixer ) {
264
+ // Fixed code always starts with `[`
265
+ if ( needsSemicolon ( sourceCode . getTokenBefore ( node ) , sourceCode , '[' ) ) {
266
+ yield fixer . insertTextBefore ( node , ';' ) ;
267
+ }
268
+
269
+ const objectText = getObjectText ( ) ;
270
+
271
+ if ( node . arguments . length === 1 ) {
272
+ yield fixer . replaceText ( node , objectText ) ;
273
+ return ;
274
+ }
275
+
276
+ // `Array.from(object, mapFunction, thisArgument)` -> `[...object].map(mapFunction, thisArgument)`
277
+ yield fixer . replaceText ( node . callee . object , objectText ) ;
278
+ yield fixer . replaceText ( node . callee . property , 'map' ) ;
279
+ yield * removeObject ( fixer ) ;
280
+ } ;
281
+ }
282
+
233
283
const create = context => {
234
284
const sourceCode = context . getSourceCode ( ) ;
235
- const getSource = node => sourceCode . getText ( node ) ;
236
285
237
286
return {
238
287
[ arrayFromCallSelector ] ( node ) {
239
288
context . report ( {
240
289
node,
241
290
messageId : ERROR_ARRAY_FROM ,
242
- fix : fixer => {
243
- const [ arrayLikeArgument , mapFn , thisArgument ] = node . arguments . map ( node => getSource ( node ) ) ;
244
- let replacement = `${
245
- needsSemicolon ( sourceCode . getTokenBefore ( node ) , sourceCode ) ? ';' : ''
246
- } [...${ arrayLikeArgument } ]`;
247
-
248
- if ( mapFn ) {
249
- const mapArguments = [ mapFn , thisArgument ] . filter ( Boolean ) ;
250
- replacement += `.map(${ mapArguments . join ( ', ' ) } )` ;
251
- }
252
-
253
- return fixer . replaceText ( node , replacement ) ;
254
- }
291
+ fix : fixArrayFrom ( node , sourceCode )
255
292
} ) ;
256
293
} ,
257
294
[ arrayConcatCallSelector ] ( node ) {
0 commit comments