Skip to content
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

Update: report double extra parens in no-extra-parens (fixes #12127) #12697

Merged
merged 11 commits into from Jan 16, 2020
Merged

Update: report double extra parens in no-extra-parens (fixes #12127) #12697

merged 11 commits into from Jan 16, 2020

Conversation

yeonjuan
Copy link
Member

@yeonjuan yeonjuan commented Dec 21, 2019

What is the purpose of this pull request? (put an "X" next to item)

[x] Bug fix (template)

What changes did you make? (Give an overview)
Fix #12127

I tried to solve issue #12127 by adding just || hasDoubleExcessParens() everywhere, but it had a performance issue when checking ArrayExpression's element nodes.

So, I made a new function(hasExcessParensWithConsiderPrecedence) which checks extra parens with considering the precedence of a node. This function checks isParenthesisedTwice only if the node surrounded by at least one extra paren.

Is there anything you'd like reviewers to focus on?

This pr doesn't change the option's behavior that @mdjermanovic mentioned.

There is also a question of options, do they allow just one pair or more.

@eslint-deprecated eslint-deprecated bot added the triage An ESLint team member will look at this issue soon label Dec 21, 2019
@kaicataldo kaicataldo added accepted There is consensus among the team that this change meets the criteria for inclusion bug ESLint is working incorrectly rule Relates to ESLint's core rules and removed triage An ESLint team member will look at this issue soon labels Dec 22, 2019
Copy link
Member

@kaicataldo kaicataldo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! This generally looks good to me, but I'd like to have at least one other person review before merging.

lib/rules/no-extra-parens.js Outdated Show resolved Hide resolved
lib/rules/no-extra-parens.js Show resolved Hide resolved
Copy link
Member

@mdjermanovic mdjermanovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look very good! I'd like to check the whole rule once again.

lib/rules/no-extra-parens.js Outdated Show resolved Hide resolved
lib/rules/no-extra-parens.js Outdated Show resolved Hide resolved
@mdjermanovic
Copy link
Member

This pr doesn't change the option's behavior that @mdjermanovic mentioned.

There is also a question of options, do they allow just one pair or more.

By the docs, it sounds like any number of extra parens should be allowed when something is excepted by an option.

  • "conditionalAssign": false allows extra parentheses around assignments in conditional test expressions
  • "returnAssign": false allows extra parentheses around assignments in return statements
    ...

There are also cases where double parens are indeed required. For example, conditionalAssign was added to avoid conflicts with no-cond-assign (#3317), and that rule allows assignments in conditional expressions' test conditions only if they're parenthesized twice:

/*eslint no-cond-assign: "error"*/

var a = ((b = c)) ? foo : bar; // ok

var a = (b = c) ? foo : bar; // not ok

So it's probably best to leave that part as is.

@mdjermanovic
Copy link
Member

Ooops, ConditionalExpression(node) doesn't actually check conditionalAssign option, while it probably should.

But it does check returnAssign option, it's might be relevant to read #6095.

@yeonjuan
Copy link
Member Author

yeonjuan commented Dec 26, 2019

@mdjermanovic

Ooops, ConditionalExpression(node) doesn't actually check conditionalAssign option, while it probably should.

Oh. Yes. I got it. The problem has not been discovered because the bug(#12127) allows extra twice parens in those cases.

// Error in the current PR
 {
   code: "var a = ((b = c)) ? foo : bar;",
   options: ["all", { conditionalAssign: false }]
 }

I can fix it, but maybe there are some other undiscovered issues. So can I add more test cases for option?

@mdjermanovic
Copy link
Member

mdjermanovic commented Dec 26, 2019

Oh. Yes. I got it. The problem has not been discovered because the bug(#12127) allows extra twice parens in those cases.

// Error in the current PR
 {
   code: "var a = ((b = c)) ? foo : bar;",
   options: ["all", { conditionalAssign: false }]
 }

Yes, it seems that this wasn't noticed because of #12127 bug.

Now when the bug is going to be fixed, we should ensure that this code stays valid for conditionalAssign: true conditionalAssign: false. Sorry! These options without a prefix are confusing.

I can fix it, but maybe there are some other undiscovered issues. So can I add more test cases for option?

That would be great, thanks!

@yeonjuan
Copy link
Member Author

yeonjuan commented Dec 27, 2019

@mdjermanovic
I fixed it by adding isCondAssignException().
By the way, what do you think about this case? - demo - enforceForArrowConditionals: false

/* eslint no-extra-parens: ["error", "all", { "enforceForArrowConditionals": false }] */

var a = () => (1 ? 2 : 3);
var a = () => ((1 ? 2 : 3));  // Unnecessary parentheses arround expression.

The option(enforceDorArrowConditionals: false) doesn't allow extra twice parens in the actual version.
I think it can be treated in separate PR because it occurs in the actual version and less related to this PR, but I want to know whether it is a bug or not.

By the docs, maybe it is a bug?

"enforceForArrowConditionals": false allows extra parentheses around ternary expressions which are the body of an arrow function

@mdjermanovic
Copy link
Member

mdjermanovic commented Dec 27, 2019

The option(enforceDorArrowConditionals: false) doesn't allow extra twice parens in the actual version.
I think it can be treated in separate PR because it occurs in the actual version and less related to this PR, but I want to know whether it is a bug or not.

I agree, fixing that behavior can be a separate PR (if it's a bug at all).

It looks like the options are inconsistent about this. Some allow only 1 pair of extra parens while the others allow 1, 2, or more. The documentation isn't very specific about this, although it sounds more like that any number of extra parens should be allowed.

It's hard to tell what makes more sense. Probably only 1, except for the special cases such as conditional expressions where the presence of 2 pairs has a meaning for another rule. On the other hand, an option name such as ignoreJSX might imply that the rule should really completely ignore JSX elements and allow any number of extra parens around them.

lib/rules/no-extra-parens.js Outdated Show resolved Hide resolved
@mdjermanovic
Copy link
Member

function checkUnaryUpdate(node) might also need to be changed? E.g., -((a + b))

It could be nice to change SequenceExpression(node) as well, although it's untestable at the moment because single parens are always unnecessary with the actual syntax.

@yeonjuan
Copy link
Member Author

yeonjuan commented Dec 28, 2019

@mdjermanovic Yes!. That should be.
And VariableDeclarator needs to be changed also. - ex) var foo = ((bar, baz));
I'll check all the cases once more and commit. thanks!

@yeonjuan
Copy link
Member Author

yeonjuan commented Dec 30, 2019

@mdjermanovic It seems to cover all. To note,

  1. updated for checking double parens
  • in checkUnaryUpdate
  • in SequenceExpression
  • in VariableDeclarator
  1. updated for refactoring
  • in checkSpreadOperator
  • in checkClass

Thanks :)

Copy link
Member

@mdjermanovic mdjermanovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of notes about **

Maybe we should also fix double parens in MemberExpression(node)?

lib/rules/no-extra-parens.js Outdated Show resolved Hide resolved
lib/rules/no-extra-parens.js Outdated Show resolved Hide resolved
@mdjermanovic
Copy link
Member

Actually, let's do MemberExpression(node) in a separate PR.

This PR has already a lot of changes, and it seems that the logic in MemberExpression(node) needs to be modified (#12740).

@yeonjuan
Copy link
Member Author

yeonjuan commented Jan 4, 2020

@mdjermanovic
Wow. it has really many cases for checking. Thanks, I'll check all once again including what you mentioned

@mdjermanovic
Copy link
Member

One edge case: for (a of ((b, c)));

@mdjermanovic mdjermanovic changed the title Fix: report double extra parens in no-extra-parens (fixes #12127) Update: report double extra parens in no-extra-parens (fixes #12127) Jan 12, 2020
@mdjermanovic
Copy link
Member

Just changed the title to Update: because this change produces more warnings.

Copy link
Member

@mdjermanovic mdjermanovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great work @yeonjuan, this certainly required a lot of effort. Each line is a separate change and there are so many details.

All cases are covered (MemberExpression needs a separate PR).

All changes have tests (some refactored functions already had double parens tests) + regression tests where it seemed appropriate.

Thanks!

Copy link
Member

@kaicataldo kaicataldo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sticking with this! LGTM.

@kaicataldo kaicataldo merged commit ae959b6 into eslint:master Jan 16, 2020
@kaicataldo
Copy link
Member

Thanks for contributing to ESLint!

@yeonjuan yeonjuan deleted the no-extra-paren-double branch January 17, 2020 14:33
montmanu pushed a commit to montmanu/eslint that referenced this pull request Mar 4, 2020
…2127) (eslint#12697)

* Fix: report double extra parens in no-extra-parens (fixes eslint#12127)

* rename function, add comments

* review feedback

* add more test cases

* apply cond-assign-exception to test node only

* add more checking for double parens

* move unaryExpression and exponentiation check

* change comments

* rebase checkClass, add test case for regression

* add invalid test case

* add double parens check for for-of, sequence expression
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Jul 16, 2020
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Jul 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly rule Relates to ESLint's core rules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

no-extra-parens never reports double parens
3 participants