diff --git a/docs/deleted-and-deprecated-rules.md b/docs/deleted-and-deprecated-rules.md index 82c1dd60c6..adad29e32e 100644 --- a/docs/deleted-and-deprecated-rules.md +++ b/docs/deleted-and-deprecated-rules.md @@ -6,6 +6,10 @@ Replaced by [`no-instanceof-builtins`](rules/no-instanceof-builtins.md) which covers more cases. +### no-array-push-push + +Replaced by [`prefer-single-call`](rules/prefer-single-call.md) which covers more cases. + ### no-length-as-slice-end Replaced by [`no-unnecessary-slice-end`](rules/no-unnecessary-slice-end.md) which covers more cases. diff --git a/docs/rules/no-array-push-push.md b/docs/rules/no-array-push-push.md deleted file mode 100644 index a0d4c82b36..0000000000 --- a/docs/rules/no-array-push-push.md +++ /dev/null @@ -1,70 +0,0 @@ -# Enforce combining multiple `Array#push()` into one call - -πŸ’Ό This rule is enabled in the βœ… `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config). - -πŸ”§πŸ’‘ This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). - - - - -[`Array#push()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push) accepts multiple arguments. Multiple calls should be combined into one. - -## Fail - -```js -foo.push(1); -foo.push(2, 3); -``` - -## Pass - -```js -foo.push(1, 2, 3); -``` - -```js -const length = foo.push(1); -foo.push(2); -``` - -```js -foo.push(1); -bar(); -foo.push(2); -``` - -## Options - -Type: `object` - -### ignore - -Type: `string[]` - -Ignore objects, `stream`, `this`, `this.stream` are ignored by default. - -Example: - -```js -{ - 'unicorn/no-array-push-push': [ - 'error', - { - ignore: [ - 'readable', - 'foo.stream' - ] - } - ] -} -``` - -```js -// eslint unicorn/no-array-push-push: ["error", {"ignore": ["readable"]}] -import {Readable} from 'node:stream'; - -const readable = new Readable(); -readable.push('one'); -readable.push('another'); -readable.push(null); -``` diff --git a/docs/rules/prefer-single-call.md b/docs/rules/prefer-single-call.md new file mode 100644 index 0000000000..3d55d8b5db --- /dev/null +++ b/docs/rules/prefer-single-call.md @@ -0,0 +1,80 @@ +# Enforce combining multiple `Array#push()`, `Element#classList.{add,remove}()`, and `importScripts()` into one call + +πŸ’Ό This rule is enabled in the βœ… `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config). + +πŸ”§πŸ’‘ This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). + + + + +[`Array#push()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push), [`Element#classList.add()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList), [`Element#classList.remove()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList), and [`importScripts`](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts) accepts multiple arguments. Multiple calls should be combined into one. + +## Examples + +```js +// ❌ +foo.push(1); +foo.push(2, 3); + +// βœ… +foo.push(1, 2, 3); +``` + +```js +// ❌ +element.classList.add('foo'); +element.classList.add('bar', 'baz'); + +// βœ… +element.classList.add('foo', 'bar', 'baz'); +``` + +```js +// ❌ +importScripts("https://example.com/foo.js"); +importScripts("https://example.com/bar.js"); + +// βœ… +importScripts( + "https://example.com/foo.js", + "https://example.com/bar.js", +); +``` + +## Options + +Type: `object` + +### ignore + +Type: `string[]` + +Functions to ignore. + +`stream.push`, `this.push`, and `this.stream.push` are ignored by default. + +Example: + +```js +{ + 'unicorn/prefer-single-call': [ + 'error', + { + ignore: [ + 'readable.push', + 'foo.stream.push' + ] + } + ] +} +``` + +```js +// eslint unicorn/prefer-single-call: ["error", {"ignore": ["readable"]}] +import {Readable} from 'node:stream'; + +const readable = new Readable(); +readable.push('one'); +readable.push('another'); +readable.push(null); +``` diff --git a/index.js b/index.js index edaeef568e..61f4f5a12d 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,10 @@ const deprecatedRules = createDeprecatedRules({ message: 'Replaced by `unicorn/no-unnecessary-slice-end` which covers more cases.', replacedBy: ['unicorn/no-unnecessary-slice-end'], }, + 'no-array-push-push': { + message: 'Replaced by `unicorn/prefer-single-call` which covers more cases.', + replacedBy: ['unicorn/prefer-single-call'], + }, }); const externalRules = { diff --git a/readme.md b/readme.md index 42ffb6ec98..e59d8ca305 100644 --- a/readme.md +++ b/readme.md @@ -79,7 +79,6 @@ export default [ | [no-array-callback-reference](docs/rules/no-array-callback-reference.md) | Prevent passing a function reference directly to iterator methods. | βœ… | | πŸ’‘ | | [no-array-for-each](docs/rules/no-array-for-each.md) | Prefer `for…of` over the `forEach` method. | βœ… | πŸ”§ | πŸ’‘ | | [no-array-method-this-argument](docs/rules/no-array-method-this-argument.md) | Disallow using the `this` argument in array methods. | βœ… | πŸ”§ | πŸ’‘ | -| [no-array-push-push](docs/rules/no-array-push-push.md) | Enforce combining multiple `Array#push()` into one call. | βœ… | πŸ”§ | πŸ’‘ | | [no-array-reduce](docs/rules/no-array-reduce.md) | Disallow `Array#reduce()` and `Array#reduceRight()`. | βœ… | | | | [no-await-expression-member](docs/rules/no-await-expression-member.md) | Disallow member access from await expression. | βœ… | πŸ”§ | | | [no-await-in-promise-methods](docs/rules/no-await-in-promise-methods.md) | Disallow using `await` in `Promise` method parameters. | βœ… | | πŸ’‘ | @@ -165,6 +164,7 @@ export default [ | [prefer-regexp-test](docs/rules/prefer-regexp-test.md) | Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-set-has](docs/rules/prefer-set-has.md) | Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-set-size](docs/rules/prefer-set-size.md) | Prefer using `Set#size` instead of `Array#length`. | βœ… | πŸ”§ | | +| [prefer-single-call](docs/rules/prefer-single-call.md) | Enforce combining multiple `Array#push()`, `Element#classList.{add,remove}()`, and `importScripts()` into one call. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-spread](docs/rules/prefer-spread.md) | Prefer the spread operator over `Array.from(…)`, `Array#concat(…)`, `Array#{slice,toSpliced}()` and `String#split('')`. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-string-raw](docs/rules/prefer-string-raw.md) | Prefer using the `String.raw` tag to avoid escaping `\`. | βœ… | πŸ”§ | | | [prefer-string-replace-all](docs/rules/prefer-string-replace-all.md) | Prefer `String#replaceAll()` over regex searches with the global flag. | βœ… | πŸ”§ | | diff --git a/rules/index.js b/rules/index.js index ca7d1bc9da..df4fe31c36 100644 --- a/rules/index.js +++ b/rules/index.js @@ -24,7 +24,6 @@ import noAnonymousDefaultExport from './no-anonymous-default-export.js'; import noArrayCallbackReference from './no-array-callback-reference.js'; import noArrayForEach from './no-array-for-each.js'; import noArrayMethodThisArgument from './no-array-method-this-argument.js'; -import noArrayPushPush from './no-array-push-push.js'; import noArrayReduce from './no-array-reduce.js'; import noAwaitExpressionMember from './no-await-expression-member.js'; import noAwaitInPromiseMethods from './no-await-in-promise-methods.js'; @@ -110,6 +109,7 @@ import preferReflectApply from './prefer-reflect-apply.js'; import preferRegexpTest from './prefer-regexp-test.js'; import preferSetHas from './prefer-set-has.js'; import preferSetSize from './prefer-set-size.js'; +import preferSingleCall from './prefer-single-call.js'; import preferSpread from './prefer-spread.js'; import preferStringRaw from './prefer-string-raw.js'; import preferStringReplaceAll from './prefer-string-replace-all.js'; @@ -156,7 +156,6 @@ const rules = { 'no-array-callback-reference': createRule(noArrayCallbackReference, 'no-array-callback-reference'), 'no-array-for-each': createRule(noArrayForEach, 'no-array-for-each'), 'no-array-method-this-argument': createRule(noArrayMethodThisArgument, 'no-array-method-this-argument'), - 'no-array-push-push': createRule(noArrayPushPush, 'no-array-push-push'), 'no-array-reduce': createRule(noArrayReduce, 'no-array-reduce'), 'no-await-expression-member': createRule(noAwaitExpressionMember, 'no-await-expression-member'), 'no-await-in-promise-methods': createRule(noAwaitInPromiseMethods, 'no-await-in-promise-methods'), @@ -242,6 +241,7 @@ const rules = { 'prefer-regexp-test': createRule(preferRegexpTest, 'prefer-regexp-test'), 'prefer-set-has': createRule(preferSetHas, 'prefer-set-has'), 'prefer-set-size': createRule(preferSetSize, 'prefer-set-size'), + 'prefer-single-call': createRule(preferSingleCall, 'prefer-single-call'), 'prefer-spread': createRule(preferSpread, 'prefer-spread'), 'prefer-string-raw': createRule(preferStringRaw, 'prefer-string-raw'), 'prefer-string-replace-all': createRule(preferStringReplaceAll, 'prefer-string-replace-all'), diff --git a/rules/no-array-push-push.js b/rules/no-array-push-push.js deleted file mode 100644 index 8a02002a9d..0000000000 --- a/rules/no-array-push-push.js +++ /dev/null @@ -1,150 +0,0 @@ -import {hasSideEffect, isSemicolonToken} from '@eslint-community/eslint-utils'; -import {getCallExpressionTokens, getCallExpressionArgumentsText} from './utils/index.js'; -import isSameReference from './utils/is-same-reference.js'; -import {isNodeMatches} from './utils/is-node-matches.js'; -import getPreviousNode from './utils/get-previous-node.js'; -import {isMethodCall} from './ast/index.js'; - -const ERROR = 'error'; -const SUGGESTION = 'suggestion'; -const messages = { - [ERROR]: 'Do not call `Array#push()` multiple times.', - [SUGGESTION]: 'Merge with previous one.', -}; - -const isArrayPushCall = node => - node - && node.parent.type === 'ExpressionStatement' - && node.parent.expression === node - && isMethodCall(node, { - method: 'push', - optionalCall: false, - optionalMember: false, - }); - -function getFirstArrayPushCall(secondCall, sourceCode) { - const firstCall = getPreviousNode(secondCall.parent, sourceCode)?.expression; - if (isArrayPushCall(firstCall)) { - return firstCall; - } -} - -function create(context) { - const {ignore} = { - ignore: [], - ...context.options[0], - }; - const ignoredObjects = [ - 'stream', - 'this', - 'this.stream', - 'process.stdin', - 'process.stdout', - 'process.stderr', - ...ignore, - ]; - const {sourceCode} = context; - - return { - CallExpression(secondCall) { - if (!isArrayPushCall(secondCall)) { - return; - } - - const secondCallArray = secondCall.callee.object; - - if (isNodeMatches(secondCallArray, ignoredObjects)) { - return; - } - - const firstCall = getFirstArrayPushCall(secondCall, sourceCode); - if (!firstCall) { - return; - } - - const firstCallArray = firstCall.callee.object; - - // Not same array - if (!isSameReference(firstCallArray, secondCallArray)) { - return; - } - - const secondCallArguments = secondCall.arguments; - const problem = { - node: secondCall.callee.property, - messageId: ERROR, - }; - - const fix = function * (fixer) { - if (secondCallArguments.length > 0) { - const text = getCallExpressionArgumentsText(sourceCode, secondCall); - - const { - trailingCommaToken, - closingParenthesisToken, - } = getCallExpressionTokens(sourceCode, firstCall); - - yield ( - trailingCommaToken - ? fixer.insertTextAfter(trailingCommaToken, ` ${text}`) - : fixer.insertTextBefore(closingParenthesisToken, firstCall.arguments.length > 0 ? `, ${text}` : text) - ); - } - - const firstExpression = firstCall.parent; - const secondExpression = secondCall.parent; - const shouldKeepSemicolon = !isSemicolonToken(sourceCode.getLastToken(firstExpression)) - && isSemicolonToken(sourceCode.getLastToken(secondExpression)); - const [, start] = sourceCode.getRange(firstExpression); - const [, end] = sourceCode.getRange(secondExpression); - - yield fixer.replaceTextRange([start, end], shouldKeepSemicolon ? ';' : ''); - }; - - if (secondCallArguments.some(element => hasSideEffect(element, sourceCode))) { - problem.suggest = [ - { - messageId: SUGGESTION, - fix, - }, - ]; - } else { - problem.fix = fix; - } - - return problem; - }, - }; -} - -const schema = [ - { - type: 'object', - additionalProperties: false, - properties: { - ignore: { - type: 'array', - uniqueItems: true, - }, - }, - }, -]; - -/** @type {import('eslint').Rule.RuleModule} */ -const config = { - create, - meta: { - type: 'suggestion', - docs: { - description: 'Enforce combining multiple `Array#push()` into one call.', - recommended: true, - }, - fixable: 'code', - hasSuggestions: true, - schema, - defaultOptions: [{}], - messages, - }, -}; - -export default config; diff --git a/rules/prefer-single-call.js b/rules/prefer-single-call.js new file mode 100644 index 0000000000..60fa267b7f --- /dev/null +++ b/rules/prefer-single-call.js @@ -0,0 +1,179 @@ +import {hasSideEffect, isSemicolonToken} from '@eslint-community/eslint-utils'; +import {getCallExpressionTokens, getCallExpressionArgumentsText} from './utils/index.js'; +import isSameReference from './utils/is-same-reference.js'; +import {isNodeMatches} from './utils/is-node-matches.js'; +import getPreviousNode from './utils/get-previous-node.js'; +import {isMethodCall, isMemberExpression, isCallExpression} from './ast/index.js'; + +const ERROR = 'error/array-push'; +const SUGGESTION = 'suggestion'; +const messages = { + [ERROR]: 'Do not call `{{description}}` multiple times.', + [SUGGESTION]: 'Merge with previous one.', +}; + +const isExpressionStatement = node => + node?.parent.type === 'ExpressionStatement' + && node.parent.expression === node; +const isClassList = node => isMemberExpression(node, { + property: 'classList', + optional: false, + computed: false, +}); + +const cases = [ + { + description: 'Array#push()', + test: callExpression => isMethodCall(callExpression, { + method: 'push', + optionalCall: false, + optionalMember: false, + }), + ignore: [ + 'stream.push', + 'this.push', + 'this.stream.push', + 'process.stdin.push', + 'process.stdout.push', + 'process.stderr.push', + ], + }, + { + description: 'Element#classList.add()', + test: callExpression => + isMethodCall(callExpression, { + method: 'add', + optionalCall: false, + optionalMember: false, + }) + && isClassList(callExpression.callee.object), + }, + { + description: 'Element#classList.remove()', + test: callExpression => + isMethodCall(callExpression, { + method: 'remove', + optionalCall: false, + optionalMember: false, + }) + && isClassList(callExpression.callee.object), + }, + { + description: 'importScripts()', + test: callExpression => isCallExpression(callExpression, { + name: 'importScripts', + optional: false, + }), + }, +].map(problematicalCase => ({ + ...problematicalCase, + test: callExpression => isExpressionStatement(callExpression) && problematicalCase.test(callExpression), +})); + +function create(context) { + const { + ignore: ignoredCalleeInOptions, + } = { + ignore: [], + ...context.options[0], + }; + const {sourceCode} = context; + + return { + * CallExpression(secondCall) { + for (const {description, test, ignore = []} of cases) { + if (!test(secondCall)) { + continue; + } + + const ignoredCallee = [...ignore, ...ignoredCalleeInOptions]; + if (isNodeMatches(secondCall.callee, ignoredCallee)) { + continue; + } + + const firstCall = getPreviousNode(secondCall.parent, sourceCode)?.expression; + if (!test(firstCall) || !isSameReference(firstCall.callee, secondCall.callee)) { + continue; + } + + const secondCallArguments = secondCall.arguments; + const problem = { + node: secondCall.callee.type === 'Identifier' ? secondCall.callee : secondCall.callee.property, + messageId: ERROR, + data: {description}, + }; + + const fix = function * (fixer) { + if (secondCallArguments.length > 0) { + const text = getCallExpressionArgumentsText(sourceCode, secondCall); + + const { + trailingCommaToken, + closingParenthesisToken, + } = getCallExpressionTokens(sourceCode, firstCall); + + yield ( + trailingCommaToken + ? fixer.insertTextAfter(trailingCommaToken, ` ${text}`) + : fixer.insertTextBefore(closingParenthesisToken, firstCall.arguments.length > 0 ? `, ${text}` : text) + ); + } + + const firstExpression = firstCall.parent; + const secondExpression = secondCall.parent; + const shouldKeepSemicolon = !isSemicolonToken(sourceCode.getLastToken(firstExpression)) + && isSemicolonToken(sourceCode.getLastToken(secondExpression)); + const [, start] = sourceCode.getRange(firstExpression); + const [, end] = sourceCode.getRange(secondExpression); + + yield fixer.replaceTextRange([start, end], shouldKeepSemicolon ? ';' : ''); + }; + + if (secondCallArguments.some(element => hasSideEffect(element, sourceCode))) { + problem.suggest = [ + { + messageId: SUGGESTION, + fix, + }, + ]; + } else { + problem.fix = fix; + } + + yield problem; + } + }, + }; +} + +const schema = [ + { + type: 'object', + additionalProperties: false, + properties: { + ignore: { + type: 'array', + uniqueItems: true, + }, + }, + }, +]; + +/** @type {import('eslint').Rule.RuleModule} */ +const config = { + create, + meta: { + type: 'suggestion', + docs: { + description: 'Enforce combining multiple `Array#push()`, `Element#classList.{add,remove}()`, and `importScripts()` into one call.', + recommended: true, + }, + fixable: 'code', + hasSuggestions: true, + schema, + defaultOptions: [{}], + messages, + }, +}; + +export default config; diff --git a/test/no-array-push-push.js b/test/no-array-push-push.js deleted file mode 100644 index 064b93cdcb..0000000000 --- a/test/no-array-push-push.js +++ /dev/null @@ -1,296 +0,0 @@ -import outdent from 'outdent'; -import {getTester} from './utils/test.js'; - -const {test} = getTester(import.meta); - -test.snapshot({ - valid: [ - outdent` - foo.forEach(fn); - foo.forEach(fn); - `, - 'foo.push(1);', - outdent` - foo.push(1); - foo.unshift(2); - `, - outdent` - foo.push(1);; // <- there is a "EmptyStatement" between - foo.push(2); - `, - // Not same array - outdent` - foo.push(1); - bar.push(2); - `, - // `.push` selector - 'foo.push(1);push(2)', - 'push(1);foo.push(2)', - 'new foo.push(1);foo.push(2)', - 'foo.push(1);new foo.push(2)', - 'foo[push](1);foo.push(2)', - 'foo.push(1);foo[push](2)', - 'foo.push(foo.push(1));', - // Not `ExpressionStatement` - outdent` - const length = foo.push(1); - foo.push(2); - `, - outdent` - foo.push(1); - const length = foo.push(2); - `, - // Not considered same array - outdent` - foo().push(1); - foo().push(2); - `, - outdent` - foo().bar.push(1); - foo().bar.push(2); - `, - // Ignored - outdent` - const stream = new Readable(); - stream.push('one string'); - stream.push('another string'); - `, - outdent` - class FooReadable extends Readable { - pushAndEnd(chunk) { - this.push(chunk); - this.push(null); - } - } - `, - outdent` - class Foo { - pushAndEnd(chunk) { - this.stream.push(chunk); - this.stream.push(null); - } - } - `, - { - code: outdent` - foo.push(1); - foo.push(2); - foo.bar.push(1); - foo.bar.push(2); - `, - options: [ - { - ignore: ['foo', 'foo.bar'], - }, - ], - }, - 'for (const _ of []) foo.push(bar);', - ], - invalid: [ - outdent` - foo.push(1); - foo.push(2); - `, - outdent` - (foo.push)(1); - (foo.push)(2); - `, - outdent` - foo.bar.push(1); - foo.bar.push(2); - `, - outdent` - foo.push(1); - (foo).push(2); - `, - outdent` - foo.push(); - foo.push(); - `, - outdent` - foo.push(1); - foo.push(); - `, - outdent` - foo.push(); - foo.push(2); - `, - outdent` - foo.push(1, 2); - foo.push((3), (4)); - `, - outdent` - foo.push(1, 2,); - foo.push(3, 4); - `, - outdent` - foo.push(1, 2); - foo.push(3, 4,); - `, - outdent` - foo.push(1, 2,); - foo.push(3, 4,); - `, - outdent` - foo.push(1, 2, ...a,); - foo.push(...b,); - `, - outdent` - foo.push(bar()); - foo.push(1); - `, - // `arguments` in second push has side effect - outdent` - foo.push(1); - foo.push(bar()); - `, - // Multiple - outdent` - foo.push(1,); - foo.push(2,); - foo.push(3,); - `, - // Should be able to find the previous expression - outdent` - if (a) { - foo.push(1); - foo.push(2); - } - `, - outdent` - switch (a) { - default: - foo.push(1); - foo.push(2); - } - `, - outdent` - function a() { - foo.push(1); - foo.push(2); - } - `, - // ASI - outdent` - foo.push(1) - foo.push(2) - ;[foo].forEach(bar) - `, - // Still same array - outdent` - foo.bar.push(1); - (foo)['bar'].push(2); - `, - // Ignored - outdent` - foo.push(1); - foo.push(2); - stream.push(1); - stream.push(2); - `, - { - code: outdent` - foo.bar.push(1); - foo.bar.push(2); - foo.push(1); - foo.push(2); - bar.foo.push(1); - bar.foo.push(2); - `, - options: [ - { - ignore: ['foo', 'foo.bar'], - }, - ], - }, - ], -}); - -// `isSameReference` coverage -test({ - valid: [ - outdent` - '1'.someMagicPropertyReturnsAnArray.push(1); - (1).someMagicPropertyReturnsAnArray.push(2); - - /a/i.someMagicPropertyReturnsAnArray.push(1); - /b/g.someMagicPropertyReturnsAnArray.push(2); - - 1n.someMagicPropertyReturnsAnArray.push(1); - 2n.someMagicPropertyReturnsAnArray.push(2); - - (true).someMagicPropertyReturnsAnArray.push(1); - (false).someMagicPropertyReturnsAnArray.push(2); - `, - ], - invalid: [ - { - code: outdent` - class A extends B { - foo() { - this.x.push(1); - this.x.push(2); - - super.x.push(1); - super.x.push(2); - - ((a?.x).y).push(1); - (a.x?.y).push(1); - - ((a?.x.y).z).push(1); - ((a.x?.y).z).push(1); - - a[null].push(1); - a['null'].push(1); - - '1'.someMagicPropertyReturnsAnArray.push(1); - '1'.someMagicPropertyReturnsAnArray.push(2); - - /a/i.someMagicPropertyReturnsAnArray.push(1); - /a/i.someMagicPropertyReturnsAnArray.push(2); - - 1n.someMagicPropertyReturnsAnArray.push(1); - 1n.someMagicPropertyReturnsAnArray.push(2); - - (true).someMagicPropertyReturnsAnArray.push(1); - (true).someMagicPropertyReturnsAnArray.push(2); - } - } - `, - output: outdent` - class A extends B { - foo() { - this.x.push(1, 2); - - super.x.push(1, 2); - - ((a?.x).y).push(1, 1); - - ((a?.x.y).z).push(1, 1); - - a[null].push(1, 1); - - '1'.someMagicPropertyReturnsAnArray.push(1, 2); - - /a/i.someMagicPropertyReturnsAnArray.push(1, 2); - - 1n.someMagicPropertyReturnsAnArray.push(1, 2); - - (true).someMagicPropertyReturnsAnArray.push(1, 2); - } - } - `, - errors: 9, - }, - { - code: outdent` - a[x].push(1); - a[x].push(2); - `, - output: outdent` - a[x].push(1, 2); - `, - errors: 1, - }, - ], -}); diff --git a/test/prefer-single-call.js b/test/prefer-single-call.js new file mode 100644 index 0000000000..3e6d071589 --- /dev/null +++ b/test/prefer-single-call.js @@ -0,0 +1,593 @@ +import outdent from 'outdent'; +import {getTester} from './utils/test.js'; + +const {test} = getTester(import.meta); + +// `Array#push()` +test.snapshot({ + valid: [ + outdent` + foo.forEach(fn); + foo.forEach(fn); + `, + 'foo.push(1);', + outdent` + foo.push(1); + foo.unshift(2); + `, + outdent` + foo.push(1);; // <- there is a "EmptyStatement" between + foo.push(2); + `, + // Not same array + outdent` + foo.push(1); + bar.push(2); + `, + // `.push` selector + 'foo.push(1);push(2)', + 'push(1);foo.push(2)', + 'new foo.push(1);foo.push(2)', + 'foo.push(1);new foo.push(2)', + 'foo[push](1);foo.push(2)', + 'foo.push(1);foo[push](2)', + 'foo.push(foo.push(1));', + // Not `ExpressionStatement` + outdent` + const length = foo.push(1); + foo.push(2); + `, + outdent` + foo.push(1); + const length = foo.push(2); + `, + // Not considered same array + outdent` + foo().push(1); + foo().push(2); + `, + outdent` + foo().bar.push(1); + foo().bar.push(2); + `, + // Ignored + outdent` + const stream = new Readable(); + stream.push('one string'); + stream.push('another string'); + `, + outdent` + class FooReadable extends Readable { + pushAndEnd(chunk) { + this.push(chunk); + this.push(null); + } + } + `, + outdent` + class Foo { + pushAndEnd(chunk) { + this.stream.push(chunk); + this.stream.push(null); + } + } + `, + { + code: outdent` + foo.push(1); + foo.push(2); + foo.bar.push(1); + foo.bar.push(2); + `, + options: [ + { + ignore: ['foo.push', 'foo.bar.push'], + }, + ], + }, + 'for (const _ of []) foo.push(bar);', + ], + invalid: [ + outdent` + foo.push(1); + foo.push(2); + `, + outdent` + (foo.push)(1); + (foo.push)(2); + `, + outdent` + foo.bar.push(1); + foo.bar.push(2); + `, + outdent` + foo.push(1); + (foo).push(2); + `, + outdent` + foo.push(); + foo.push(); + `, + outdent` + foo.push(1); + foo.push(); + `, + outdent` + foo.push(); + foo.push(2); + `, + outdent` + foo.push(1, 2); + foo.push((3), (4)); + `, + outdent` + foo.push(1, 2,); + foo.push(3, 4); + `, + outdent` + foo.push(1, 2); + foo.push(3, 4,); + `, + outdent` + foo.push(1, 2,); + foo.push(3, 4,); + `, + outdent` + foo.push(1, 2, ...a,); + foo.push(...b,); + `, + outdent` + foo.push(bar()); + foo.push(1); + `, + // `arguments` in second push has side effect + outdent` + foo.push(1); + foo.push(bar()); + `, + // Multiple + outdent` + foo.push(1,); + foo.push(2,); + foo.push(3,); + `, + // Should be able to find the previous expression + outdent` + if (a) { + foo.push(1); + foo.push(2); + } + `, + outdent` + switch (a) { + default: + foo.push(1); + foo.push(2); + } + `, + outdent` + function a() { + foo.push(1); + foo.push(2); + } + `, + // ASI + outdent` + foo.push(1) + foo.push(2) + ;[foo].forEach(bar) + `, + // Still same array + outdent` + foo.bar.push(1); + (foo)['bar'].push(2); + `, + // Ignored + outdent` + foo.push(1); + foo.push(2); + stream.push(1); + stream.push(2); + `, + { + code: outdent` + foo.bar.push(1); + foo.bar.push(2); + foo.push(1); + foo.push(2); + bar.foo.push(1); + bar.foo.push(2); + `, + options: [ + { + ignore: ['foo', 'foo.bar'], + }, + ], + }, + ], +}); + +// `Element#classList.{add,remove}()` +test.snapshot({ + valid: [ + outdent` + foo.classList.toggle('foo'); + foo.classList.toggle('bar'); + `, + 'foo.classList.add("foo");', + outdent` + foo.classList.add("foo"); + foo.classList.remove("bar"); + `, + outdent` + foo.classList.add("foo");; // <- there is a "EmptyStatement" between + foo.classList.add("bar"); + `, + // Not same element + outdent` + foo.classList.add("foo"); + bar.classList.add("bar"); + `, + // `.add` selector + 'foo.classList.add("foo");add("bar")', + 'add("foo");foo.classList("bar")', + 'new foo.classList.add("foo");foo.classList.add("bar")', + 'foo.classList.add("foo");new foo.classList.add("bar")', + 'foo.classList[add]("foo");foo.classList.add("bar")', + 'foo.classList.add("foo");foo.classList[add]("bar");', + 'foo.classList.add(foo.classList.add("foo"));', + // `.classList` elector + outdent` + foo.classList.add("foo"); + foo[classList].add("bar"); + `, + outdent` + foo.classList.add("foo"); + classList.add("bar"); + `, + outdent` + foo.classList.add("foo"); + (new foo.classList).add("bar"); + `, + outdent` + foo.classList.add("foo"); + foo?.classList.add("bar"); + `, + outdent` + foo.notClassList.add("foo"); + foo.notClassList.add("bar"); + `, + outdent` + classList.add("foo"); + classList.add("bar"); + `, + // Not `ExpressionStatement` + outdent` + const _ = foo.classList.add("foo"); + foo.classList.add("bar"); + `, + outdent` + foo.classList.add("foo"); + const _ = foo.classList.add("bar"); + `, + // Not considered same array + outdent` + foo().classList.add("foo"); + foo().classList.add("bar"); + `, + outdent` + foo().bar.classList.add("foo"); + foo().bar.classList.add("bar"); + `, + ], + invalid: [ + outdent` + foo.classList.add("foo"); + foo.classList.add("bar"); + `, + outdent` + foo.classList.remove("foo"); + foo.classList.remove("bar"); + `, + outdent` + (foo.classList.add)("foo"); + (foo.classList.add)("bar"); + `, + outdent` + foo.bar.classList.add("foo"); + foo.bar.classList.add("bar"); + `, + outdent` + foo.classList.add("foo"); + (foo).classList.add("bar"); + `, + outdent` + foo.classList.add(); + foo.classList.add(); + `, + outdent` + foo.classList.add("foo"); + foo.classList.add(); + `, + outdent` + foo.classList.add(); + foo.classList.add(2); + `, + outdent` + foo.classList.add(a, b); + foo.classList.add((c), (d)); + `, + outdent` + foo.classList.add.push(a, b,); + foo.classList.add.push(c, d); + `, + outdent` + foo.classList.add(a, b); + foo.classList.add(c, d,); + `, + outdent` + foo.classList.add(a, b,); + foo.classList.add(c, d,); + `, + outdent` + foo.classList.add(a, b, ...c,); + foo.classList.add(...d,); + `, + outdent` + foo.classList.add(bar()); + foo.classList.add("foo"); + `, + // `arguments` in second call has side effect + outdent` + foo.classList.add(a); + foo.classList.add(bar()); + `, + // Multiple + outdent` + foo.classList.add(a,); + foo.classList.add(b,); + foo.classList.add(c,); + `, + // Should be able to find the previous expression + outdent` + if (a) { + foo.classList.add(a); + foo.classList.add(b); + } + `, + outdent` + switch (a) { + default: + foo.classList.add(a); + foo.classList.add(b); + } + `, + outdent` + function _() { + foo.classList.add(a); + foo.classList.add(b); + } + `, + // ASI + outdent` + foo.classList.add(a) + foo.classList.add(b) + ;[foo].forEach(bar) + `, + // Still same reference + outdent` + foo.bar.classList.add(a); + (foo)['bar'].classList.add(b); + `, + ], +}); + +// `importScripts()` +test.snapshot({ + valid: [ + outdent` + importScripts('foo.js'); + notImportScripts('bar.js'); + `, + 'importScripts("foo.js");', + outdent` + importScripts("foo.js");; // <- there is a "EmptyStatement" between + importScripts("bar.js"); + `, + // `.add` selector + 'new importScripts("foo.js");importScripts("bar.js")', + 'importScripts("foo.js");new importScripts("bar.js")', + // Not `ExpressionStatement` + outdent` + const _ = importScripts("foo.js"); + importScripts("bar.js"); + `, + outdent` + importScripts("foo.js"); + const _ = importScripts("bar.js"); + `, + { + code: outdent` + importScripts("foo.js"); + importScripts("bar.js"); + `, + options: [ + { + ignore: ['importScripts'], + }, + ], + }, + ], + invalid: [ + outdent` + importScripts("foo.js"); + importScripts("bar.js"); + `, + outdent` + (importScripts)("foo.js"); + (importScripts)("bar.js"); + `, + outdent` + importScripts(); + importScripts(); + `, + outdent` + importScripts("foo.js"); + importScripts(); + `, + outdent` + importScripts(); + importScripts(2); + `, + outdent` + importScripts(a, b); + importScripts((c), (d)); + `, + outdent` + importScripts(a, b,); + importScripts(c, d); + `, + outdent` + importScripts(a, b); + importScripts(c, d,); + `, + outdent` + importScripts(a, b,); + importScripts(c, d,); + `, + outdent` + foo.classList.add(a, b, ...c,); + foo.classList.add(...d,); + `, + outdent` + importScripts(bar()); + importScripts("foo.js"); + `, + // `arguments` in second call has side effect + outdent` + importScripts(a); + importScripts(bar()); + `, + // Multiple + outdent` + importScripts(a,); + importScripts(b,); + importScripts(c,); + `, + // Should be able to find the previous expression + outdent` + if (a) { + importScripts(a); + importScripts(b); + } + `, + outdent` + switch (a) { + default: + importScripts(a); + importScripts(b); + } + `, + outdent` + function _() { + importScripts(a); + importScripts(b); + } + `, + // ASI + outdent` + importScripts(a) + importScripts(b) + ;[foo].forEach(bar) + `, + ], +}); + +// `isSameReference` coverage +test({ + valid: [ + outdent` + '1'.someMagicPropertyReturnsAnArray.push(1); + (1).someMagicPropertyReturnsAnArray.push(2); + + /a/i.someMagicPropertyReturnsAnArray.push(1); + /b/g.someMagicPropertyReturnsAnArray.push(2); + + 1n.someMagicPropertyReturnsAnArray.push(1); + 2n.someMagicPropertyReturnsAnArray.push(2); + + (true).someMagicPropertyReturnsAnArray.push(1); + (false).someMagicPropertyReturnsAnArray.push(2); + `, + ], + invalid: [ + { + code: outdent` + class A extends B { + foo() { + this.x.push(1); + this.x.push(2); + + super.x.push(1); + super.x.push(2); + + ((a?.x).y).push(1); + (a.x?.y).push(1); + + ((a?.x.y).z).push(1); + ((a.x?.y).z).push(1); + + a[null].push(1); + a['null'].push(1); + + '1'.someMagicPropertyReturnsAnArray.push(1); + '1'.someMagicPropertyReturnsAnArray.push(2); + + /a/i.someMagicPropertyReturnsAnArray.push(1); + /a/i.someMagicPropertyReturnsAnArray.push(2); + + 1n.someMagicPropertyReturnsAnArray.push(1); + 1n.someMagicPropertyReturnsAnArray.push(2); + + (true).someMagicPropertyReturnsAnArray.push(1); + (true).someMagicPropertyReturnsAnArray.push(2); + } + } + `, + output: outdent` + class A extends B { + foo() { + this.x.push(1, 2); + + super.x.push(1, 2); + + ((a?.x).y).push(1, 1); + + ((a?.x.y).z).push(1, 1); + + a[null].push(1, 1); + + '1'.someMagicPropertyReturnsAnArray.push(1, 2); + + /a/i.someMagicPropertyReturnsAnArray.push(1, 2); + + 1n.someMagicPropertyReturnsAnArray.push(1, 2); + + (true).someMagicPropertyReturnsAnArray.push(1, 2); + } + } + `, + errors: 9, + }, + { + code: outdent` + a[x].push(1); + a[x].push(2); + `, + output: outdent` + a[x].push(1, 2); + `, + errors: 1, + }, + ], +}); diff --git a/test/snapshots/no-array-push-push.js.md b/test/snapshots/no-array-push-push.js.md deleted file mode 100644 index d408d538b3..0000000000 --- a/test/snapshots/no-array-push-push.js.md +++ /dev/null @@ -1,574 +0,0 @@ -# Snapshot report for `test/no-array-push-push.js` - -The actual snapshot is saved in `no-array-push-push.js.snap`. - -Generated by [AVA](https://avajs.dev). - -## invalid(1): foo.push(1); foo.push(2); - -> Input - - `␊ - 1 | foo.push(1);␊ - 2 | foo.push(2);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1);␊ - > 2 | foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(2): (foo.push)(1); (foo.push)(2); - -> Input - - `␊ - 1 | (foo.push)(1);␊ - 2 | (foo.push)(2);␊ - ` - -> Output - - `␊ - 1 | (foo.push)(1, 2);␊ - ` - -> Error 1/1 - - `␊ - 1 | (foo.push)(1);␊ - > 2 | (foo.push)(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(3): foo.bar.push(1); foo.bar.push(2); - -> Input - - `␊ - 1 | foo.bar.push(1);␊ - 2 | foo.bar.push(2);␊ - ` - -> Output - - `␊ - 1 | foo.bar.push(1, 2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.bar.push(1);␊ - > 2 | foo.bar.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(4): foo.push(1); (foo).push(2); - -> Input - - `␊ - 1 | foo.push(1);␊ - 2 | (foo).push(2);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1);␊ - > 2 | (foo).push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(5): foo.push(); foo.push(); - -> Input - - `␊ - 1 | foo.push();␊ - 2 | foo.push();␊ - ` - -> Output - - `␊ - 1 | foo.push();␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push();␊ - > 2 | foo.push();␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(6): foo.push(1); foo.push(); - -> Input - - `␊ - 1 | foo.push(1);␊ - 2 | foo.push();␊ - ` - -> Output - - `␊ - 1 | foo.push(1);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1);␊ - > 2 | foo.push();␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(7): foo.push(); foo.push(2); - -> Input - - `␊ - 1 | foo.push();␊ - 2 | foo.push(2);␊ - ` - -> Output - - `␊ - 1 | foo.push(2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push();␊ - > 2 | foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(8): foo.push(1, 2); foo.push((3), (4)); - -> Input - - `␊ - 1 | foo.push(1, 2);␊ - 2 | foo.push((3), (4));␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2, (3), (4));␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1, 2);␊ - > 2 | foo.push((3), (4));␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(9): foo.push(1, 2,); foo.push(3, 4); - -> Input - - `␊ - 1 | foo.push(1, 2,);␊ - 2 | foo.push(3, 4);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2, 3, 4);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1, 2,);␊ - > 2 | foo.push(3, 4);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(10): foo.push(1, 2); foo.push(3, 4,); - -> Input - - `␊ - 1 | foo.push(1, 2);␊ - 2 | foo.push(3, 4,);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2, 3, 4,);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1, 2);␊ - > 2 | foo.push(3, 4,);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(11): foo.push(1, 2,); foo.push(3, 4,); - -> Input - - `␊ - 1 | foo.push(1, 2,);␊ - 2 | foo.push(3, 4,);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2, 3, 4,);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1, 2,);␊ - > 2 | foo.push(3, 4,);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(12): foo.push(1, 2, ...a,); foo.push(...b,); - -> Input - - `␊ - 1 | foo.push(1, 2, ...a,);␊ - 2 | foo.push(...b,);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2, ...a, ...b,);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1, 2, ...a,);␊ - > 2 | foo.push(...b,);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(13): foo.push(bar()); foo.push(1); - -> Input - - `␊ - 1 | foo.push(bar());␊ - 2 | foo.push(1);␊ - ` - -> Output - - `␊ - 1 | foo.push(bar(), 1);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(bar());␊ - > 2 | foo.push(1);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(14): foo.push(1); foo.push(bar()); - -> Input - - `␊ - 1 | foo.push(1);␊ - 2 | foo.push(bar());␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1);␊ - > 2 | foo.push(bar());␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Merge with previous one.␊ - 1 | foo.push(1, bar());␊ - ` - -## invalid(15): foo.push(1,); foo.push(2,); foo.push(3,); - -> Input - - `␊ - 1 | foo.push(1,);␊ - 2 | foo.push(2,);␊ - 3 | foo.push(3,);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2, 3,);␊ - ` - -> Error 1/2 - - `␊ - 1 | foo.push(1,);␊ - > 2 | foo.push(2,);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - 3 | foo.push(3,);␊ - ` - -> Error 2/2 - - `␊ - 1 | foo.push(1,);␊ - 2 | foo.push(2,);␊ - > 3 | foo.push(3,);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(16): if (a) { foo.push(1); foo.push(2); } - -> Input - - `␊ - 1 | if (a) {␊ - 2 | foo.push(1);␊ - 3 | foo.push(2);␊ - 4 | }␊ - ` - -> Output - - `␊ - 1 | if (a) {␊ - 2 | foo.push(1, 2);␊ - 3 | }␊ - ` - -> Error 1/1 - - `␊ - 1 | if (a) {␊ - 2 | foo.push(1);␊ - > 3 | foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - 4 | }␊ - ` - -## invalid(17): switch (a) { default: foo.push(1); foo.push(2); } - -> Input - - `␊ - 1 | switch (a) {␊ - 2 | default:␊ - 3 | foo.push(1);␊ - 4 | foo.push(2);␊ - 5 | }␊ - ` - -> Output - - `␊ - 1 | switch (a) {␊ - 2 | default:␊ - 3 | foo.push(1, 2);␊ - 4 | }␊ - ` - -> Error 1/1 - - `␊ - 1 | switch (a) {␊ - 2 | default:␊ - 3 | foo.push(1);␊ - > 4 | foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - 5 | }␊ - ` - -## invalid(18): function a() { foo.push(1); foo.push(2); } - -> Input - - `␊ - 1 | function a() {␊ - 2 | foo.push(1);␊ - 3 | foo.push(2);␊ - 4 | }␊ - ` - -> Output - - `␊ - 1 | function a() {␊ - 2 | foo.push(1, 2);␊ - 3 | }␊ - ` - -> Error 1/1 - - `␊ - 1 | function a() {␊ - 2 | foo.push(1);␊ - > 3 | foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - 4 | }␊ - ` - -## invalid(19): foo.push(1) foo.push(2) ;[foo].forEach(bar) - -> Input - - `␊ - 1 | foo.push(1)␊ - 2 | foo.push(2)␊ - 3 | ;[foo].forEach(bar)␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2);[foo].forEach(bar)␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1)␊ - > 2 | foo.push(2)␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - 3 | ;[foo].forEach(bar)␊ - ` - -## invalid(20): foo.bar.push(1); (foo)['bar'].push(2); - -> Input - - `␊ - 1 | foo.bar.push(1);␊ - 2 | (foo)['bar'].push(2);␊ - ` - -> Output - - `␊ - 1 | foo.bar.push(1, 2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.bar.push(1);␊ - > 2 | (foo)['bar'].push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` - -## invalid(21): foo.push(1); foo.push(2); stream.push(1); stream.push(2); - -> Input - - `␊ - 1 | foo.push(1);␊ - 2 | foo.push(2);␊ - 3 | stream.push(1);␊ - 4 | stream.push(2);␊ - ` - -> Output - - `␊ - 1 | foo.push(1, 2);␊ - 2 | stream.push(1);␊ - 3 | stream.push(2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.push(1);␊ - > 2 | foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - 3 | stream.push(1);␊ - 4 | stream.push(2);␊ - ` - -## invalid(22): foo.bar.push(1); foo.bar.push(2); foo.push(1); foo.push(2); bar.foo.push(1); bar.foo.push(2); - -> Input - - `␊ - 1 | foo.bar.push(1);␊ - 2 | foo.bar.push(2);␊ - 3 | foo.push(1);␊ - 4 | foo.push(2);␊ - 5 | bar.foo.push(1);␊ - 6 | bar.foo.push(2);␊ - ` - -> Options - - `␊ - [␊ - {␊ - "ignore": [␊ - "foo",␊ - "foo.bar"␊ - ]␊ - }␊ - ]␊ - ` - -> Output - - `␊ - 1 | foo.bar.push(1);␊ - 2 | foo.bar.push(2);␊ - 3 | foo.push(1);␊ - 4 | foo.push(2);␊ - 5 | bar.foo.push(1, 2);␊ - ` - -> Error 1/1 - - `␊ - 1 | foo.bar.push(1);␊ - 2 | foo.bar.push(2);␊ - 3 | foo.push(1);␊ - 4 | foo.push(2);␊ - 5 | bar.foo.push(1);␊ - > 6 | bar.foo.push(2);␊ - | ^^^^ Do not call \`Array#push()\` multiple times.␊ - ` diff --git a/test/snapshots/no-array-push-push.js.snap b/test/snapshots/no-array-push-push.js.snap deleted file mode 100644 index 4354945dcf..0000000000 Binary files a/test/snapshots/no-array-push-push.js.snap and /dev/null differ diff --git a/test/snapshots/prefer-single-call.js.md b/test/snapshots/prefer-single-call.js.md new file mode 100644 index 0000000000..b41113c3ae --- /dev/null +++ b/test/snapshots/prefer-single-call.js.md @@ -0,0 +1,1534 @@ +# Snapshot report for `test/prefer-single-call.js` + +The actual snapshot is saved in `prefer-single-call.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## invalid(1): foo.push(1); foo.push(2); + +> Input + + `␊ + 1 | foo.push(1);␊ + 2 | foo.push(2);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1);␊ + > 2 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(2): (foo.push)(1); (foo.push)(2); + +> Input + + `␊ + 1 | (foo.push)(1);␊ + 2 | (foo.push)(2);␊ + ` + +> Output + + `␊ + 1 | (foo.push)(1, 2);␊ + ` + +> Error 1/1 + + `␊ + 1 | (foo.push)(1);␊ + > 2 | (foo.push)(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(3): foo.bar.push(1); foo.bar.push(2); + +> Input + + `␊ + 1 | foo.bar.push(1);␊ + 2 | foo.bar.push(2);␊ + ` + +> Output + + `␊ + 1 | foo.bar.push(1, 2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.bar.push(1);␊ + > 2 | foo.bar.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(4): foo.push(1); (foo).push(2); + +> Input + + `␊ + 1 | foo.push(1);␊ + 2 | (foo).push(2);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1);␊ + > 2 | (foo).push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(5): foo.push(); foo.push(); + +> Input + + `␊ + 1 | foo.push();␊ + 2 | foo.push();␊ + ` + +> Output + + `␊ + 1 | foo.push();␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push();␊ + > 2 | foo.push();␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(6): foo.push(1); foo.push(); + +> Input + + `␊ + 1 | foo.push(1);␊ + 2 | foo.push();␊ + ` + +> Output + + `␊ + 1 | foo.push(1);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1);␊ + > 2 | foo.push();␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(7): foo.push(); foo.push(2); + +> Input + + `␊ + 1 | foo.push();␊ + 2 | foo.push(2);␊ + ` + +> Output + + `␊ + 1 | foo.push(2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push();␊ + > 2 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(8): foo.push(1, 2); foo.push((3), (4)); + +> Input + + `␊ + 1 | foo.push(1, 2);␊ + 2 | foo.push((3), (4));␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2, (3), (4));␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1, 2);␊ + > 2 | foo.push((3), (4));␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(9): foo.push(1, 2,); foo.push(3, 4); + +> Input + + `␊ + 1 | foo.push(1, 2,);␊ + 2 | foo.push(3, 4);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2, 3, 4);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1, 2,);␊ + > 2 | foo.push(3, 4);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(10): foo.push(1, 2); foo.push(3, 4,); + +> Input + + `␊ + 1 | foo.push(1, 2);␊ + 2 | foo.push(3, 4,);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2, 3, 4,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1, 2);␊ + > 2 | foo.push(3, 4,);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(11): foo.push(1, 2,); foo.push(3, 4,); + +> Input + + `␊ + 1 | foo.push(1, 2,);␊ + 2 | foo.push(3, 4,);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2, 3, 4,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1, 2,);␊ + > 2 | foo.push(3, 4,);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(12): foo.push(1, 2, ...a,); foo.push(...b,); + +> Input + + `␊ + 1 | foo.push(1, 2, ...a,);␊ + 2 | foo.push(...b,);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2, ...a, ...b,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1, 2, ...a,);␊ + > 2 | foo.push(...b,);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(13): foo.push(bar()); foo.push(1); + +> Input + + `␊ + 1 | foo.push(bar());␊ + 2 | foo.push(1);␊ + ` + +> Output + + `␊ + 1 | foo.push(bar(), 1);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(bar());␊ + > 2 | foo.push(1);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(14): foo.push(1); foo.push(bar()); + +> Input + + `␊ + 1 | foo.push(1);␊ + 2 | foo.push(bar());␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1);␊ + > 2 | foo.push(bar());␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Merge with previous one.␊ + 1 | foo.push(1, bar());␊ + ` + +## invalid(15): foo.push(1,); foo.push(2,); foo.push(3,); + +> Input + + `␊ + 1 | foo.push(1,);␊ + 2 | foo.push(2,);␊ + 3 | foo.push(3,);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2, 3,);␊ + ` + +> Error 1/2 + + `␊ + 1 | foo.push(1,);␊ + > 2 | foo.push(2,);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 3 | foo.push(3,);␊ + ` + +> Error 2/2 + + `␊ + 1 | foo.push(1,);␊ + 2 | foo.push(2,);␊ + > 3 | foo.push(3,);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(16): if (a) { foo.push(1); foo.push(2); } + +> Input + + `␊ + 1 | if (a) {␊ + 2 | foo.push(1);␊ + 3 | foo.push(2);␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | if (a) {␊ + 2 | foo.push(1, 2);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | if (a) {␊ + 2 | foo.push(1);␊ + > 3 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 4 | }␊ + ` + +## invalid(17): switch (a) { default: foo.push(1); foo.push(2); } + +> Input + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | foo.push(1);␊ + 4 | foo.push(2);␊ + 5 | }␊ + ` + +> Output + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | foo.push(1, 2);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | foo.push(1);␊ + > 4 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 5 | }␊ + ` + +## invalid(18): function a() { foo.push(1); foo.push(2); } + +> Input + + `␊ + 1 | function a() {␊ + 2 | foo.push(1);␊ + 3 | foo.push(2);␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | function a() {␊ + 2 | foo.push(1, 2);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function a() {␊ + 2 | foo.push(1);␊ + > 3 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 4 | }␊ + ` + +## invalid(19): foo.push(1) foo.push(2) ;[foo].forEach(bar) + +> Input + + `␊ + 1 | foo.push(1)␊ + 2 | foo.push(2)␊ + 3 | ;[foo].forEach(bar)␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2);[foo].forEach(bar)␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1)␊ + > 2 | foo.push(2)␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 3 | ;[foo].forEach(bar)␊ + ` + +## invalid(20): foo.bar.push(1); (foo)['bar'].push(2); + +> Input + + `␊ + 1 | foo.bar.push(1);␊ + 2 | (foo)['bar'].push(2);␊ + ` + +> Output + + `␊ + 1 | foo.bar.push(1, 2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.bar.push(1);␊ + > 2 | (foo)['bar'].push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(21): foo.push(1); foo.push(2); stream.push(1); stream.push(2); + +> Input + + `␊ + 1 | foo.push(1);␊ + 2 | foo.push(2);␊ + 3 | stream.push(1);␊ + 4 | stream.push(2);␊ + ` + +> Output + + `␊ + 1 | foo.push(1, 2);␊ + 2 | stream.push(1);␊ + 3 | stream.push(2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.push(1);␊ + > 2 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 3 | stream.push(1);␊ + 4 | stream.push(2);␊ + ` + +## invalid(22): foo.bar.push(1); foo.bar.push(2); foo.push(1); foo.push(2); bar.foo.push(1); bar.foo.push(2); + +> Input + + `␊ + 1 | foo.bar.push(1);␊ + 2 | foo.bar.push(2);␊ + 3 | foo.push(1);␊ + 4 | foo.push(2);␊ + 5 | bar.foo.push(1);␊ + 6 | bar.foo.push(2);␊ + ` + +> Options + + `␊ + [␊ + {␊ + "ignore": [␊ + "foo",␊ + "foo.bar"␊ + ]␊ + }␊ + ]␊ + ` + +> Output + + `␊ + 1 | foo.bar.push(1, 2);␊ + 2 | foo.push(1, 2);␊ + 3 | bar.foo.push(1, 2);␊ + ` + +> Error 1/3 + + `␊ + 1 | foo.bar.push(1);␊ + > 2 | foo.bar.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 3 | foo.push(1);␊ + 4 | foo.push(2);␊ + 5 | bar.foo.push(1);␊ + 6 | bar.foo.push(2);␊ + ` + +> Error 2/3 + + `␊ + 1 | foo.bar.push(1);␊ + 2 | foo.bar.push(2);␊ + 3 | foo.push(1);␊ + > 4 | foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + 5 | bar.foo.push(1);␊ + 6 | bar.foo.push(2);␊ + ` + +> Error 3/3 + + `␊ + 1 | foo.bar.push(1);␊ + 2 | foo.bar.push(2);␊ + 3 | foo.push(1);␊ + 4 | foo.push(2);␊ + 5 | bar.foo.push(1);␊ + > 6 | bar.foo.push(2);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(1): foo.classList.add("foo"); foo.classList.add("bar"); + +> Input + + `␊ + 1 | foo.classList.add("foo");␊ + 2 | foo.classList.add("bar");␊ + ` + +> Output + + `␊ + 1 | foo.classList.add("foo", "bar");␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add("foo");␊ + > 2 | foo.classList.add("bar");␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(2): foo.classList.remove("foo"); foo.classList.remove("bar"); + +> Input + + `␊ + 1 | foo.classList.remove("foo");␊ + 2 | foo.classList.remove("bar");␊ + ` + +> Output + + `␊ + 1 | foo.classList.remove("foo", "bar");␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.remove("foo");␊ + > 2 | foo.classList.remove("bar");␊ + | ^^^^^^ Do not call \`Element#classList.remove()\` multiple times.␊ + ` + +## invalid(3): (foo.classList.add)("foo"); (foo.classList.add)("bar"); + +> Input + + `␊ + 1 | (foo.classList.add)("foo");␊ + 2 | (foo.classList.add)("bar");␊ + ` + +> Output + + `␊ + 1 | (foo.classList.add)("foo", "bar");␊ + ` + +> Error 1/1 + + `␊ + 1 | (foo.classList.add)("foo");␊ + > 2 | (foo.classList.add)("bar");␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(4): foo.bar.classList.add("foo"); foo.bar.classList.add("bar"); + +> Input + + `␊ + 1 | foo.bar.classList.add("foo");␊ + 2 | foo.bar.classList.add("bar");␊ + ` + +> Output + + `␊ + 1 | foo.bar.classList.add("foo", "bar");␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.bar.classList.add("foo");␊ + > 2 | foo.bar.classList.add("bar");␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(5): foo.classList.add("foo"); (foo).classList.add("bar"); + +> Input + + `␊ + 1 | foo.classList.add("foo");␊ + 2 | (foo).classList.add("bar");␊ + ` + +> Output + + `␊ + 1 | foo.classList.add("foo", "bar");␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add("foo");␊ + > 2 | (foo).classList.add("bar");␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(6): foo.classList.add(); foo.classList.add(); + +> Input + + `␊ + 1 | foo.classList.add();␊ + 2 | foo.classList.add();␊ + ` + +> Output + + `␊ + 1 | foo.classList.add();␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add();␊ + > 2 | foo.classList.add();␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(7): foo.classList.add("foo"); foo.classList.add(); + +> Input + + `␊ + 1 | foo.classList.add("foo");␊ + 2 | foo.classList.add();␊ + ` + +> Output + + `␊ + 1 | foo.classList.add("foo");␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add("foo");␊ + > 2 | foo.classList.add();␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(8): foo.classList.add(); foo.classList.add(2); + +> Input + + `␊ + 1 | foo.classList.add();␊ + 2 | foo.classList.add(2);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(2);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add();␊ + > 2 | foo.classList.add(2);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(9): foo.classList.add(a, b); foo.classList.add((c), (d)); + +> Input + + `␊ + 1 | foo.classList.add(a, b);␊ + 2 | foo.classList.add((c), (d));␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b, (c), (d));␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a, b);␊ + > 2 | foo.classList.add((c), (d));␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(10): foo.classList.add.push(a, b,); foo.classList.add.push(c, d); + +> Input + + `␊ + 1 | foo.classList.add.push(a, b,);␊ + 2 | foo.classList.add.push(c, d);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add.push(a, b, c, d);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add.push(a, b,);␊ + > 2 | foo.classList.add.push(c, d);␊ + | ^^^^ Do not call \`Array#push()\` multiple times.␊ + ` + +## invalid(11): foo.classList.add(a, b); foo.classList.add(c, d,); + +> Input + + `␊ + 1 | foo.classList.add(a, b);␊ + 2 | foo.classList.add(c, d,);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b, c, d,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a, b);␊ + > 2 | foo.classList.add(c, d,);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(12): foo.classList.add(a, b,); foo.classList.add(c, d,); + +> Input + + `␊ + 1 | foo.classList.add(a, b,);␊ + 2 | foo.classList.add(c, d,);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b, c, d,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a, b,);␊ + > 2 | foo.classList.add(c, d,);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(13): foo.classList.add(a, b, ...c,); foo.classList.add(...d,); + +> Input + + `␊ + 1 | foo.classList.add(a, b, ...c,);␊ + 2 | foo.classList.add(...d,);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b, ...c, ...d,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a, b, ...c,);␊ + > 2 | foo.classList.add(...d,);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(14): foo.classList.add(bar()); foo.classList.add("foo"); + +> Input + + `␊ + 1 | foo.classList.add(bar());␊ + 2 | foo.classList.add("foo");␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(bar(), "foo");␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(bar());␊ + > 2 | foo.classList.add("foo");␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(15): foo.classList.add(a); foo.classList.add(bar()); + +> Input + + `␊ + 1 | foo.classList.add(a);␊ + 2 | foo.classList.add(bar());␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a);␊ + > 2 | foo.classList.add(bar());␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Merge with previous one.␊ + 1 | foo.classList.add(a, bar());␊ + ` + +## invalid(16): foo.classList.add(a,); foo.classList.add(b,); foo.classList.add(c,); + +> Input + + `␊ + 1 | foo.classList.add(a,);␊ + 2 | foo.classList.add(b,);␊ + 3 | foo.classList.add(c,);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b, c,);␊ + ` + +> Error 1/2 + + `␊ + 1 | foo.classList.add(a,);␊ + > 2 | foo.classList.add(b,);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + 3 | foo.classList.add(c,);␊ + ` + +> Error 2/2 + + `␊ + 1 | foo.classList.add(a,);␊ + 2 | foo.classList.add(b,);␊ + > 3 | foo.classList.add(c,);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(17): if (a) { foo.classList.add(a); foo.classList.add(b); } + +> Input + + `␊ + 1 | if (a) {␊ + 2 | foo.classList.add(a);␊ + 3 | foo.classList.add(b);␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | if (a) {␊ + 2 | foo.classList.add(a, b);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | if (a) {␊ + 2 | foo.classList.add(a);␊ + > 3 | foo.classList.add(b);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + 4 | }␊ + ` + +## invalid(18): switch (a) { default: foo.classList.add(a); foo.classList.add(b); } + +> Input + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | foo.classList.add(a);␊ + 4 | foo.classList.add(b);␊ + 5 | }␊ + ` + +> Output + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | foo.classList.add(a, b);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | foo.classList.add(a);␊ + > 4 | foo.classList.add(b);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + 5 | }␊ + ` + +## invalid(19): function _() { foo.classList.add(a); foo.classList.add(b); } + +> Input + + `␊ + 1 | function _() {␊ + 2 | foo.classList.add(a);␊ + 3 | foo.classList.add(b);␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | function _() {␊ + 2 | foo.classList.add(a, b);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function _() {␊ + 2 | foo.classList.add(a);␊ + > 3 | foo.classList.add(b);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + 4 | }␊ + ` + +## invalid(20): foo.classList.add(a) foo.classList.add(b) ;[foo].forEach(bar) + +> Input + + `␊ + 1 | foo.classList.add(a)␊ + 2 | foo.classList.add(b)␊ + 3 | ;[foo].forEach(bar)␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b);[foo].forEach(bar)␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a)␊ + > 2 | foo.classList.add(b)␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + 3 | ;[foo].forEach(bar)␊ + ` + +## invalid(21): foo.bar.classList.add(a); (foo)['bar'].classList.add(b); + +> Input + + `␊ + 1 | foo.bar.classList.add(a);␊ + 2 | (foo)['bar'].classList.add(b);␊ + ` + +> Output + + `␊ + 1 | foo.bar.classList.add(a, b);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.bar.classList.add(a);␊ + > 2 | (foo)['bar'].classList.add(b);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(1): importScripts("foo.js"); importScripts("bar.js"); + +> Input + + `␊ + 1 | importScripts("foo.js");␊ + 2 | importScripts("bar.js");␊ + ` + +> Output + + `␊ + 1 | importScripts("foo.js", "bar.js");␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts("foo.js");␊ + > 2 | importScripts("bar.js");␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(2): (importScripts)("foo.js"); (importScripts)("bar.js"); + +> Input + + `␊ + 1 | (importScripts)("foo.js");␊ + 2 | (importScripts)("bar.js");␊ + ` + +> Output + + `␊ + 1 | (importScripts)("foo.js", "bar.js");␊ + ` + +> Error 1/1 + + `␊ + 1 | (importScripts)("foo.js");␊ + > 2 | (importScripts)("bar.js");␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(3): importScripts(); importScripts(); + +> Input + + `␊ + 1 | importScripts();␊ + 2 | importScripts();␊ + ` + +> Output + + `␊ + 1 | importScripts();␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts();␊ + > 2 | importScripts();␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(4): importScripts("foo.js"); importScripts(); + +> Input + + `␊ + 1 | importScripts("foo.js");␊ + 2 | importScripts();␊ + ` + +> Output + + `␊ + 1 | importScripts("foo.js");␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts("foo.js");␊ + > 2 | importScripts();␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(5): importScripts(); importScripts(2); + +> Input + + `␊ + 1 | importScripts();␊ + 2 | importScripts(2);␊ + ` + +> Output + + `␊ + 1 | importScripts(2);␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts();␊ + > 2 | importScripts(2);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(6): importScripts(a, b); importScripts((c), (d)); + +> Input + + `␊ + 1 | importScripts(a, b);␊ + 2 | importScripts((c), (d));␊ + ` + +> Output + + `␊ + 1 | importScripts(a, b, (c), (d));␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(a, b);␊ + > 2 | importScripts((c), (d));␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(7): importScripts(a, b,); importScripts(c, d); + +> Input + + `␊ + 1 | importScripts(a, b,);␊ + 2 | importScripts(c, d);␊ + ` + +> Output + + `␊ + 1 | importScripts(a, b, c, d);␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(a, b,);␊ + > 2 | importScripts(c, d);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(8): importScripts(a, b); importScripts(c, d,); + +> Input + + `␊ + 1 | importScripts(a, b);␊ + 2 | importScripts(c, d,);␊ + ` + +> Output + + `␊ + 1 | importScripts(a, b, c, d,);␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(a, b);␊ + > 2 | importScripts(c, d,);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(9): importScripts(a, b,); importScripts(c, d,); + +> Input + + `␊ + 1 | importScripts(a, b,);␊ + 2 | importScripts(c, d,);␊ + ` + +> Output + + `␊ + 1 | importScripts(a, b, c, d,);␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(a, b,);␊ + > 2 | importScripts(c, d,);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(10): foo.classList.add(a, b, ...c,); foo.classList.add(...d,); + +> Input + + `␊ + 1 | foo.classList.add(a, b, ...c,);␊ + 2 | foo.classList.add(...d,);␊ + ` + +> Output + + `␊ + 1 | foo.classList.add(a, b, ...c, ...d,);␊ + ` + +> Error 1/1 + + `␊ + 1 | foo.classList.add(a, b, ...c,);␊ + > 2 | foo.classList.add(...d,);␊ + | ^^^ Do not call \`Element#classList.add()\` multiple times.␊ + ` + +## invalid(11): importScripts(bar()); importScripts("foo.js"); + +> Input + + `␊ + 1 | importScripts(bar());␊ + 2 | importScripts("foo.js");␊ + ` + +> Output + + `␊ + 1 | importScripts(bar(), "foo.js");␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(bar());␊ + > 2 | importScripts("foo.js");␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(12): importScripts(a); importScripts(bar()); + +> Input + + `␊ + 1 | importScripts(a);␊ + 2 | importScripts(bar());␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(a);␊ + > 2 | importScripts(bar());␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Merge with previous one.␊ + 1 | importScripts(a, bar());␊ + ` + +## invalid(13): importScripts(a,); importScripts(b,); importScripts(c,); + +> Input + + `␊ + 1 | importScripts(a,);␊ + 2 | importScripts(b,);␊ + 3 | importScripts(c,);␊ + ` + +> Output + + `␊ + 1 | importScripts(a, b, c,);␊ + ` + +> Error 1/2 + + `␊ + 1 | importScripts(a,);␊ + > 2 | importScripts(b,);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + 3 | importScripts(c,);␊ + ` + +> Error 2/2 + + `␊ + 1 | importScripts(a,);␊ + 2 | importScripts(b,);␊ + > 3 | importScripts(c,);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + ` + +## invalid(14): if (a) { importScripts(a); importScripts(b); } + +> Input + + `␊ + 1 | if (a) {␊ + 2 | importScripts(a);␊ + 3 | importScripts(b);␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | if (a) {␊ + 2 | importScripts(a, b);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | if (a) {␊ + 2 | importScripts(a);␊ + > 3 | importScripts(b);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + 4 | }␊ + ` + +## invalid(15): switch (a) { default: importScripts(a); importScripts(b); } + +> Input + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | importScripts(a);␊ + 4 | importScripts(b);␊ + 5 | }␊ + ` + +> Output + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | importScripts(a, b);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | switch (a) {␊ + 2 | default:␊ + 3 | importScripts(a);␊ + > 4 | importScripts(b);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + 5 | }␊ + ` + +## invalid(16): function _() { importScripts(a); importScripts(b); } + +> Input + + `␊ + 1 | function _() {␊ + 2 | importScripts(a);␊ + 3 | importScripts(b);␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | function _() {␊ + 2 | importScripts(a, b);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function _() {␊ + 2 | importScripts(a);␊ + > 3 | importScripts(b);␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + 4 | }␊ + ` + +## invalid(17): importScripts(a) importScripts(b) ;[foo].forEach(bar) + +> Input + + `␊ + 1 | importScripts(a)␊ + 2 | importScripts(b)␊ + 3 | ;[foo].forEach(bar)␊ + ` + +> Output + + `␊ + 1 | importScripts(a, b);[foo].forEach(bar)␊ + ` + +> Error 1/1 + + `␊ + 1 | importScripts(a)␊ + > 2 | importScripts(b)␊ + | ^^^^^^^^^^^^^ Do not call \`importScripts()\` multiple times.␊ + 3 | ;[foo].forEach(bar)␊ + ` diff --git a/test/snapshots/prefer-single-call.js.snap b/test/snapshots/prefer-single-call.js.snap new file mode 100644 index 0000000000..e576dd99e5 Binary files /dev/null and b/test/snapshots/prefer-single-call.js.snap differ