quick-lint / quick-lint-js

quick-lint-js finds bugs in JavaScript programs
https://quick-lint-js.com
GNU General Public License v3.0
1.52k stars 191 forks source link

error on 'x++.toString()' #1208

Open strager opened 5 months ago

strager commented 5 months ago

x++.toString() seems to be invalid JS. Reject it and suggest parentheses.

msharipov commented 5 months ago

@strager Could you please assign this to me?

msharipov commented 5 months ago

@strager This seems to be a more general issue when using a "member of" dot operator or a ?. directly after a postfix operator. For example, this also results in an error:

let x = 3;
console.log((x--).valueOf());  // Works fine, prints "3"
console.log((x--).constructor);  // Works fine, prints "ƒ Number()"
console.log((x--)?.constructor);  // Works fine, prints "ƒ Number()"
console.log(x--.valueOf()); // Invalid syntax
console.log(x--.constructor); // Invalid syntax
console.log(x--?.constructor); // Invalid syntax
msharipov commented 5 months ago

@strager This PR fixes the issue. I am also going to look for any other operators that cause a similar issue when placed after ++ or --. Let me know if you want me to add anything to this.

msharipov commented 5 months ago

@strager After poking around a bit, it looks like there are a number of operators and other tokens that cause a syntax error when placed after -- and ++. Many of these are not properly reported by quick-lint-js. The following is what I've managed to find, though it is unlikely to be an exhaustive list.


Current quick-lint-js Output
Nothing
x++ (y);
x++ [y];
x++ .y;
x++ ?.y;

Current quick-lint-js Output
E0027: missing semicolon after statement
x++ new Type();
x++ ++y;
x++ --y;
x++ !y;  // Also reports E0261
x++ typeof y;
x++ void(y);
x++ delete(y);
x++ yield y;
x++ yield* y;

Current quick-lint-js Output
E0054: unexpected token
x++ ~y;
x++ : y;  // Also reports E0027
x++ ...y;

Current quick-lint-js Output
E0020: invalid expression left of assignment
x++ = y;
x++ += y;
x++ -= y;
x++ *= y;
x++ **= y;
x++ /= y;
x++ %= y;
x++ <<= y;
x++ >>= y;
x++ >>>= y;
x++ &= y;
x++ |= y;
x++ ^= y;
x++ &&= y;
x++ ||= y;

Current quick-lint-js Output
E0151: invalid function parameter
x++ => y;

The cases that report E0020, E0027, and E0151 make sense, while the rest probably need to be fixed.