Disambiguate unary expr in instanceof and in (#15468)

Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
Luca Casonatoandfisker Cheung authored and GitHub committed 2023-09-28 14:56:55 +08:00
1 parent fa8cb85434
commit b78d7c7d2d
5 files changed
+270 -2

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
#### Disambiguate unary expressions on left hand side of instanceof and in (#15468 by @lucacasonato)
Parentheses are now added around unary expression on the left hand side of
`instanceof` and `in` expressions, to disambiguate the unary on the left hand
side with a unary applying to the entire binary expression.
This helps catch a common mistake where a user intends to write `!("x" in y)`
but instead writes `!"x" in y`, which is really parsed as the nonsensical
`(!"x") in y`.
<!-- prettier-ignore -->
```js
// Input
!"x" in y;
!("x" in y);
// Prettier stable
!"x" in y;
!("x" in y);
// Prettier main
(!"x") in y;
!("x" in y);
```
+13
View File
@@ -241,6 +241,19 @@ function needsParens(path, options) {
return true;
}
break;
// A user typing `!foo instanceof Bar` probably intended
// `!(foo instanceof Bar)`, so format to `(!foo) instance Bar` to what is
// really happening
case "BinaryExpression":
if (
key === "left" &&
(parent.operator === "in" || parent.operator === "instanceof") &&
node.type === "UnaryExpression"
) {
return true;
}
break;
}
switch (node.type) {
@@ -97,7 +97,7 @@ let tests = [
// bogus stuff on LHS
function () {
null in {}; // error
void 0 in {}; // error
(void 0) in {}; // error
({}) in {}; // error
[] in {}; // error
false in []; // error
@@ -107,7 +107,7 @@ let tests = [
function () {
if ("foo" in 123) {
} // error
if (!"foo" in {}) {
if ((!"foo") in {}) {
} // error, !'foo' is a boolean
if (!("foo" in {})) {
}
@@ -424,6 +424,164 @@ if (
================================================================================
`;
exports[`in_instanceof.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
!foo in bar;
(!foo in bar);
!(foo in bar);
(!foo) in bar;
!foo instanceof Bar;
(!foo instanceof Bar);
!(foo instanceof Bar);
(!foo) instanceof Bar;
~foo in bar;
(~foo in bar);
~(foo in bar);
(~foo) in bar;
~foo instanceof Bar;
(~foo instanceof Bar);
~(foo instanceof Bar);
(~foo) instanceof Bar;
+foo in bar;
(+foo in bar);
+(foo in bar);
(+foo) in bar;
+foo instanceof Bar;
(+foo instanceof Bar);
+(foo instanceof Bar);
(+foo) instanceof Bar;
-foo in bar;
(-foo in bar);
-(foo in bar);
(-foo) in bar;
-foo instanceof Bar;
(-foo instanceof Bar);
-(foo instanceof Bar);
(-foo) instanceof Bar;
void 0 in bar;
(void 0 in bar);
void (0 in bar);
(void 0) in bar;
void 0 instanceof bar;
(void 0 instanceof bar);
void (0 instanceof bar);
(void 0) instanceof bar;
delete 0 in bar;
(delete 0 in bar);
delete (0 in bar);
(delete 0) in bar;
delete 0 instanceof bar;
(delete 0 instanceof bar);
delete (0 instanceof bar);
(delete 0) instanceof bar;
typeof 0 in bar;
(typeof 0 in bar);
typeof (0 in bar);
(typeof 0) in bar;
typeof 0 instanceof bar;
(typeof 0 instanceof bar);
typeof (0 instanceof bar);
(typeof 0) instanceof bar;
++x instanceof bar; // not ambiguous, because ++(x instanceof bar) is obviously invalid
!!foo instanceof Bar;
=====================================output=====================================
(!foo) in bar;
(!foo) in bar;
!(foo in bar);
(!foo) in bar;
(!foo) instanceof Bar;
(!foo) instanceof Bar;
!(foo instanceof Bar);
(!foo) instanceof Bar;
(~foo) in bar;
(~foo) in bar;
~(foo in bar);
(~foo) in bar;
(~foo) instanceof Bar;
(~foo) instanceof Bar;
~(foo instanceof Bar);
(~foo) instanceof Bar;
(+foo) in bar;
(+foo) in bar;
+(foo in bar);
(+foo) in bar;
(+foo) instanceof Bar;
(+foo) instanceof Bar;
+(foo instanceof Bar);
(+foo) instanceof Bar;
(-foo) in bar;
(-foo) in bar;
-(foo in bar);
(-foo) in bar;
(-foo) instanceof Bar;
(-foo) instanceof Bar;
-(foo instanceof Bar);
(-foo) instanceof Bar;
(void 0) in bar;
(void 0) in bar;
void (0 in bar);
(void 0) in bar;
(void 0) instanceof bar;
(void 0) instanceof bar;
void (0 instanceof bar);
(void 0) instanceof bar;
(delete 0) in bar;
(delete 0) in bar;
delete (0 in bar);
(delete 0) in bar;
(delete 0) instanceof bar;
(delete 0) instanceof bar;
delete (0 instanceof bar);
(delete 0) instanceof bar;
(typeof 0) in bar;
(typeof 0) in bar;
typeof (0 in bar);
(typeof 0) in bar;
(typeof 0) instanceof bar;
(typeof 0) instanceof bar;
typeof (0 instanceof bar);
(typeof 0) instanceof bar;
++x instanceof bar; // not ambiguous, because ++(x instanceof bar) is obviously invalid
(!!foo) instanceof Bar;
================================================================================
`;
exports[`inline-jsx.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
@@ -0,0 +1,73 @@
!foo in bar;
(!foo in bar);
!(foo in bar);
(!foo) in bar;
!foo instanceof Bar;
(!foo instanceof Bar);
!(foo instanceof Bar);
(!foo) instanceof Bar;
~foo in bar;
(~foo in bar);
~(foo in bar);
(~foo) in bar;
~foo instanceof Bar;
(~foo instanceof Bar);
~(foo instanceof Bar);
(~foo) instanceof Bar;
+foo in bar;
(+foo in bar);
+(foo in bar);
(+foo) in bar;
+foo instanceof Bar;
(+foo instanceof Bar);
+(foo instanceof Bar);
(+foo) instanceof Bar;
-foo in bar;
(-foo in bar);
-(foo in bar);
(-foo) in bar;
-foo instanceof Bar;
(-foo instanceof Bar);
-(foo instanceof Bar);
(-foo) instanceof Bar;
void 0 in bar;
(void 0 in bar);
void (0 in bar);
(void 0) in bar;
void 0 instanceof bar;
(void 0 instanceof bar);
void (0 instanceof bar);
(void 0) instanceof bar;
delete 0 in bar;
(delete 0 in bar);
delete (0 in bar);
(delete 0) in bar;
delete 0 instanceof bar;
(delete 0 instanceof bar);
delete (0 instanceof bar);
(delete 0) instanceof bar;
typeof 0 in bar;
(typeof 0 in bar);
typeof (0 in bar);
(typeof 0) in bar;
typeof 0 instanceof bar;
(typeof 0 instanceof bar);
typeof (0 instanceof bar);
(typeof 0) instanceof bar;
++x instanceof bar; // not ambiguous, because ++(x instanceof bar) is obviously invalid
!!foo instanceof Bar;