From 797caee5e0206156be980dbcb1b41dbebbdc4ff2 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 19 Jan 2024 00:53:35 +0800 Subject: [PATCH] `no-array-method-this-argument`: Check `Array.from()` (#2262) --- rules/no-array-method-this-argument.js | 188 +++++++----- test/no-array-method-this-argument.mjs | 37 ++- .../no-array-method-this-argument.mjs.md | 290 +++++++++++++++++- .../no-array-method-this-argument.mjs.snap | Bin 1259 -> 1780 bytes 4 files changed, 427 insertions(+), 88 deletions(-) diff --git a/rules/no-array-method-this-argument.js b/rules/no-array-method-this-argument.js index e865d8109a..58afc6d0da 100644 --- a/rules/no-array-method-this-argument.js +++ b/rules/no-array-method-this-argument.js @@ -7,11 +7,13 @@ const {isNodeMatches} = require('./utils/is-node-matches.js'); const {isNodeValueNotFunction} = require('./utils/index.js'); const {isMethodCall} = require('./ast/index.js'); -const ERROR = 'error'; +const ERROR_PROTOTYPE_METHOD = 'error-prototype-method'; +const ERROR_STATIC_METHOD = 'error-static-method'; const SUGGESTION_BIND = 'suggestion-bind'; const SUGGESTION_REMOVE = 'suggestion-remove'; const messages = { - [ERROR]: 'Do not use the `this` argument in `Array#{{method}}()`.', + [ERROR_PROTOTYPE_METHOD]: 'Do not use the `this` argument in `Array#{{method}}()`.', + [ERROR_STATIC_METHOD]: 'Do not use the `this` argument in `Array.{{method}}()`.', [SUGGESTION_REMOVE]: 'Remove the second argument.', [SUGGESTION_BIND]: 'Use a bound function.', }; @@ -70,107 +72,141 @@ const ignored = [ 'underscore.some', ]; -function removeThisArgument(callExpression, sourceCode) { - return fixer => removeArgument(fixer, callExpression.arguments[1], sourceCode); +function removeThisArgument(thisArgumentNode, sourceCode) { + return fixer => removeArgument(fixer, thisArgumentNode, sourceCode); } -function useBoundFunction(callExpression, sourceCode) { +function useBoundFunction(callbackNode, thisArgumentNode, sourceCode) { return function * (fixer) { - yield removeThisArgument(callExpression, sourceCode)(fixer); + yield removeThisArgument(thisArgumentNode, sourceCode)(fixer); - const [callback, thisArgument] = callExpression.arguments; - - const callbackParentheses = getParentheses(callback, sourceCode); + const callbackParentheses = getParentheses(callbackNode, sourceCode); const isParenthesized = callbackParentheses.length > 0; const callbackLastToken = isParenthesized ? callbackParentheses.at(-1) - : callback; + : callbackNode; if ( !isParenthesized - && shouldAddParenthesesToMemberExpressionObject(callback, sourceCode) + && shouldAddParenthesesToMemberExpressionObject(callbackNode, sourceCode) ) { yield fixer.insertTextBefore(callbackLastToken, '('); yield fixer.insertTextAfter(callbackLastToken, ')'); } - const thisArgumentText = getParenthesizedText(thisArgument, sourceCode); + const thisArgumentText = getParenthesizedText(thisArgumentNode, sourceCode); // `thisArgument` was a argument, no need add extra parentheses yield fixer.insertTextAfter(callbackLastToken, `.bind(${thisArgumentText})`); }; } -/** @param {import('eslint').Rule.RuleContext} context */ -const create = context => { - const {sourceCode} = context; - - return { - CallExpression(callExpression) { - if ( - !isMethodCall(callExpression, { - methods: [ - 'every', - 'filter', - 'find', - 'findLast', - 'findIndex', - 'findLastIndex', - 'flatMap', - 'forEach', - 'map', - 'some', - ], - argumentsLength: 2, - optionalCall: false, - optionalMember: false, - }) - || isNodeMatches(callExpression.callee, ignored) - || isNodeValueNotFunction(callExpression.arguments[0]) - ) { - return; - } - - const {callee} = callExpression; - const method = callee.property.name; - const [callback, thisArgument] = callExpression.arguments; - - const problem = { - node: thisArgument, - messageId: ERROR, - data: {method}, - }; - - const thisArgumentHasSideEffect = hasSideEffect(thisArgument, sourceCode); - const isArrowCallback = callback.type === 'ArrowFunctionExpression'; - - if (isArrowCallback) { - if (thisArgumentHasSideEffect) { - problem.suggest = [ - { - messageId: SUGGESTION_REMOVE, - fix: removeThisArgument(callExpression, sourceCode), - }, - ]; - } else { - problem.fix = removeThisArgument(callExpression, sourceCode); - } - - return problem; - } +function getProblem({ + sourceCode, + callExpression, + callbackNode, + thisArgumentNode, + messageId, +}) { + const problem = { + node: thisArgumentNode, + messageId, + data: { + method: callExpression.callee.property.name, + }, + }; + const isArrowCallback = callbackNode.type === 'ArrowFunctionExpression'; + if (isArrowCallback) { + const thisArgumentHasSideEffect = hasSideEffect(thisArgumentNode, sourceCode); + if (thisArgumentHasSideEffect) { problem.suggest = [ { messageId: SUGGESTION_REMOVE, - fix: removeThisArgument(callExpression, sourceCode), - }, - { - messageId: SUGGESTION_BIND, - fix: useBoundFunction(callExpression, sourceCode), + fix: removeThisArgument(thisArgumentNode, sourceCode), }, ]; + } else { + problem.fix = removeThisArgument(thisArgumentNode, sourceCode); + } + + return problem; + } - return problem; + problem.suggest = [ + { + messageId: SUGGESTION_REMOVE, + fix: removeThisArgument(thisArgumentNode, sourceCode), }, - }; + { + messageId: SUGGESTION_BIND, + fix: useBoundFunction(callbackNode, thisArgumentNode, sourceCode), + }, + ]; + + return problem; +} + +/** @param {import('eslint').Rule.RuleContext} context */ +const create = context => { + const {sourceCode} = context; + + // Prototype methods + context.on('CallExpression', callExpression => { + if ( + !isMethodCall(callExpression, { + methods: [ + 'every', + 'filter', + 'find', + 'findLast', + 'findIndex', + 'findLastIndex', + 'flatMap', + 'forEach', + 'map', + 'some', + ], + argumentsLength: 2, + optionalCall: false, + optionalMember: false, + }) + || isNodeMatches(callExpression.callee, ignored) + || isNodeValueNotFunction(callExpression.arguments[0]) + ) { + return; + } + + return getProblem({ + sourceCode, + callExpression, + callbackNode: callExpression.arguments[0], + thisArgumentNode: callExpression.arguments[1], + messageId: ERROR_PROTOTYPE_METHOD, + }); + }); + + // `Array.from()` + context.on('CallExpression', callExpression => { + if ( + !isMethodCall(callExpression, { + object: 'Array', + method: 'from', + argumentsLength: 3, + optionalCall: false, + optionalMember: false, + }) + || isNodeValueNotFunction(callExpression.arguments[1]) + ) { + return; + } + + return getProblem({ + sourceCode, + callExpression, + callbackNode: callExpression.arguments[1], + thisArgumentNode: callExpression.arguments[2], + messageId: ERROR_STATIC_METHOD, + }); + }); }; /** @type {import('eslint').Rule.RuleModule} */ diff --git a/test/no-array-method-this-argument.mjs b/test/no-array-method-this-argument.mjs index c2f8db1589..6cb708b5c9 100644 --- a/test/no-array-method-this-argument.mjs +++ b/test/no-array-method-this-argument.mjs @@ -9,12 +9,26 @@ test.snapshot({ 'new array.map(() => {}, thisArgument)', 'array.map?.(() => {}, thisArgument)', 'array?.map(() => {}, thisArgument)', + 'Array.unknownMethod(iterableOrArrayLike, () => {}, thisArgument)', + 'new Array.from(iterableOrArrayLike, () => {}, thisArgument)', + 'Array.from?.(iterableOrArrayLike, () => {}, thisArgument)', + 'Array?.from(iterableOrArrayLike, () => {}, thisArgument)', + 'NotArray.from(iterableOrArrayLike, () => {}, thisArgument)', + // More or less arguments 'array.map()', 'array.map(() => {},)', 'array.map(() => {}, ...thisArgument)', 'array.map(...() => {}, thisArgument)', 'array.map(() => {}, thisArgument, extraArgument)', + 'Array.from()', + 'Array.from(iterableOrArrayLike)', + 'Array.from(iterableOrArrayLike, () => {},)', + 'Array.from(iterableOrArrayLike, () => {}, ...thisArgument)', + 'Array.from(iterableOrArrayLike, ...() => {}, thisArgument)', + 'Array.from(...iterableOrArrayLike, () => {}, thisArgument)', + 'Array.from(iterableOrArrayLike, () => {}, thisArgument, extraArgument)', + // Ignored 'lodash.every(array, () => {})', 'lodash.find(array, () => {})', @@ -33,10 +47,13 @@ test.snapshot({ // `jQuery.find` and `jQuery.filter` don't accept second argument '$( "li" ).filter( ":nth-child(2n)" ).css( "background-color", "red" );', '$( "li.item-ii" ).find( "li" ).css( "background-color", "red" );', - // First argument is not function + // Callback argument is not function 'array.map(new Callback, thisArgument)', 'array.map(1, thisArgument)', 'async () => array.map(await callback, thisArgument)', + 'Array.from(iterableOrArrayLike, new Callback, thisArgument)', + 'Array.from(iterableOrArrayLike, 1, thisArgument)', + 'Array.from(iterableOrArrayLike, await callback, thisArgument)', ], invalid: [ 'array.every(() => {}, thisArgument)', @@ -48,11 +65,14 @@ test.snapshot({ 'array.flatMap(() => {}, thisArgument)', 'array.forEach(() => {}, thisArgument)', 'array.map(() => {}, thisArgument)', + 'Array.from(iterableOrArrayLike, () => {}, thisArgument)', // Comma 'array.map(() => {}, thisArgument,)', 'array.map(() => {}, (0, thisArgument),)', + 'Array.from(iterableOrArrayLike, () => {}, thisArgument,)', // Side effect 'array.map(() => {}, thisArgumentHasSideEffect())', + 'Array.from(iterableOrArrayLike, () => {}, thisArgumentHasSideEffect())', ], }); @@ -61,21 +81,36 @@ test.snapshot({ valid: [], invalid: [ 'array.map(callback, thisArgument)', + 'Array.from(iterableOrArrayLike, callback, thisArgument)', 'array.map(callback, (0, thisArgument))', + 'Array.from(iterableOrArrayLike, callback, (0, thisArgument))', 'array.map(function () {}, thisArgument)', + 'Array.from(iterableOrArrayLike, function () {}, thisArgument)', 'array.map(function callback () {}, thisArgument)', + 'Array.from(iterableOrArrayLike, function callback () {}, thisArgument)', { code: 'array.map( foo as bar, (( thisArgument )),)', parser: parsers.typescript, }, + { + code: 'Array.from(iterableOrArrayLike, foo as bar, (( thisArgument )),)', + parser: parsers.typescript, + }, { code: 'array.map( (( foo as bar )), (( thisArgument )),)', parser: parsers.typescript, }, + { + code: 'Array.from(iterableOrArrayLike, (( foo as bar )), (( thisArgument )),)', + parser: parsers.typescript, + }, 'array.map( (( 0, callback )), (( thisArgument )),)', + 'Array.from(iterableOrArrayLike, (( 0, callback )), (( thisArgument )),)', // This callback is actually arrow function, but we don't know 'array.map((0, () => {}), thisArgument)', + 'Array.from(iterableOrArrayLike, (0, () => {}), thisArgument)', // This callback is a bound function, but we don't know 'array.map(callback.bind(foo), thisArgument)', + 'Array.from(iterableOrArrayLike, callback.bind(foo), thisArgument)', ], }); diff --git a/test/snapshots/no-array-method-this-argument.mjs.md b/test/snapshots/no-array-method-this-argument.mjs.md index 1bea6b9f43..9d9e3c3993 100644 --- a/test/snapshots/no-array-method-this-argument.mjs.md +++ b/test/snapshots/no-array-method-this-argument.mjs.md @@ -193,7 +193,28 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array#map()\`.␊ ` -## invalid(10): array.map(() => {}, thisArgument,) +## invalid(10): Array.from(iterableOrArrayLike, () => {}, thisArgument) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, () => {}, thisArgument)␊ + ` + +> Output + + `␊ + 1 | Array.from(iterableOrArrayLike, () => {})␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, () => {}, thisArgument)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ` + +## invalid(11): array.map(() => {}, thisArgument,) > Input @@ -214,7 +235,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array#map()\`.␊ ` -## invalid(11): array.map(() => {}, (0, thisArgument),) +## invalid(12): array.map(() => {}, (0, thisArgument),) > Input @@ -235,7 +256,28 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array#map()\`.␊ ` -## invalid(12): array.map(() => {}, thisArgumentHasSideEffect()) +## invalid(13): Array.from(iterableOrArrayLike, () => {}, thisArgument,) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, () => {}, thisArgument,)␊ + ` + +> Output + + `␊ + 1 | Array.from(iterableOrArrayLike, () => {},)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, () => {}, thisArgument,)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ` + +## invalid(14): array.map(() => {}, thisArgumentHasSideEffect()) > Input @@ -254,6 +296,25 @@ Generated by [AVA](https://avajs.dev). 1 | array.map(() => {})␊ ` +## invalid(15): Array.from(iterableOrArrayLike, () => {}, thisArgumentHasSideEffect()) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, () => {}, thisArgumentHasSideEffect())␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, () => {}, thisArgumentHasSideEffect())␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, () => {})␊ + ` + ## invalid(1): array.map(callback, thisArgument) > Input @@ -277,7 +338,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map(callback.bind(thisArgument))␊ ` -## invalid(2): array.map(callback, (0, thisArgument)) +## invalid(2): Array.from(iterableOrArrayLike, callback, thisArgument) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, callback, thisArgument)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, callback, thisArgument)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, callback)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, callback.bind(thisArgument))␊ + ` + +## invalid(3): array.map(callback, (0, thisArgument)) > Input @@ -300,7 +384,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map(callback.bind((0, thisArgument)))␊ ` -## invalid(3): array.map(function () {}, thisArgument) +## invalid(4): Array.from(iterableOrArrayLike, callback, (0, thisArgument)) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, callback, (0, thisArgument))␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, callback, (0, thisArgument))␊ + | ^^^^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, callback)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, callback.bind((0, thisArgument)))␊ + ` + +## invalid(5): array.map(function () {}, thisArgument) > Input @@ -323,7 +430,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map(function () {}.bind(thisArgument))␊ ` -## invalid(4): array.map(function callback () {}, thisArgument) +## invalid(6): Array.from(iterableOrArrayLike, function () {}, thisArgument) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, function () {}, thisArgument)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, function () {}, thisArgument)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, function () {})␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, function () {}.bind(thisArgument))␊ + ` + +## invalid(7): array.map(function callback () {}, thisArgument) > Input @@ -346,7 +476,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map(function callback () {}.bind(thisArgument))␊ ` -## invalid(5): array.map( foo as bar, (( thisArgument )),) +## invalid(8): Array.from(iterableOrArrayLike, function callback () {}, thisArgument) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, function callback () {}, thisArgument)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, function callback () {}, thisArgument)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, function callback () {})␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, function callback () {}.bind(thisArgument))␊ + ` + +## invalid(9): array.map( foo as bar, (( thisArgument )),) > Input @@ -369,7 +522,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map( (foo as bar).bind((( thisArgument ))),)␊ ` -## invalid(6): array.map( (( foo as bar )), (( thisArgument )),) +## invalid(10): Array.from(iterableOrArrayLike, foo as bar, (( thisArgument )),) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, foo as bar, (( thisArgument )),)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, foo as bar, (( thisArgument )),)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, foo as bar,)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, (foo as bar).bind((( thisArgument ))),)␊ + ` + +## invalid(11): array.map( (( foo as bar )), (( thisArgument )),) > Input @@ -392,7 +568,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map( (( foo as bar )).bind((( thisArgument ))),)␊ ` -## invalid(7): array.map( (( 0, callback )), (( thisArgument )),) +## invalid(12): Array.from(iterableOrArrayLike, (( foo as bar )), (( thisArgument )),) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, (( foo as bar )), (( thisArgument )),)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, (( foo as bar )), (( thisArgument )),)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, (( foo as bar )),)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, (( foo as bar )).bind((( thisArgument ))),)␊ + ` + +## invalid(13): array.map( (( 0, callback )), (( thisArgument )),) > Input @@ -415,7 +614,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map( (( 0, callback )).bind((( thisArgument ))),)␊ ` -## invalid(8): array.map((0, () => {}), thisArgument) +## invalid(14): Array.from(iterableOrArrayLike, (( 0, callback )), (( thisArgument )),) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, (( 0, callback )), (( thisArgument )),)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, (( 0, callback )), (( thisArgument )),)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, (( 0, callback )),)␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, (( 0, callback )).bind((( thisArgument ))),)␊ + ` + +## invalid(15): array.map((0, () => {}), thisArgument) > Input @@ -438,7 +660,30 @@ Generated by [AVA](https://avajs.dev). 1 | array.map((0, () => {}).bind(thisArgument))␊ ` -## invalid(9): array.map(callback.bind(foo), thisArgument) +## invalid(16): Array.from(iterableOrArrayLike, (0, () => {}), thisArgument) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, (0, () => {}), thisArgument)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, (0, () => {}), thisArgument)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, (0, () => {}))␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, (0, () => {}).bind(thisArgument))␊ + ` + +## invalid(17): array.map(callback.bind(foo), thisArgument) > Input @@ -460,3 +705,26 @@ Generated by [AVA](https://avajs.dev). Suggestion 2/2: Use a bound function.␊ 1 | array.map(callback.bind(foo).bind(thisArgument))␊ ` + +## invalid(18): Array.from(iterableOrArrayLike, callback.bind(foo), thisArgument) + +> Input + + `␊ + 1 | Array.from(iterableOrArrayLike, callback.bind(foo), thisArgument)␊ + ` + +> Error 1/1 + + `␊ + > 1 | Array.from(iterableOrArrayLike, callback.bind(foo), thisArgument)␊ + | ^^^^^^^^^^^^ Do not use the \`this\` argument in \`Array.from()\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Remove the second argument.␊ + 1 | Array.from(iterableOrArrayLike, callback.bind(foo))␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Use a bound function.␊ + 1 | Array.from(iterableOrArrayLike, callback.bind(foo).bind(thisArgument))␊ + ` diff --git a/test/snapshots/no-array-method-this-argument.mjs.snap b/test/snapshots/no-array-method-this-argument.mjs.snap index 2887aae2ae125acdaca804a4f40a0da9d1466cc8..cace8729956bab82ebd965bcd51961415aff9198 100644 GIT binary patch literal 1780 zcmV(Wuv_NsVzy9 zP9_9~=O2p*00000000B+TuW~oRTNI9LKWGuV!`WHsK{;{C$>|ZgeGYqfkbK&Ddtfm zs4}+4$tccDG&7D`C<_7-0)$jl2?0W?$PXyLfc^s5uwa9P!~%BgKtin0)E;||=ght5 z-f?Q<)XPNv?#cI>$Gz>hwQ}9A?73f_J2pJis~guRP3usvo7Ge>HMsHeE|UaCdFb{ouG-)jj>{?3t0XBmQUfk&(wn$Hy4U zv6~dAF{7@Rjk>XB9W=Za*f;=tiUSsWy|&r#I^X{y{C(}Ck+B8xG>kEJli{Chp$}WO znPq#d;Tp`_HQ2Tfv(5At5Hl^dz2vX=Y;(QzcD6ODx#Bps!*Y|kfc>d}{d}AKnpyV@ zhfe<-U@QX|<6~j`X8_vMJTzQ@uYdrbKmi2v@Dxy#ptT}TgKVHdA*6v-r7JK4IJ?lr zSv(TP{{?{cWIPtm{%yeihu!RRX5nzJ%Dh$O@?Hpdp9Z|ISykgYo&0$~*kpt-E*z%7 zBmg`o0K{cD1~S}^%D|tBn}bAxG}q;+k`Gk52voVEyB=MXOMt^{ghL)0rb!myF+LtH z$sHict*9j2nFNZc3vz!|o*u@Bv~Q-sIlSp*B@Bp1L%`yPmPHxNyAYRW|>vB1r_cnWu(+H-_ZWh5V3cu2AjEdUFb z=yM>^5j9tt2Oq5IHtqQs+EY_qj={L+J+lbmPC$UKfdHTK1i%L3Wa1k9^iGMDwh{&9 zio>MY08Cy^)N#00m%$2o*%fdF?*RqBOV)CHNgrg*&9_yaCe+-j?v~7|u~MrU6)%+z zse9C->1DwE46*dOaS>JD90kx?agwj^72B$|$H@xsyP{4gwViNLIqzbByaoKRktqEn*L)0I^Ui3Z+)8+f)Yb_@JqQ+) zy?5k1y}%o-ie9gm^~zrCP4f})=_LjTb<2;yE%%}w69+~sm4R!Kyj+U}e|`F7=gRwY zz2+KBXJxx#RavcJRs7$?Pn0eDFT;T*@s4{byeA|wFxiJ{4{s9g)Sd(Gd|V@TnY?FD z$v_0-*nK%@pJHmdxf&u({ zXwJ*yBjP(RE*x6TzXOy19Ia+Pq{z?1)XtEJep@weE~(pvweY^U$o!ICEdj5t5ECZt zU~K_7c#>Mv$$Z^IxBtJIdayzuH?34OE=3O^fUpIZ0%96OFHLEm9agZ}3>2S5zz6pF^2EH#z7k`h^@bFSFSkX}&TPjdR{4@@$ z**4Q%R@R*iOQnFLSQ_kN2dUwmCnQ0lclCdQX#5(zB#2=}{vW1`K$wkw+cz{-sxwx) z^~4!bs^fsDOV_1NFv)xOb>Q7qYW@@qt-S~gT_AUTQkS3FZXcXL2zMV7req=J6qs+A z4zzC9?~vv#A)l1kTk7W25M9#nTg)kXWM&m)W)6)%1sTo9S&)x^@Jj*- zotTATyC`&V({GFOhEuWgtKj%2AwX&#e;aswlb%;)>$iZnIqQL6IRQQ00emgd1EVV7%9Aytz z&ZcSyZDh@>f&Y9%8z&ce0!yFX+8!kTOARZPikWsQis(VeCRok3#UT*Ap%+4;h5a}1 z{2%d0BI98x79XbSjxy43|MF&&vg=0Mu9O{G1rxskOuVLa+>K~$4gBjrZBh2zWHQ5_ W+F~EPbjVLk%FKU*wv*<5O#lE!pkj{z literal 1259 zcmVJEe$O*!&z$|H)AEA$?da)&jNRCica~g#UwE!#)$COeVJPla+ta>Wr%m&Xd~S2?n*zl-N+Yv(M}LY4-Onh#Nxx16LY8Ll576t-0AuAC4d^-Gl?om zPqd^bZ}@xNxF2>Ng}ugvr62FS*Numte>VF0g-_>7>&DXn0Nexmx;1ja)d2h;hHfMw z-jT4C#B71+2Z8Iu)<$x_w+`=TZ&muEx|?Abgiu?mrR`VK_UnW8JFXYY(7gUt)L0oc z#%EFemr>g5TpA7FO9bFE3_vpvN1z~r{vA06m6Snagn{pv6Ie!_og3>cJBjN59LhSA zokh3*1hxNgynSXCru(AJ`wrWCBklbH>ivfA$UElcuc5-0l)~6Jiog;Id{YxhV>mz< zo~Ri3so3Y>NI(wn%TcMPR4yVa?}#WihjImVSW!CU(kLbslm~nsjpR8(@<>I(&ZHqy z9LS5iay*(Tk4p-VoKMOIDzQP9nEPpIpwP1hp){Uv5uWEXo})cAM+c>UdTJ@H=8%>r z;&;WKIj760(nVY;A4U;cL~(DhaWtE+5t}c@*k~r=sTAbVzo!w2LSqKS~`-;*P;n37l-kl4-hJTy^lHmZ#Yq6pY1>eb9By8TC}{rk9mZj$Wg zi?zP1aew$uS2d`-oO4UdCFR}HqAa@g$Efw5Y3t?xzV-`)+G`oLTh%c&sP4HPtu}4~ z0KP&1KIZ^X12N0aEqomxiM0WVy1@f*T|_rsM{agHvK?FY2$EjEg11qF%Z87`crL-_ zqj?m)(405aTgf(){m6}%7LWNV-Ry2}%P4jOKOwjZ@5|j_|8Sg0wgcZ8j8oCB*UXm> zek9w%^ID>PJM+t@XZYol5k#W?0ipg*MV%EksfBF9FzfkXrvJS?*}3Y;TpvUd1hj&# z??9*Px0AnQPgH3oXBmh|wsCd!NDs4B7D+-o?gd(xM!NSia_@W2JtA?EYxqkE^GK+| z$u_Z}9&9Fo>8-%Bx$Sq)a67`rkuLs*T>MFOk&k3#oVhg-H!(d@;<<9Ik5|-VUzC{o zZm6ejYi5>9dAjfl^7J3ZQ$AZK>};EhyO~0T@qoEpZmNgnNi=kV07L{W5thNSkPcv@ zm%g6C;jB?4xzhfD4E{wmSRea;T5U($m>yBV8jfZ6cL55ip#jX>@Fi@iHTn-Hv<+Ro zhFo1C1~v*N*W44x*gpwl4a3bA-I=miX=a)n9-FO*$Ls2kD`|GMJY2@jMZS(iUL~hC zNhVD`g-rgNHrXiMaQ`rCE{}CHT{7e0ir8FNf1rACq*X1$;8;t$`_-KjaB1X@;a6ns zkHm2#m#8symJCHbOplvrtYUlF74qEbFsl;;dMR~#S#2a~=3mIn-?LA!vSUpa(php; VZDe{xRcAA@^