diff --git a/rules/no-single-promise-in-promise-methods.js b/rules/no-single-promise-in-promise-methods.js index 94e30744a7..2539e15877 100644 --- a/rules/no-single-promise-in-promise-methods.js +++ b/rules/no-single-promise-in-promise-methods.js @@ -33,6 +33,13 @@ const isPromiseMethodCallWithSingleElementArray = node => && node.arguments[0].elements[0] && node.arguments[0].elements[0].type !== 'SpreadElement'; +const isVariableAssignment = node => ['VariableDeclarator', 'AssignmentExpression'].includes(node.parent.type); + +const isStoredInVariable = node => isVariableAssignment(node) + || (node.parent.type === 'AwaitExpression' && isVariableAssignment(node.parent)); + +const isStoredInArray = node => isMethodCall(node, {methods: ['all']}) && isStoredInVariable(node); + const unwrapAwaitedCallExpression = (callExpression, sourceCode) => fixer => { const [promiseNode] = callExpression.arguments[0].elements; let text = getParenthesizedText(promiseNode, sourceCode); @@ -115,7 +122,8 @@ const switchToPromiseResolve = (callExpression, sourceCode) => function * (fixer /** @param {import('eslint').Rule.RuleContext} context */ const create = context => ({ CallExpression(callExpression) { - if (!isPromiseMethodCallWithSingleElementArray(callExpression)) { + if (!isPromiseMethodCallWithSingleElementArray(callExpression) + || isStoredInArray(callExpression)) { return; } diff --git a/test/no-single-promise-in-promise-methods.mjs b/test/no-single-promise-in-promise-methods.mjs index 4e73df0926..d6034db687 100644 --- a/test/no-single-promise-in-promise-methods.mjs +++ b/test/no-single-promise-in-promise-methods.mjs @@ -6,6 +6,8 @@ const {test} = getTester(import.meta); // `await`ed test.snapshot({ valid: [ + 'const results = await Promise.all([promise])', + 'results = await Promise.all([promise])', ], invalid: [ 'await Promise.all([(0, promise)])', @@ -39,6 +41,10 @@ test.snapshot({ 'await Promise.race([promise])', 'await Promise.all([new Promise(() => {})])', '+await Promise.all([+1])', + 'const results = await Promise.any([promise])', + 'results = await Promise.any([promise])', + 'const results = await Promise.race([promise])', + 'results = await Promise.race([promise])', // ASI, `Promise.all()` is not really `await`ed outdent` @@ -66,6 +72,8 @@ test.snapshot({ 'Promise.all([promise], extraArguments)', 'Promise.all()', 'new Promise.all([promise])', + 'const results = Promise.all([promise])', + 'results = Promise.all([promise])', // We are not checking these cases 'globalThis.Promise.all([promise])', @@ -100,5 +108,9 @@ test.snapshot({ 'Promise.all([promise])[0] ||= 1', 'Promise.all([undefined]).then()', 'Promise.all([null]).then()', + 'const results = Promise.any([promise])', + 'results = Promise.any([promise])', + 'const results = Promise.race([promise])', + 'results = Promise.race([promise])', ], }); diff --git a/test/snapshots/no-single-promise-in-promise-methods.mjs.md b/test/snapshots/no-single-promise-in-promise-methods.mjs.md index 4433570d96..f841bc9317 100644 --- a/test/snapshots/no-single-promise-in-promise-methods.mjs.md +++ b/test/snapshots/no-single-promise-in-promise-methods.mjs.md @@ -655,7 +655,91 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Wrapping single-element array with \`Promise.all()\` is unnecessary.␊ ` -## invalid(32): await Promise.all([(x,y)]) [0].toString() +## invalid(32): const results = await Promise.any([promise]) + +> Input + + `␊ + 1 | const results = await Promise.any([promise])␊ + ` + +> Output + + `␊ + 1 | const results = await promise␊ + ` + +> Error 1/1 + + `␊ + > 1 | const results = await Promise.any([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.any()\` is unnecessary.␊ + ` + +## invalid(33): results = await Promise.any([promise]) + +> Input + + `␊ + 1 | results = await Promise.any([promise])␊ + ` + +> Output + + `␊ + 1 | results = await promise␊ + ` + +> Error 1/1 + + `␊ + > 1 | results = await Promise.any([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.any()\` is unnecessary.␊ + ` + +## invalid(34): const results = await Promise.race([promise]) + +> Input + + `␊ + 1 | const results = await Promise.race([promise])␊ + ` + +> Output + + `␊ + 1 | const results = await promise␊ + ` + +> Error 1/1 + + `␊ + > 1 | const results = await Promise.race([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.race()\` is unnecessary.␊ + ` + +## invalid(35): results = await Promise.race([promise]) + +> Input + + `␊ + 1 | results = await Promise.race([promise])␊ + ` + +> Output + + `␊ + 1 | results = await promise␊ + ` + +> Error 1/1 + + `␊ + > 1 | results = await Promise.race([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.race()\` is unnecessary.␊ + ` + +## invalid(36): await Promise.all([(x,y)]) [0].toString() > Input @@ -1126,3 +1210,122 @@ Generated by [AVA](https://avajs.dev). Suggestion 2/2: Switch to \`Promise.resolve(…)\`.␊ 1 | Promise.resolve(null).then()␊ ` + +## invalid(20): const results = Promise.any([promise]) + +> Input + + `␊ + 1 | const results = Promise.any([promise])␊ + ` + +> Error 1/1 + + `␊ + > 1 | const results = Promise.any([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.any()\` is unnecessary.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Use the value directly.␊ + 1 | const results = promise␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Switch to \`Promise.resolve(…)\`.␊ + 1 | const results = Promise.resolve(promise)␊ + ` + +## invalid(21): results = Promise.any([promise]) + +> Input + + `␊ + 1 | results = Promise.any([promise])␊ + ` + +> Error 1/1 + + `␊ + > 1 | results = Promise.any([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.any()\` is unnecessary.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Use the value directly.␊ + 1 | results = promise␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Switch to \`Promise.resolve(…)\`.␊ + 1 | results = Promise.resolve(promise)␊ + ` + +## invalid(22): const results = Promise.race([promise]) + +> Input + + `␊ + 1 | const results = Promise.race([promise])␊ + ` + +> Error 1/1 + + `␊ + > 1 | const results = Promise.race([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.race()\` is unnecessary.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Use the value directly.␊ + 1 | const results = promise␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Switch to \`Promise.resolve(…)\`.␊ + 1 | const results = Promise.resolve(promise)␊ + ` + +## invalid(23): results = Promise.race([promise]) + +> Input + + `␊ + 1 | results = Promise.race([promise])␊ + ` + +> Error 1/1 + + `␊ + > 1 | results = Promise.race([promise])␊ + | ^^^^^^^^^ Wrapping single-element array with \`Promise.race()\` is unnecessary.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Use the value directly.␊ + 1 | results = promise␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Switch to \`Promise.resolve(…)\`.␊ + 1 | results = Promise.resolve(promise)␊ + ` + +## invalid(32): await Promise.all([(x,y)]) [0].toString() + +> Input + + `␊ + 1 | await Promise.all([(x,y)])␊ + 2 | [0].toString()␊ + ` + +> Error 1/1 + + `␊ + > 1 | await Promise.all([(x,y)])␊ + | ^^^^^^^ Wrapping single-element array with \`Promise.all()\` is unnecessary.␊ + 2 | [0].toString()␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/2: Use the value directly.␊ + 1 | await (x,y)␊ + 2 | [0].toString()␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 2/2: Switch to \`Promise.resolve(…)\`.␊ + 1 | await Promise.resolve((x,y))␊ + 2 | [0].toString()␊ + ` diff --git a/test/snapshots/no-single-promise-in-promise-methods.mjs.snap b/test/snapshots/no-single-promise-in-promise-methods.mjs.snap index 6c58d9ef78..77733b7a1b 100644 Binary files a/test/snapshots/no-single-promise-in-promise-methods.mjs.snap and b/test/snapshots/no-single-promise-in-promise-methods.mjs.snap differ