diff --git a/lib/rules/no-promise-executor-return.js b/lib/rules/no-promise-executor-return.js index 23c4bd3e40d..7095edb7176 100644 --- a/lib/rules/no-promise-executor-return.js +++ b/lib/rules/no-promise-executor-return.js @@ -71,22 +71,32 @@ function expressionIsVoid(node) { /** * Fixes the linting error by prepending "void " to the given node + * @param {Object} sourceCode context given by context.sourceCode * @param {ASTNode} node The node to fix. * @param {Object} fixer The fixer object provided by ESLint. * @returns {Array|Object} - An array of fix objects or fix to apply to the node. */ -function voidPrependFixer(node, fixer) { +function voidPrependFixer(sourceCode, node, fixer) { /* - * prepending `void ` will fail if - * the expression is () => void () => {} - * therefore, check if the expression is a function + * prepending `void ` will fail if the node has a lower precedence than void */ - if (node.type === "ArrowFunctionExpression") { - return [ - fixer.insertTextBefore(node, "void ("), - fixer.insertTextAfter(node, ")") - ]; + if (astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression", operator: "void" })) { + + // check if there are parentheses around the node to avoid redundant parentheses + if (!(sourceCode.getTokenBefore(node).value === "(" && sourceCode.getTokenAfter(node).value === ")")) { + return [ + fixer.insertTextBefore(node, "void ("), + fixer.insertTextAfter(node, ")") + ]; + } + } + + if (node.parent.type === "ArrowFunctionExpression") { + const arrowToken = sourceCode.getTokenBefore(node, astUtils.isArrowToken); + const firstToken = sourceCode.getTokenAfter(arrowToken); + + return fixer.insertTextBefore(firstToken, "void "); } return fixer.insertTextBefore(node, "void "); @@ -183,7 +193,7 @@ module.exports = { suggest.push({ messageId: "prependVoid", fix(fixer) { - return voidPrependFixer(node.body, fixer); + return voidPrependFixer(sourceCode, node.body, fixer); } }); } @@ -229,7 +239,7 @@ module.exports = { suggest: [{ messageId: "prependVoid", fix(fixer) { - return voidPrependFixer(node.argument, fixer); + return voidPrependFixer(sourceCode, node.argument, fixer); } }] }); diff --git a/tests/lib/rules/no-promise-executor-return.js b/tests/lib/rules/no-promise-executor-return.js index 68ba77d7512..c1fb4e2b677 100644 --- a/tests/lib/rules/no-promise-executor-return.js +++ b/tests/lib/rules/no-promise-executor-return.js @@ -251,6 +251,24 @@ ruleTester.run("no-promise-executor-return", rule, { "new Promise(r => void 1)", "new Promise(r => {1})" ]), + suggestion({ + code: "new Promise(r => 1 ? 2 : 3)", + options: [{ + allowVoid: true + }] + }, [ + "new Promise(r => void (1 ? 2 : 3))", + "new Promise(r => {1 ? 2 : 3})" + ]), + suggestion({ + code: "new Promise(r => (1 ? 2 : 3))", + options: [{ + allowVoid: true + }] + }, [ + "new Promise(r => void (1 ? 2 : 3))", + "new Promise(r => {(1 ? 2 : 3)})" + ]), suggestion({ code: "new Promise(r => (1))", @@ -258,7 +276,7 @@ ruleTester.run("no-promise-executor-return", rule, { allowVoid: true }] }, [ - "new Promise(r => (void 1))", + "new Promise(r => void (1))", "new Promise(r => {(1)})" ]), suggestion({ @@ -351,7 +369,7 @@ ruleTester.run("no-promise-executor-return", rule, { allowVoid: true }] }, [ - "new Promise(r => ((void 1)))", + "new Promise(r => void ((1)))", "new Promise(r => {((1))})" ]),