From f372aba50a273ad2ec9b013b31b27124bf03f26c Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sun, 4 Feb 2024 20:19:48 -0700 Subject: [PATCH 1/7] 8379: Support ternary branches in prefer-find --- .../eslint-plugin/src/rules/prefer-find.ts | 66 ++++++++++++------ .../tests/rules/prefer-find.test.ts | 68 +++++++++++++++++++ 2 files changed, 115 insertions(+), 19 deletions(-) diff --git a/packages/eslint-plugin/src/rules/prefer-find.ts b/packages/eslint-plugin/src/rules/prefer-find.ts index 154d27d1a864..ff567178989a 100644 --- a/packages/eslint-plugin/src/rules/prefer-find.ts +++ b/packages/eslint-plugin/src/rules/prefer-find.ts @@ -41,20 +41,41 @@ export default createRule({ filterNode: TSESTree.Node; } - function parseIfArrayFilterExpression( + function parseArrayFilterExpressions( expression: TSESTree.Expression, - ): FilterExpressionData | undefined { + ): FilterExpressionData[] { if (expression.type === AST_NODE_TYPES.SequenceExpression) { // Only the last expression in (a, b, [1, 2, 3].filter(condition))[0] matters const lastExpression = nullThrows( expression.expressions.at(-1), 'Expected to have more than zero expressions in a sequence expression', ); - return parseIfArrayFilterExpression(lastExpression); + return parseArrayFilterExpressions(lastExpression); } if (expression.type === AST_NODE_TYPES.ChainExpression) { - return parseIfArrayFilterExpression(expression.expression); + return parseArrayFilterExpressions(expression.expression); + } + + // This is the only reason we're returning a list rather than a single value. + if (expression.type === AST_NODE_TYPES.ConditionalExpression) { + // Both branches of the ternary _must_ return results. + const alternateResult = parseArrayFilterExpressions( + expression.alternate, + ); + if (alternateResult.length === 0) { + return []; + } + + const consequentResult = parseArrayFilterExpressions( + expression.consequent, + ); + if (consequentResult.length === 0) { + return []; + } + + // Accumulate the results from both sides and pass up the chain. + return [...alternateResult, ...consequentResult]; } // Check if it looks like <>(...), but not <>?.(...) @@ -78,16 +99,19 @@ export default createRule({ // As long as the object is a (possibly nullable) array, // this is an Array.prototype.filter expression. if (isArrayish(filteredObjectType)) { - return { - isBracketSyntaxForFilter, - filterNode, - }; + return [ + { + isBracketSyntaxForFilter, + filterNode, + }, + ]; } } } } - return undefined; + // not a filter expression. + return []; } /** @@ -223,8 +247,8 @@ export default createRule({ CallExpression(node): void { const object = getObjectIfArrayAtZeroExpression(node); if (object) { - const filterExpression = parseIfArrayFilterExpression(object); - if (filterExpression) { + const filterExpressions = parseArrayFilterExpressions(object); + if (filterExpressions.length !== 0) { context.report({ node, messageId: 'preferFind', @@ -233,9 +257,11 @@ export default createRule({ messageId: 'preferFindSuggestion', fix: (fixer): TSESLint.RuleFix[] => { return [ - generateFixToReplaceFilterWithFind( - fixer, - filterExpression, + ...filterExpressions.map(filterExpression => + generateFixToReplaceFilterWithFind( + fixer, + filterExpression, + ), ), // Get rid of the .at(0) or ['at'](0). generateFixToRemoveArrayElementAccess( @@ -261,8 +287,8 @@ export default createRule({ ): void { if (isMemberAccessOfZero(node)) { const object = node.object; - const filterExpression = parseIfArrayFilterExpression(object); - if (filterExpression) { + const filterExpressions = parseArrayFilterExpressions(object); + if (filterExpressions.length !== 0) { context.report({ node, messageId: 'preferFind', @@ -271,9 +297,11 @@ export default createRule({ messageId: 'preferFindSuggestion', fix: (fixer): TSESLint.RuleFix[] => { return [ - generateFixToReplaceFilterWithFind( - fixer, - filterExpression, + ...filterExpressions.map(filterExpression => + generateFixToReplaceFilterWithFind( + fixer, + filterExpression, + ), ), // Get rid of the [0]. generateFixToRemoveArrayElementAccess( diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index dddb56f14d34..a21eca8861ed 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -70,6 +70,7 @@ ruleTester.run('prefer-find', rule, { `, "[1, 2, 3].filter(x => x)[Symbol('0')];", "[1, 2, 3].filter(x => x)[Symbol.for('0')];", + '(Math.random < 0.5 ? [1, 2, 3].filter(x => true) : [1, 2, 3])[0];', ], invalid: [ @@ -584,5 +585,72 @@ arr.find(f, thisArg); }, ], }, + { + code: ` +declare const f: any, g: any; +const nestedTernaries = ( + Math.random() < 0.5 + ? Math.random() < 0.5 + ? [1, 2, 3].filter(f) + : []?.filter(x => 'shrug') + : [2, 3, 4]['filter'](g) +).at(0.2); + `, + errors: [ + { + line: 3, + messageId: 'preferFind', + suggestions: [ + { + messageId: 'preferFindSuggestion', + output: ` +declare const f: any, g: any; +const nestedTernaries = ( + Math.random() < 0.5 + ? Math.random() < 0.5 + ? [1, 2, 3].find(f) + : []?.find(x => 'shrug') + : [2, 3, 4]["find"](g) +); + `, + }, + ], + }, + ], + }, + + { + code: ` +declare const f: any, g: any; +const nestedTernariesWithSequenceExpression = ( + Math.random() < 0.5 + ? ('sequence', + 'expression', + Math.random() < 0.5 ? [1, 2, 3].filter(f) : []?.filter(x => 'shrug')) + : [2, 3, 4]['filter'](g) +).at(0.2); + `, + errors: [ + { + line: 3, + messageId: 'preferFind', + suggestions: [ + { + messageId: 'preferFindSuggestion', + output: ` +declare const f: any, g: any; +const nestedTernariesWithSequenceExpression = ( + Math.random() < 0.5 + ? ('sequence', + 'expression', + Math.random() < 0.5 ? [1, 2, 3].find(f) : []?.find(x => 'shrug')) + : [2, 3, 4]["find"](g) +); + `, + }, + ], + }, + ], + }, ], }); From 0db418310e7c08c6784ec674197d2c7df4e929e2 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Fri, 9 Feb 2024 13:59:54 -0700 Subject: [PATCH 2/7] fix codecov --- packages/eslint-plugin/src/rules/prefer-find.ts | 14 +++++++------- .../eslint-plugin/tests/rules/prefer-find.test.ts | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/prefer-find.ts b/packages/eslint-plugin/src/rules/prefer-find.ts index ff567178989a..4461ec21da0a 100644 --- a/packages/eslint-plugin/src/rules/prefer-find.ts +++ b/packages/eslint-plugin/src/rules/prefer-find.ts @@ -60,22 +60,22 @@ export default createRule({ // This is the only reason we're returning a list rather than a single value. if (expression.type === AST_NODE_TYPES.ConditionalExpression) { // Both branches of the ternary _must_ return results. - const alternateResult = parseArrayFilterExpressions( - expression.alternate, + const consequentResult = parseArrayFilterExpressions( + expression.consequent, ); - if (alternateResult.length === 0) { + if (consequentResult.length === 0) { return []; } - const consequentResult = parseArrayFilterExpressions( - expression.consequent, + const alternateResult = parseArrayFilterExpressions( + expression.alternate, ); - if (consequentResult.length === 0) { + if (alternateResult.length === 0) { return []; } // Accumulate the results from both sides and pass up the chain. - return [...alternateResult, ...consequentResult]; + return [...consequentResult, ...alternateResult]; } // Check if it looks like <>(...), but not <>?.(...) diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index a21eca8861ed..d4423aed8a1f 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -71,6 +71,7 @@ ruleTester.run('prefer-find', rule, { "[1, 2, 3].filter(x => x)[Symbol('0')];", "[1, 2, 3].filter(x => x)[Symbol.for('0')];", '(Math.random < 0.5 ? [1, 2, 3].filter(x => true) : [1, 2, 3])[0];', + '(Math.random < 0.5 ? [1, 2, 3].find(x => true) : [1, 2, 3].filter(x => true))[0];', ], invalid: [ From 2200f834eb1cd6155c9f7edd3c0f36f36bada6bb Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Fri, 9 Feb 2024 14:22:09 -0700 Subject: [PATCH 3/7] lintfix --- packages/eslint-plugin/tests/rules/prefer-find.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index d4423aed8a1f..69cec8ee79e7 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -71,7 +71,11 @@ ruleTester.run('prefer-find', rule, { "[1, 2, 3].filter(x => x)[Symbol('0')];", "[1, 2, 3].filter(x => x)[Symbol.for('0')];", '(Math.random < 0.5 ? [1, 2, 3].filter(x => true) : [1, 2, 3])[0];', - '(Math.random < 0.5 ? [1, 2, 3].find(x => true) : [1, 2, 3].filter(x => true))[0];', + ` + (Math.random < 0.5 + ? [1, 2, 3].find(x => true) + : [1, 2, 3].filter(x => true))[0]; + `, ], invalid: [ From 7fd8285a51776eb5dc6e08b1a57b83a78f83cc6d Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Fri, 23 Feb 2024 08:58:54 -0700 Subject: [PATCH 4/7] Update packages/eslint-plugin/tests/rules/prefer-find.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Josh Goldberg ✨ --- packages/eslint-plugin/tests/rules/prefer-find.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index 69cec8ee79e7..4f4425f29912 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -70,9 +70,9 @@ ruleTester.run('prefer-find', rule, { `, "[1, 2, 3].filter(x => x)[Symbol('0')];", "[1, 2, 3].filter(x => x)[Symbol.for('0')];", - '(Math.random < 0.5 ? [1, 2, 3].filter(x => true) : [1, 2, 3])[0];', + '(Math.random() < 0.5 ? [1, 2, 3].filter(x => true) : [1, 2, 3])[0];', ` - (Math.random < 0.5 + (Math.random() < 0.5 ? [1, 2, 3].find(x => true) : [1, 2, 3].filter(x => true))[0]; `, From 9d1b79aa730cc9ffe1a89f13b6ee76de2f7bc948 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Fri, 23 Feb 2024 09:29:51 -0700 Subject: [PATCH 5/7] add some straightforward tests --- .../tests/rules/prefer-find.test.ts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index 4f4425f29912..0b7c5d695d70 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -592,6 +592,52 @@ arr.find(f, thisArg); }, { code: ` +(Math.random() < 0.5 + ? [1, 2, 3].filter(x => false) + : [1, 2, 3].filter(x => true))[0]; + `, + errors: [ + { + line: 2, + messageId: 'preferFind', + suggestions: [ + { + messageId: 'preferFindSuggestion', + output: ` +(Math.random() < 0.5 + ? [1, 2, 3].find(x => false) + : [1, 2, 3].find(x => true)); + `, + }, + ], + }, + ], + }, + { + code: ` +Math.random() < 0.5 + ? [1, 2, 3].find(x => true) + : [1, 2, 3].filter(x => true)[0]; + `, + errors: [ + { + line: 4, + messageId: 'preferFind', + suggestions: [ + { + messageId: 'preferFindSuggestion', + output: ` +Math.random() < 0.5 + ? [1, 2, 3].find(x => true) + : [1, 2, 3].find(x => true); + `, + }, + ], + }, + ], + }, + { + code: ` declare const f: any, g: any; const nestedTernaries = ( Math.random() < 0.5 From f397a3ac4a11ee4791315bfb4abe255b0e922447 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sat, 24 Feb 2024 10:18:20 -0700 Subject: [PATCH 6/7] remove any --- packages/eslint-plugin/tests/rules/prefer-find.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index 0b7c5d695d70..a17aac4ab008 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -638,7 +638,7 @@ Math.random() < 0.5 }, { code: ` -declare const f: any, g: any; +declare const f: (arg0: unknown) => boolean, g: (arg0: unknown) => boolean; const nestedTernaries = ( Math.random() < 0.5 ? Math.random() < 0.5 @@ -655,7 +655,7 @@ const nestedTernaries = ( { messageId: 'preferFindSuggestion', output: ` -declare const f: any, g: any; +declare const f: (arg0: unknown) => boolean, g: (arg0: unknown) => boolean; const nestedTernaries = ( Math.random() < 0.5 ? Math.random() < 0.5 @@ -672,7 +672,7 @@ const nestedTernaries = ( { code: ` -declare const f: any, g: any; +declare const f: (arg0: unknown) => boolean, g: (arg0: unknown) => boolean; const nestedTernariesWithSequenceExpression = ( Math.random() < 0.5 ? ('sequence', @@ -689,7 +689,7 @@ const nestedTernariesWithSequenceExpression = ( { messageId: 'preferFindSuggestion', output: ` -declare const f: any, g: any; +declare const f: (arg0: unknown) => boolean, g: (arg0: unknown) => boolean; const nestedTernariesWithSequenceExpression = ( Math.random() < 0.5 ? ('sequence', From 9e599c0c977993ebf958e4ecc7bd6a23755b8474 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sat, 24 Feb 2024 10:27:42 -0700 Subject: [PATCH 7/7] tweak tests slightly --- .../tests/rules/prefer-find.test.ts | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/prefer-find.test.ts b/packages/eslint-plugin/tests/rules/prefer-find.test.ts index a17aac4ab008..b4773b19182d 100644 --- a/packages/eslint-plugin/tests/rules/prefer-find.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-find.test.ts @@ -638,7 +638,8 @@ Math.random() < 0.5 }, { code: ` -declare const f: (arg0: unknown) => boolean, g: (arg0: unknown) => boolean; +declare const f: (arg0: unknown, arg1: number, arg2: Array) => boolean, + g: (arg0: unknown) => boolean; const nestedTernaries = ( Math.random() < 0.5 ? Math.random() < 0.5 @@ -649,13 +650,14 @@ const nestedTernaries = ( `, errors: [ { - line: 3, + line: 4, messageId: 'preferFind', suggestions: [ { messageId: 'preferFindSuggestion', output: ` -declare const f: (arg0: unknown) => boolean, g: (arg0: unknown) => boolean; +declare const f: (arg0: unknown, arg1: number, arg2: Array) => boolean, + g: (arg0: unknown) => boolean; const nestedTernaries = ( Math.random() < 0.5 ? Math.random() < 0.5 @@ -703,5 +705,27 @@ const nestedTernariesWithSequenceExpression = ( }, ], }, + + { + code: ` +declare const spreadArgs: [(x: unknown) => boolean]; +[1, 2, 3].filter(...spreadArgs).at(0); + `, + errors: [ + { + line: 3, + messageId: 'preferFind', + suggestions: [ + { + messageId: 'preferFindSuggestion', + output: ` +declare const spreadArgs: [(x: unknown) => boolean]; +[1, 2, 3].find(...spreadArgs); + `, + }, + ], + }, + ], + }, ], }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy