New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat!: add two more cases to no-implicit-coercion
#17832
Conversation
Hi @gurgunday!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.
To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page. Read more about contributing to ESLint here |
✅ Deploy Preview for docs-eslint canceled.
|
no-implicit-coercion
: add two more casesno-implicit-coercion
: add two more cases
no-implicit-coercion
: add two more casesno-implicit-coercion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put these two cases in the documentation as well? The documentation is at
docs/src/rules/no-implicit-coercion.md
Done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, a good catch. Thank you
I believe that there should be a way to explicitly disable reporting on The full list of options is here: eslint/lib/rules/no-implicit-coercion.js Line 15 in e52b98b
|
Nice catch, added |
I think the main question is whether the current behavior of not reporting these patterns is a bug. If it's a bug, then we should fix it, and we could release this change as a semver-minor bug fix that results in ESLint reporting more errors. If it isn't a bug, but rather an enhancement, then we can't change the default behavior in a minor version. These checks could only be added in a minor version if they're behind an option (or options) that is disabled by default, or in a major version. Also, per our rules policies, stylistic rules are frozen except for bug fixes. Since this is a stylistic rule and these particular patterns are not listed in the documentation, I don't think we can consider this a bug fix. Curious what others think about this. |
To me it's clearly a bug or at least a big inconsistency
and Edit: Also, I thought stylistic meant modifications that don’t alter the AST, at least that’s how Prettier defines it |
I'm more inclined to think this is a error. Because the implicit type conversion here is no different from what is listed in the current document. It doesn't add new functionality, it just fixes missing cases. |
@gurgunday thanks for the submission. Because you didn't fill out an issue template (as mentioned in the PR template) describing whether you think this is a bug or a feature request, it makes it difficult to evaluate as either. In the future, please be sure to include a template, or file an issue first, to help us better evaluate your submission. As mentioned, Given that the PR already is created and has tests, I'm willing to treat this as a bug. |
lib/rules/no-implicit-coercion.js
Outdated
@@ -12,7 +12,7 @@ const astUtils = require("./utils/ast-utils"); | |||
//------------------------------------------------------------------------------ | |||
|
|||
const INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/u; | |||
const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"]; | |||
const ALLOWABLE_OPERATORS = ["~", "!!", "+", "--", "-", "*"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this means -(-expr)
correct? If so, I think this is misleading since this looks like the decrement operator (--
) which does change the value. I think we need to rethink how this is represented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, it does look like that, yeah
I could use -
for both but they are different operators (unary negation and subtraction)
Maybe "-(-)"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use "- -"
with a space in between (as in - -1
) to separate the -
tokens. It's unfortunate that those exceptions to the rule are expressed in terms of operators and not operations, so there is no way to differentiate among +foo
and "" + foo
and foo += ""
when defining exceptions. But since there is already "!!"
as a combination of two operators, "- -"
should make sense, too, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with what you said
I am now looking into the behavior of the rule with the other numeric expressions /* eslint no-implicit-coercion: "error" */
+foo; // error
+123; // ok
+Number(foo); // ok
+parseInt(foo); // ok
+parseFloat(foo); // ok
foo * 1; // error
123 * 1; // ok
Number(foo) * 1; // ok
parseInt(foo) * 1; // ok
parseFloat(foo) * 1; // ok I can think that What the rule is doing here is calling eslint/lib/rules/no-implicit-coercion.js Lines 97 to 106 in e52b98b
Shall we do the same thing with the new cases introduced in this PR? Then, for example, we would no longer flag expressions like |
I still think that enabling these checks by default is a breaking change, so marking this as |
Per our semver policies, a bug fix in a rule that results in ESLint reporting more linting errors is a semver-minor change, so we're using the |
Based on the discussion, marking this as accepted and breaking. |
no-implicit-coercion
no-implicit-coercion
Autofixing const exp = 1n;
-(-exp); // 1n
Number(exp); // 1 This is an edge case, but maybe because of this |
I agree, but isn’t this the case with all Number autofixes? I now believe we should remove it though |
I believe we considered it acceptable for
I think it's fine to introduce the Curious what others think about this. |
My first thought was that the BigInt case had never been considered because the rule itself predates the introduction of eslint/docs/src/_data/rule_versions.json Line 133 in 299bfae
I agree that the current autofix behavior for numbers should be rediscussed. Maybe in another issue? |
I checked the BigInt issues and PRs now, and it was mentioned in #11983 (comment) but there was no further discussion. I agree that we could discuss the current behavior in a separate issue. As for the new check |
lib/rules/no-implicit-coercion.js
Outdated
// -(-foo) | ||
operatorAllowed = options.allow.includes("- -"); | ||
if (!operatorAllowed && options.number && node.operator === "-" && node.argument.type === "UnaryExpression" && node.argument.operator === "-" && !isNumeric(node.argument.argument)) { | ||
report(node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message for this error now becomes "use `undefined` instead".
I think it's fine to keep the recommendation in the message, we can just make the error non-fixable (the third argument passed to report()
should be false
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, apologies, hadn't properly tested my changes
Fixing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
* main: docs: Migrate to v9.0.0 (eslint#17905) docs: Switch to flat config by default (eslint#17840) docs: Update Create a Plugin for flat config (eslint#17826) feat!: add two more cases to `no-implicit-coercion` (eslint#17832) docs: Switch shareable config docs to use flat config (eslint#17827) chore: remove creating an unused instance of Linter in tests (eslint#17902) feat!: Switch Linter to flat config by default (eslint#17851)
I've created a new issue to discuss about the autofix for BigInt values and other edge cases: #17983. |
Prerequisites checklist
What is the purpose of this pull request? (put an "X" next to an item)
What changes did you make? (Give an overview)
Hey everyone, I realized the
no-implicit-coercion
had some missing cases:Subtracting 0 from an expression (
exp - 0
) — I can't image why anyone would do that other than to convert to a number, in fact I know that some use it within Fastify reposUsing the subtraction operator twice (
-(-exp)
) — this is something that would be pretty hard to come by I guess 🤣, but should still be invalidIs there anything you'd like reviewers to focus on?
My first ESLint PR, so not sure if everything is a-ok