Skip to content

Commit

Permalink
throw-new-error: Fix an edge case (#1390)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker authored Jun 30, 2021
1 parent 6512fbd commit 806831b
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
19 changes: 17 additions & 2 deletions rules/throw-new-error.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';
const {matches} = require('./selectors/index.js');
const {getParenthesizedRange, isParenthesized} = require('./utils/parentheses.js');
const shouldAddParenthesesToNewExpressionCallee = require('./utils/should-add-parentheses-to-new-expression-callee.js');

const messageId = 'throw-new-error';
const messages = {
Expand Down Expand Up @@ -28,12 +30,25 @@ const selector = [
])
].join('');

const create = () => ({
const create = context => ({
[selector]: node => {
return {
node,
messageId,
fix: fixer => fixer.insertTextBefore(node, 'new ')
* fix(fixer) {
const errorConstructor = node.callee;
const sourceCode = context.getSourceCode();
const range = getParenthesizedRange(errorConstructor, sourceCode);
yield fixer.insertTextBeforeRange(range, 'new ');

if (
!isParenthesized(errorConstructor, sourceCode) &&
shouldAddParenthesesToNewExpressionCallee(errorConstructor)
) {
yield fixer.insertTextBeforeRange(range, '(');
yield fixer.insertTextAfterRange(range, ')');
}
}
};
}
});
Expand Down
32 changes: 32 additions & 0 deletions rules/utils/should-add-parentheses-to-new-expression-callee.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

// Copied from https://github.com/eslint/eslint/blob/aa87329d919f569404ca573b439934552006572f/lib/rules/no-extra-parens.js#L448
/**
Check if a member expression contains a call expression.
@param {ASTNode} node - The `MemberExpression` node to evaluate.
@returns {boolean} true if found, false if not.
*/
function doesMemberExpressionContainCallExpression(node) {
let currentNode = node.object;
let currentNodeType = node.object.type;

while (currentNodeType === 'MemberExpression') {
currentNode = currentNode.object;
currentNodeType = currentNode.type;
}

return currentNodeType === 'CallExpression';
}

/**
Check if parentheses should be added to a `node` when it's used as `callee` of `NewExpression`.
@param {Node} node - The AST node to check.
@returns {boolean}
*/
function shouldAddParenthesesToNewExpressionCallee(node) {
return node.type === 'MemberExpression' && doesMemberExpressionContainCallExpression(node);
}

module.exports = shouldAddParenthesesToNewExpressionCallee;
25 changes: 25 additions & 0 deletions test/throw-new-error.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,31 @@ test({
code: 'throw URIError()',
output: 'throw new URIError()',
errors
},
{
code: 'throw (( URIError() ))',
output: 'throw (( new URIError() ))',
errors
},
{
code: 'throw (( URIError ))()',
output: 'throw new (( URIError ))()',
errors
},
{
code: 'throw getGlobalThis().Error()',
output: 'throw new (getGlobalThis().Error)()',
errors
},
{
code: 'throw utils.getGlobalThis().Error()',
output: 'throw new (utils.getGlobalThis().Error)()',
errors
},
{
code: 'throw (( getGlobalThis().Error ))()',
output: 'throw new (( getGlobalThis().Error ))()',
errors
}
]
});

0 comments on commit 806831b

Please sign in to comment.