Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update: fix MemberExpression handling in no-extra-parens (fixes #9156)
  • Loading branch information
jackyho112 authored and not-an-aardvark committed Sep 15, 2017
1 parent 0c720a3 commit ce1f084
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
45 changes: 41 additions & 4 deletions lib/rules/no-extra-parens.js
Expand Up @@ -336,17 +336,45 @@ module.exports = {
}
}

/**
* Check if a member expression contains a call expression
* @param {ASTNode} node 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";
}

/**
* Evaluate a new call
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkCallNew(node) {
if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node)) {
const hasNewParensException = node.callee.type === "NewExpression" && !isNewExpressionWithParens(node.callee);
const callee = node.callee;

if (hasDoubleExcessParens(node.callee) || !isIIFE(node) && !hasNewParensException) {
if (hasExcessParens(callee) && precedence(callee) >= precedence(node)) {
const hasNewParensException = callee.type === "NewExpression" && !isNewExpressionWithParens(callee);

if (
hasDoubleExcessParens(callee) ||
!isIIFE(node) && !hasNewParensException && !(

// Allow extra parens around a new expression if
// there are intervening parentheses.
callee.type === "MemberExpression" &&
doesMemberExpressionContainCallExpression(callee)
)
) {
report(node.callee);
}
}
Expand Down Expand Up @@ -574,8 +602,10 @@ module.exports = {
LogicalExpression: checkBinaryLogical,

MemberExpression(node) {
const nodeObjHasExcessParens = hasExcessParens(node.object);

if (
hasExcessParens(node.object) &&
nodeObjHasExcessParens &&
precedence(node.object) >= precedence(node) &&
(
node.computed ||
Expand All @@ -589,6 +619,13 @@ module.exports = {
) {
report(node.object);
}

if (nodeObjHasExcessParens &&
node.object.type === "CallExpression" &&
node.parent.type !== "NewExpression") {
report(node.object);
}

if (node.computed && hasExcessParens(node.property)) {
report(node.property);
}
Expand Down
11 changes: 11 additions & 0 deletions tests/lib/rules/no-extra-parens.js
Expand Up @@ -89,6 +89,12 @@ ruleTester.run("no-extra-parens", rule, {
"a(b = c, (d, e))",
"(++a)(b); (c++)(d);",
"new (A())",
"new (foo.Baz().foo)",
"new (foo.baz.bar().foo.baz)",
"new ({}.baz.bar.foo().baz)",
"new (doSomething().baz.bar().foo)",
"new ([][0].baz.foo().bar.foo)",
"new (foo\n.baz\n.bar()\n.foo.baz)",
"new A()()",
"(new A)()",
"(new (Foo || Bar))()",
Expand Down Expand Up @@ -516,11 +522,16 @@ ruleTester.run("no-extra-parens", rule, {
invalid("new (\nfunction(){}\n)", "new \nfunction(){}\n", "FunctionExpression", 1),
invalid("((function foo() {return 1;}))()", "(function foo() {return 1;})()", "FunctionExpression"),
invalid("((function(){ return bar(); })())", "(function(){ return bar(); })()", "CallExpression"),
invalid("(foo()).bar", "foo().bar", "CallExpression"),
invalid("(foo.bar()).baz", "foo.bar().baz", "CallExpression"),
invalid("(foo\n.bar())\n.baz", "foo\n.bar()\n.baz", "CallExpression"),

invalid("new (A)", "new A", "Identifier"),
invalid("(new A())()", "new A()()", "NewExpression"),
invalid("(new A(1))()", "new A(1)()", "NewExpression"),
invalid("((new A))()", "(new A)()", "NewExpression"),
invalid("new (foo\n.baz\n.bar\n.foo.baz)", "new foo\n.baz\n.bar\n.foo.baz", "MemberExpression"),
invalid("new (foo.baz.bar.baz)", "new foo.baz.bar.baz", "MemberExpression"),

invalid("0, (_ => 0)", "0, _ => 0", "ArrowFunctionExpression", 1),
invalid("(_ => 0), 0", "_ => 0, 0", "ArrowFunctionExpression", 1),
Expand Down

0 comments on commit ce1f084

Please sign in to comment.