From b0a33b73268a6b1f5a25158cc2558089f38b06e6 Mon Sep 17 00:00:00 2001 From: TitanSnow Date: Fri, 10 Aug 2018 01:44:13 +0800 Subject: [PATCH] fix #4963: parens are incorrectly stripped in BindExpression (#4964) * fix #4963 * lint code * fix more incorrectly paren stripping * always need parens when UnaryExpression in BindExpression * lint code --- src/language-js/needs-parens.js | 39 ++++++ .../__snapshots__/jsfmt.spec.js.snap | 130 +++++++++++++++--- tests/bind_expressions/bind_parens.js | 27 ++++ tests/bind_expressions/unary.js | 3 - 4 files changed, 174 insertions(+), 25 deletions(-) delete mode 100644 tests/bind_expressions/unary.js diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 4e46c0a1..d665e7ad 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -140,6 +140,10 @@ function needsParens(path, options) { ) { return true; } + + if (parent.type === "BindExpression" && parent.callee === node) { + return true; + } return false; } @@ -169,6 +173,8 @@ function needsParens(path, options) { ); case "BindExpression": + return true; + case "MemberExpression": return name === "object" && parent.object === node; @@ -558,6 +564,39 @@ function needsParens(path, options) { case "OptionalMemberExpression": return parent.type === "MemberExpression"; + + case "MemberExpression": + if ( + parent.type === "BindExpression" && + name === "callee" && + parent.callee === node + ) { + let object = node.object; + while (object) { + if (object.type === "CallExpression") { + return true; + } + if ( + object.type !== "MemberExpression" && + object.type !== "BindExpression" + ) { + break; + } + object = object.object; + } + } + return false; + + case "BindExpression": + if ( + (parent.type === "BindExpression" && + name === "callee" && + parent.callee === node) || + parent.type === "MemberExpression" + ) { + return true; + } + return false; } return false; diff --git a/tests/bind_expressions/__snapshots__/jsfmt.spec.js.snap b/tests/bind_expressions/__snapshots__/jsfmt.spec.js.snap index e38133cd..0e742033 100644 --- a/tests/bind_expressions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/bind_expressions/__snapshots__/jsfmt.spec.js.snap @@ -30,10 +30,64 @@ exports[`bind_parens.js - babylon-verify 1`] = ` (a || b)::c; a || (b::c); ::obj.prop; +(void 0)::func(); +(+0)::is(-0); +a::(b.c); +a::(b.c()); +a::b.c(); +a::(b.c()()); +a::((b.c())()); +a::(b.c())(); +a::(b.c().d); +a::(c().d.e); +a::(b()); +a::(b::c()); +a::(b()::c); +a::(b().c::d); +a::(b.c::d); +a::(b::c.d); +a::(b.c::d::e); +a::(b::c::d); +a::(b::c::d.e); +a::((b::c::d).e); +a::(void 0); +a::(b.c()::d.e); +a::(b.c::d.e); +a::(b.c::d.e)::f.g; +b.c::d.e; +(b.c::d).e; +(b::c::d).e; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (a || b)::c; a || b::c; ::obj.prop; +(void 0)::func(); +(+0)::is(-0); +a::b.c; +a::(b.c()); +a::b.c(); +a::(b.c()()); +a::(b.c()()); +a::(b.c())(); +a::(b.c().d); +a::(c().d.e); +a::(b()); +a::(b::c()); +a::(b()::c); +a::(b().c::d); +a::(b.c::d); +a::(b::c.d); +a::(b.c::d::e); +a::(b::c::d); +a::(b::c::d.e); +a::(b::c::d).e; +a::(void 0); +a::(b.c()::d.e); +a::(b.c::d.e); +a::(b.c::d.e)::f.g; +b.c::d.e; +(b.c::d).e; +(b::c::d).e; `; @@ -41,10 +95,64 @@ exports[`bind_parens.js - babylon-verify 2`] = ` (a || b)::c; a || (b::c); ::obj.prop; +(void 0)::func(); +(+0)::is(-0); +a::(b.c); +a::(b.c()); +a::b.c(); +a::(b.c()()); +a::((b.c())()); +a::(b.c())(); +a::(b.c().d); +a::(c().d.e); +a::(b()); +a::(b::c()); +a::(b()::c); +a::(b().c::d); +a::(b.c::d); +a::(b::c.d); +a::(b.c::d::e); +a::(b::c::d); +a::(b::c::d.e); +a::((b::c::d).e); +a::(void 0); +a::(b.c()::d.e); +a::(b.c::d.e); +a::(b.c::d.e)::f.g; +b.c::d.e; +(b.c::d).e; +(b::c::d).e; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;(a || b)::c a || b::c ;::obj.prop +;(void 0)::func() +;(+0)::is(-0) +;a::b.c +;a::(b.c()) +;a::b.c() +;a::(b.c()()) +;a::(b.c()()) +;a::(b.c())() +;a::(b.c().d) +;a::(c().d.e) +;a::(b()) +;a::(b::c()) +;a::(b()::c) +;a::(b().c::d) +;a::(b.c::d) +;a::(b::c.d) +;a::(b.c::d::e) +;a::(b::c::d) +;a::(b::c::d.e) +;a::(b::c::d).e +;a::(void 0) +;a::(b.c()::d.e) +;a::(b.c::d.e) +;a::(b.c::d.e)::f.g +;b.c::d.e +;(b.c::d).e +;(b::c::d).e `; @@ -215,25 +323,3 @@ class X { } `; - -exports[`unary.js - babylon-verify 1`] = ` -(void 0)::func(); - -(+0)::is(-0); -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(void 0)::func(); - -(+0)::is(-0); - -`; - -exports[`unary.js - babylon-verify 2`] = ` -(void 0)::func(); - -(+0)::is(-0); -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -;(void 0)::func() - -;(+0)::is(-0) - -`; diff --git a/tests/bind_expressions/bind_parens.js b/tests/bind_expressions/bind_parens.js index 77481c2f..34b4bdcd 100644 --- a/tests/bind_expressions/bind_parens.js +++ b/tests/bind_expressions/bind_parens.js @@ -1,3 +1,30 @@ (a || b)::c; a || (b::c); ::obj.prop; +(void 0)::func(); +(+0)::is(-0); +a::(b.c); +a::(b.c()); +a::b.c(); +a::(b.c()()); +a::((b.c())()); +a::(b.c())(); +a::(b.c().d); +a::(c().d.e); +a::(b()); +a::(b::c()); +a::(b()::c); +a::(b().c::d); +a::(b.c::d); +a::(b::c.d); +a::(b.c::d::e); +a::(b::c::d); +a::(b::c::d.e); +a::((b::c::d).e); +a::(void 0); +a::(b.c()::d.e); +a::(b.c::d.e); +a::(b.c::d.e)::f.g; +b.c::d.e; +(b.c::d).e; +(b::c::d).e; diff --git a/tests/bind_expressions/unary.js b/tests/bind_expressions/unary.js deleted file mode 100644 index 0d624427..00000000 --- a/tests/bind_expressions/unary.js +++ /dev/null @@ -1,3 +0,0 @@ -(void 0)::func(); - -(+0)::is(-0);