diff --git a/docs/rules/no-array-reverse.md b/docs/rules/no-array-reverse.md index 3154fdf64a..2c1c93c7b0 100644 --- a/docs/rules/no-array-reverse.md +++ b/docs/rules/no-array-reverse.md @@ -36,6 +36,10 @@ Pass `allowExpressionStatement: false` to forbid `Array#reverse()` even if it's #### Fail ```js -// eslint unicorn/no-array-reverse: ["error", {"allowExpressionStatement": true}] +// eslint unicorn/no-array-reverse: ["error", {"allowExpressionStatement": false}] array.reverse(); ``` + +## Related rules + +- [unicorn/no-array-sort](./no-array-sort.md) diff --git a/docs/rules/no-array-sort.md b/docs/rules/no-array-sort.md new file mode 100644 index 0000000000..287db5b47f --- /dev/null +++ b/docs/rules/no-array-sort.md @@ -0,0 +1,53 @@ +# Prefer `Array#toSorted()` over `Array#sort()` + +πŸ’Ό This rule is enabled in the βœ… `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config). + +πŸ’‘ This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). + + + + +Prefer using [`Array#toSorted()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSorted) over [`Array#sort()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort). + +`Array#sort()` modifies the original array, while `Array#toSorted()` returns a new reversed array. + +## Examples + +```js +// ❌ +const sorted = [...array].sort(); + +// βœ… +const sorted = [...array].toSorted(); +``` + +```js +// ❌ +const sorted = [...array].sort((a, b) => a - b); + +// βœ… +const sorted = [...array].toSorted((a, b) => a - b); +``` + +## Options + +Type: `object` + +### allowExpressionStatement + +Type: `boolean`\ +Default: `true` + +This rule allows `array.sort()` to be used as an expression statement by default.\ +Pass `allowExpressionStatement: false` to forbid `Array#sort()` even if it's an expression statement. + +#### Fail + +```js +// eslint unicorn/no-array-sort: ["error", {"allowExpressionStatement": false}] +array.sort(); +``` + +## Related rules + +- [unicorn/no-array-reverse](./no-array-reverse.md) diff --git a/readme.md b/readme.md index d1f8b686de..6a3700937f 100644 --- a/readme.md +++ b/readme.md @@ -81,6 +81,7 @@ export default [ | [no-array-method-this-argument](docs/rules/no-array-method-this-argument.md) | Disallow using the `this` argument in array methods. | βœ… | πŸ”§ | πŸ’‘ | | [no-array-reduce](docs/rules/no-array-reduce.md) | Disallow `Array#reduce()` and `Array#reduceRight()`. | βœ… | | | | [no-array-reverse](docs/rules/no-array-reverse.md) | Prefer `Array#toReversed()` over `Array#reverse()`. | βœ… | | πŸ’‘ | +| [no-array-sort](docs/rules/no-array-sort.md) | Prefer `Array#toSorted()` over `Array#sort()`. | βœ… | | πŸ’‘ | | [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. | βœ… | | πŸ’‘ | | [no-console-spaces](docs/rules/no-console-spaces.md) | Do not use leading/trailing space between `console.log` parameters. | βœ… | πŸ”§ | | diff --git a/rules/index.js b/rules/index.js index e6c4278a57..c71396e721 100644 --- a/rules/index.js +++ b/rules/index.js @@ -25,6 +25,7 @@ export {default as 'no-array-for-each'} from './no-array-for-each.js'; export {default as 'no-array-method-this-argument'} from './no-array-method-this-argument.js'; export {default as 'no-array-reduce'} from './no-array-reduce.js'; export {default as 'no-array-reverse'} from './no-array-reverse.js'; +export {default as 'no-array-sort'} from './no-array-sort.js'; export {default as 'no-await-expression-member'} from './no-await-expression-member.js'; export {default as 'no-await-in-promise-methods'} from './no-await-in-promise-methods.js'; export {default as 'no-console-spaces'} from './no-console-spaces.js'; diff --git a/rules/no-array-reverse.js b/rules/no-array-reverse.js index 5321c6b665..d8253a7ed6 100644 --- a/rules/no-array-reverse.js +++ b/rules/no-array-reverse.js @@ -1,109 +1,6 @@ -import {isMethodCall} from './ast/index.js'; -import {getParenthesizedText} from './utils/index.js'; - -const MESSAGE_ID_ERROR = 'no-array-reverse/error'; -const MESSAGE_ID_SUGGESTION_ONLY_FIX_METHOD = 'no-array-reverse/suggestion-only-fix-method'; -const MESSAGE_ID_SUGGESTION_SPREADING_ARRAY = 'no-array-reverse/suggestion-spreading-array'; -const MESSAGE_ID_SUGGESTION_NOT_SPREADING_ARRAY = 'no-array-reverse/suggestion-not-spreading-array'; -const messages = { - [MESSAGE_ID_ERROR]: 'Use `Array#toReversed()` instead of `Array#reverse()`.', - [MESSAGE_ID_SUGGESTION_ONLY_FIX_METHOD]: 'Switch to `.toReversed()`.', - [MESSAGE_ID_SUGGESTION_SPREADING_ARRAY]: 'The spreading object is an array', - [MESSAGE_ID_SUGGESTION_NOT_SPREADING_ARRAY]: 'The spreading object is NOT an array', -}; - -/** @param {import('eslint').Rule.RuleContext} context */ -const create = context => { - const {sourceCode} = context; - const {allowExpressionStatement} = context.options[0]; - - return { - CallExpression(callExpression) { - if (!isMethodCall(callExpression, { - method: 'reverse', - argumentsLength: 0, - optionalCall: false, - })) { - return; - } - - const array = callExpression.callee.object; - - // `[...array].reverse()` - const isSpreadAndReverse = array.type === 'ArrayExpression' - && array.elements.length === 1 - && array.elements[0].type === 'SpreadElement'; - - if (allowExpressionStatement && !isSpreadAndReverse) { - const maybeExpressionStatement = callExpression.parent.type === 'ChainExpression' - ? callExpression.parent.parent - : callExpression.parent; - if (maybeExpressionStatement.type === 'ExpressionStatement') { - return; - } - } - - const reverseProperty = callExpression.callee.property; - const suggestions = []; - const fixMethodName = fixer => fixer.replaceText(reverseProperty, 'toReversed'); - - /* - For `[...array].reverse()`, provide two suggestion, let user choose if the object can be unwrapped, - otherwise only change `.reverse()` to `.toReversed()` - */ - if (isSpreadAndReverse) { - suggestions.push({ - messageId: MESSAGE_ID_SUGGESTION_SPREADING_ARRAY, - * fix(fixer) { - const text = getParenthesizedText(array.elements[0].argument, sourceCode); - yield fixer.replaceText(array, text); - yield fixMethodName(fixer); - }, - }); - } - - suggestions.push({ - messageId: isSpreadAndReverse - ? MESSAGE_ID_SUGGESTION_NOT_SPREADING_ARRAY - : MESSAGE_ID_SUGGESTION_ONLY_FIX_METHOD, - fix: fixMethodName, - }); - - return { - node: reverseProperty, - messageId: MESSAGE_ID_ERROR, - suggest: suggestions, - }; - }, - }; -}; - -const schema = [ - { - type: 'object', - additionalProperties: false, - properties: { - allowExpressionStatement: { - type: 'boolean', - }, - }, - }, -]; +import noArrayMutateRule from './shared/no-array-mutate-rule.js'; /** @type {import('eslint').Rule.RuleModule} */ -const config = { - create, - meta: { - type: 'suggestion', - docs: { - description: 'Prefer `Array#toReversed()` over `Array#reverse()`.', - recommended: true, - }, - hasSuggestions: true, - schema, - defaultOptions: [{allowExpressionStatement: true}], - messages, - }, -}; +const config = noArrayMutateRule('reverse'); export default config; diff --git a/rules/no-array-sort.js b/rules/no-array-sort.js new file mode 100644 index 0000000000..5b95b20ff5 --- /dev/null +++ b/rules/no-array-sort.js @@ -0,0 +1,6 @@ +import noArrayMutateRule from './shared/no-array-mutate-rule.js'; + +/** @type {import('eslint').Rule.RuleModule} */ +const config = noArrayMutateRule('sort'); + +export default config; diff --git a/rules/prevent-abbreviations.js b/rules/prevent-abbreviations.js index ec051a9f42..c836afb3e4 100644 --- a/rules/prevent-abbreviations.js +++ b/rules/prevent-abbreviations.js @@ -100,7 +100,7 @@ const getWordReplacements = (word, {replacements, allowList}) => { .map(name => transform(name)); } - return wordReplacement.length > 0 ? wordReplacement.sort() : []; + return wordReplacement.length > 0 ? wordReplacement.toSorted() : []; }; const getNameReplacements = (name, options, limit = 3) => { diff --git a/rules/shared/no-array-mutate-rule.js b/rules/shared/no-array-mutate-rule.js new file mode 100644 index 0000000000..2b56936d7e --- /dev/null +++ b/rules/shared/no-array-mutate-rule.js @@ -0,0 +1,140 @@ +import {isMethodCall} from '../ast/index.js'; +import {getParenthesizedText} from '../utils/index.js'; + +const MESSAGE_ID_ERROR = 'error'; +const MESSAGE_ID_SUGGESTION_APPLY_REPLACEMENT = 'suggestion-apply-replacement'; +const MESSAGE_ID_SUGGESTION_SPREADING_ARRAY = 'suggestion-spreading-array'; +const MESSAGE_ID_SUGGESTION_NOT_SPREADING_ARRAY = 'suggestion-not-spreading-array'; + +const methods = new Map([ + [ + 'reverse', + { + replacement: 'toReversed', + predicate: callExpression => isMethodCall(callExpression, { + method: 'reverse', + argumentsLength: 0, + optionalCall: false, + }), + }, + ], + [ + 'sort', + { + replacement: 'toSorted', + predicate: callExpression => isMethodCall(callExpression, { + method: 'sort', + maximumArguments: 1, + optionalCall: false, + }), + }, + ], +]); + +const schema = [ + { + type: 'object', + additionalProperties: false, + properties: { + allowExpressionStatement: { + type: 'boolean', + }, + }, + }, +]; + +function noArrayMutateRule(methodName) { + const { + replacement, + predicate, + } = methods.get(methodName); + + const messages = { + [MESSAGE_ID_ERROR]: `Use \`Array#${replacement}()\` instead of \`Array#${methodName}()\`.`, + [MESSAGE_ID_SUGGESTION_APPLY_REPLACEMENT]: `Switch to \`.${replacement}()\`.`, + [MESSAGE_ID_SUGGESTION_SPREADING_ARRAY]: 'The spreading object is an array.', + [MESSAGE_ID_SUGGESTION_NOT_SPREADING_ARRAY]: 'The spreading object is NOT an array.', + }; + + /** @param {import('eslint').Rule.RuleContext} context */ + const create = context => { + const {sourceCode} = context; + const {allowExpressionStatement} = context.options[0]; + + return { + CallExpression(callExpression) { + if (!predicate(callExpression)) { + return; + } + + const array = callExpression.callee.object; + + // `[...array].reverse()` + const isSpreadAndMutate = array.type === 'ArrayExpression' + && array.elements.length === 1 + && array.elements[0].type === 'SpreadElement'; + + if (allowExpressionStatement && !isSpreadAndMutate) { + const maybeExpressionStatement = callExpression.parent.type === 'ChainExpression' + ? callExpression.parent.parent + : callExpression.parent; + if (maybeExpressionStatement.type === 'ExpressionStatement') { + return; + } + } + + const methodProperty = callExpression.callee.property; + const suggestions = []; + const fixMethodName = fixer => fixer.replaceText(methodProperty, replacement); + + /* + For `[...array].reverse()`, provide two suggestions, let user choose if the object can be unwrapped, + otherwise only change `.reverse()` to `.toReversed()` + */ + if (isSpreadAndMutate) { + suggestions.push({ + messageId: MESSAGE_ID_SUGGESTION_SPREADING_ARRAY, + * fix(fixer) { + const text = getParenthesizedText(array.elements[0].argument, sourceCode); + yield fixer.replaceText(array, text); + yield fixMethodName(fixer); + }, + }); + } + + suggestions.push({ + messageId: isSpreadAndMutate + ? MESSAGE_ID_SUGGESTION_NOT_SPREADING_ARRAY + : MESSAGE_ID_SUGGESTION_APPLY_REPLACEMENT, + fix: fixMethodName, + }); + + return { + node: methodProperty, + messageId: MESSAGE_ID_ERROR, + suggest: suggestions, + }; + }, + }; + }; + + /** @type {import('eslint').Rule.RuleModule} */ + const config = { + create, + meta: { + type: 'suggestion', + docs: { + description: `Prefer \`Array#${replacement}()\` over \`Array#${methodName}()\`.`, + recommended: true, + }, + hasSuggestions: true, + schema, + defaultOptions: [{allowExpressionStatement: true}], + messages, + }, + }; + + return config; +} + +export default noArrayMutateRule; diff --git a/scripts/create-rules-index-file.js b/scripts/create-rules-index-file.js index 95055afd90..9c218246ad 100644 --- a/scripts/create-rules-index-file.js +++ b/scripts/create-rules-index-file.js @@ -6,7 +6,7 @@ const DIRECTORY = new URL('../rules/', import.meta.url); const files = fs.readdirSync(DIRECTORY, {withFileTypes: true}) .filter(file => file.isFile() && file.name.endsWith('.js') && file.name !== 'index.js') .map(file => file.name) - .sort(); + .toSorted(); const content = files .map(file => `export {default as '${path.basename(file, '.js')}'} from './${file}';`) diff --git a/test/no-array-sort.js b/test/no-array-sort.js new file mode 100644 index 0000000000..d5cef78d69 --- /dev/null +++ b/test/no-array-sort.js @@ -0,0 +1,45 @@ +import {getTester} from './utils/test.js'; + +const {test} = getTester(import.meta); + +const FORBID_EXPRESSION_OPTIONS = [{allowExpressionStatement: false}]; + +test.snapshot({ + valid: [ + 'sorted =[...array].toSorted()', + 'sorted =array.toSorted()', + 'sorted =[...array].sort', + 'sorted =[...array].sort?.()', + 'array.sort()', + 'array.sort?.()', + 'array?.sort()', + 'if (true) array.sort()', + 'sorted = array.sort(...[])', + 'sorted = array.sort(...[compareFn])', + 'sorted = array.sort(compareFn, extraArgument)', + ], + invalid: [ + 'sorted = [...array].sort()', + 'sorted = [...array]?.sort()', + 'sorted = array.sort()', + 'sorted = array?.sort()', + 'sorted = [...array].sort(compareFn)', + 'sorted = [...array]?.sort(compareFn)', + 'sorted = array.sort(compareFn)', + 'sorted = array?.sort(compareFn)', + { + code: 'array.sort()', + options: FORBID_EXPRESSION_OPTIONS, + }, + { + code: 'array?.sort()', + options: FORBID_EXPRESSION_OPTIONS, + }, + // Don't care about `allowExpression` + { + code: '[...array].sort()', + options: FORBID_EXPRESSION_OPTIONS, + }, + 'sorted = [...(0, array)].sort()', + ], +}); diff --git a/test/snapshots/no-array-reverse.js.md b/test/snapshots/no-array-reverse.js.md index fd7c824165..9738f17845 100644 --- a/test/snapshots/no-array-reverse.js.md +++ b/test/snapshots/no-array-reverse.js.md @@ -19,11 +19,11 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Use \`Array#toReversed()\` instead of \`Array#reverse()\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/2: The spreading object is an array␊ + Suggestion 1/2: The spreading object is an array.␊ 1 | reversed = array.toReversed()␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 2/2: The spreading object is NOT an array␊ + Suggestion 2/2: The spreading object is NOT an array.␊ 1 | reversed = [...array].toReversed()␊ ` @@ -42,11 +42,11 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Use \`Array#toReversed()\` instead of \`Array#reverse()\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/2: The spreading object is an array␊ + Suggestion 1/2: The spreading object is an array.␊ 1 | reversed = array?.toReversed()␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 2/2: The spreading object is NOT an array␊ + Suggestion 2/2: The spreading object is NOT an array.␊ 1 | reversed = [...array]?.toReversed()␊ ` @@ -171,11 +171,11 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Use \`Array#toReversed()\` instead of \`Array#reverse()\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/2: The spreading object is an array␊ + Suggestion 1/2: The spreading object is an array.␊ 1 | array.toReversed()␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 2/2: The spreading object is NOT an array␊ + Suggestion 2/2: The spreading object is NOT an array.␊ 1 | [...array].toReversed()␊ ` @@ -194,10 +194,10 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Use \`Array#toReversed()\` instead of \`Array#reverse()\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/2: The spreading object is an array␊ + Suggestion 1/2: The spreading object is an array.␊ 1 | reversed = (0, array).toReversed()␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 2/2: The spreading object is NOT an array␊ + Suggestion 2/2: The spreading object is NOT an array.␊ 1 | reversed = [...(0, array)].toReversed()␊ ` diff --git a/test/snapshots/no-array-reverse.js.snap b/test/snapshots/no-array-reverse.js.snap index 16914b2d82..48ee6c1e2a 100644 Binary files a/test/snapshots/no-array-reverse.js.snap and b/test/snapshots/no-array-reverse.js.snap differ diff --git a/test/snapshots/no-array-sort.js.md b/test/snapshots/no-array-sort.js.md new file mode 100644 index 0000000000..395a4a4170 --- /dev/null +++ b/test/snapshots/no-array-sort.js.md @@ -0,0 +1,287 @@ +# Snapshot report for `test/no-array-sort.js` + +The actual snapshot is saved in `no-array-sort.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## invalid(1): sorted = [...array].sort() + +> Input + + `␊ + 1 | sorted = [...array].sort()␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = [...array].sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: The spreading object is an array.␊ + 1 | sorted = array.toSorted()␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: The spreading object is NOT an array.␊ + 1 | sorted = [...array].toSorted()␊ + ` + +## invalid(2): sorted = [...array]?.sort() + +> Input + + `␊ + 1 | sorted = [...array]?.sort()␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = [...array]?.sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: The spreading object is an array.␊ + 1 | sorted = array?.toSorted()␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: The spreading object is NOT an array.␊ + 1 | sorted = [...array]?.toSorted()␊ + ` + +## invalid(3): sorted = array.sort() + +> Input + + `␊ + 1 | sorted = array.sort()␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = array.sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`.toSorted()\`.␊ + 1 | sorted = array.toSorted()␊ + ` + +## invalid(4): sorted = array?.sort() + +> Input + + `␊ + 1 | sorted = array?.sort()␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = array?.sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`.toSorted()\`.␊ + 1 | sorted = array?.toSorted()␊ + ` + +## invalid(5): sorted = [...array].sort(compareFn) + +> Input + + `␊ + 1 | sorted = [...array].sort(compareFn)␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = [...array].sort(compareFn)␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: The spreading object is an array.␊ + 1 | sorted = array.toSorted(compareFn)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: The spreading object is NOT an array.␊ + 1 | sorted = [...array].toSorted(compareFn)␊ + ` + +## invalid(6): sorted = [...array]?.sort(compareFn) + +> Input + + `␊ + 1 | sorted = [...array]?.sort(compareFn)␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = [...array]?.sort(compareFn)␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: The spreading object is an array.␊ + 1 | sorted = array?.toSorted(compareFn)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: The spreading object is NOT an array.␊ + 1 | sorted = [...array]?.toSorted(compareFn)␊ + ` + +## invalid(7): sorted = array.sort(compareFn) + +> Input + + `␊ + 1 | sorted = array.sort(compareFn)␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = array.sort(compareFn)␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`.toSorted()\`.␊ + 1 | sorted = array.toSorted(compareFn)␊ + ` + +## invalid(8): sorted = array?.sort(compareFn) + +> Input + + `␊ + 1 | sorted = array?.sort(compareFn)␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = array?.sort(compareFn)␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`.toSorted()\`.␊ + 1 | sorted = array?.toSorted(compareFn)␊ + ` + +## invalid(9): array.sort() + +> Input + + `␊ + 1 | array.sort()␊ + ` + +> Options + + `␊ + [␊ + {␊ + "allowExpressionStatement": false␊ + }␊ + ]␊ + ` + +> Error 1/1 + + `␊ + > 1 | array.sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`.toSorted()\`.␊ + 1 | array.toSorted()␊ + ` + +## invalid(10): array?.sort() + +> Input + + `␊ + 1 | array?.sort()␊ + ` + +> Options + + `␊ + [␊ + {␊ + "allowExpressionStatement": false␊ + }␊ + ]␊ + ` + +> Error 1/1 + + `␊ + > 1 | array?.sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`.toSorted()\`.␊ + 1 | array?.toSorted()␊ + ` + +## invalid(11): [...array].sort() + +> Input + + `␊ + 1 | [...array].sort()␊ + ` + +> Options + + `␊ + [␊ + {␊ + "allowExpressionStatement": false␊ + }␊ + ]␊ + ` + +> Error 1/1 + + `␊ + > 1 | [...array].sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: The spreading object is an array.␊ + 1 | array.toSorted()␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: The spreading object is NOT an array.␊ + 1 | [...array].toSorted()␊ + ` + +## invalid(12): sorted = [...(0, array)].sort() + +> Input + + `␊ + 1 | sorted = [...(0, array)].sort()␊ + ` + +> Error 1/1 + + `␊ + > 1 | sorted = [...(0, array)].sort()␊ + | ^^^^ Use \`Array#toSorted()\` instead of \`Array#sort()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: The spreading object is an array.␊ + 1 | sorted = (0, array).toSorted()␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: The spreading object is NOT an array.␊ + 1 | sorted = [...(0, array)].toSorted()␊ + ` diff --git a/test/snapshots/no-array-sort.js.snap b/test/snapshots/no-array-sort.js.snap new file mode 100644 index 0000000000..ab7d137bf3 Binary files /dev/null and b/test/snapshots/no-array-sort.js.snap differ