From 49c4acf6f3a15d1c972c6c84f54a9793a269b7be Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Thu, 5 Mar 2020 21:29:09 +0800 Subject: [PATCH] `prefer-spread`: Insert semicolon if needed (#578) --- rules/prefer-spread.js | 29 ++++++++++++++++++++++-- test/integration/test.js | 4 +--- test/prefer-spread.js | 48 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/rules/prefer-spread.js b/rules/prefer-spread.js index 1809b97b00..e00d63ab11 100644 --- a/rules/prefer-spread.js +++ b/rules/prefer-spread.js @@ -14,7 +14,32 @@ const selector = [ ].join(''); const create = context => { - const getSource = node => context.getSourceCode().getText(node); + const sourceCode = context.getSourceCode(); + const getSource = node => sourceCode.getText(node); + + const needsSemicolon = node => { + const tokenBefore = sourceCode.getTokenBefore(node); + + if (tokenBefore) { + const {type, value} = tokenBefore; + if (type === 'Punctuator') { + if (value === ';') { + return false; + } + + if (value === ']' || value === ')') { + return true; + } + } + + const lastBlockNode = sourceCode.getNodeByRangeIndex(tokenBefore.range[0]); + if (lastBlockNode && lastBlockNode.type === 'ObjectExpression') { + return true; + } + } + + return false; + }; return { [selector](node) { @@ -23,7 +48,7 @@ const create = context => { message: 'Prefer the spread operator over `Array.from()`.', fix: fixer => { const [arrayLikeArgument, mapFn, thisArgument] = node.arguments.map(getSource); - let replacement = `[...${arrayLikeArgument}]`; + let replacement = `${needsSemicolon(node) ? ';' : ''}[...${arrayLikeArgument}]`; if (mapFn) { const mapArguments = [mapFn, thisArgument].filter(Boolean); diff --git a/test/integration/test.js b/test/integration/test.js index 0477d2b09a..58bb0354f0 100755 --- a/test/integration/test.js +++ b/test/integration/test.js @@ -100,9 +100,7 @@ const projects = [ 'https://github.com/sindresorhus/capture-website', 'https://github.com/sindresorhus/file-type', 'https://github.com/sindresorhus/slugify', - // TODO: add this project when #254 got fixed - // https://github.com/gatsbyjs/gatsby/blob/e720d8efe58eba0f6fae9f26ec8879128967d0b5/packages/gatsby/src/bootstrap/page-hot-reloader.js#L30 - // 'https://github.com/gatsbyjs/gatsby', + 'https://github.com/gatsbyjs/gatsby', { repository: 'https://github.com/puppeteer/puppeteer', path: 'lib' diff --git a/test/prefer-spread.js b/test/prefer-spread.js index ec37c8cf2c..2c8b05ffa5 100644 --- a/test/prefer-spread.js +++ b/test/prefer-spread.js @@ -123,6 +123,54 @@ ruleTester.run('prefer-spread', rule, { } ], output: '[...document.querySelectorAll("*")].map(() => {});' + }, + // #254 + { + code: ` + const foo = [] + Array.from(arrayLike).forEach(doSomething) + `, + errors: [ + { + message: 'Prefer the spread operator over `Array.from()`.' + } + ], + output: ` + const foo = [] + ;[...arrayLike].forEach(doSomething) + ` + }, + // https://github.com/gatsbyjs/gatsby/blob/e720d8efe58eba0f6fae9f26ec8879128967d0b5/packages/gatsby/src/bootstrap/page-hot-reloader.js#L30 + { + code: ` + foo() + Array.from(arrayLike).forEach(doSomething) + `, + errors: [ + { + message: 'Prefer the spread operator over `Array.from()`.' + } + ], + output: ` + foo() + ;[...arrayLike].forEach(doSomething) + ` + }, + // https://github.com/gatsbyjs/gatsby/blob/4ab3f194cf5d6dcafcb2a75d9604aac79d963554/packages/gatsby/src/redux/__tests__/nodes.js#L277 + { + code: ` + const foo = {} + Array.from(arrayLike).forEach(doSomething) + `, + errors: [ + { + message: 'Prefer the spread operator over `Array.from()`.' + } + ], + output: ` + const foo = {} + ;[...arrayLike].forEach(doSomething) + ` } ] });