Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

New Rule: requireSpacesInsideParenthesizedExpression #1254

Conversation

gibson042
Copy link
Contributor

A proof of concept for distinguishing the several parenthetical productions (statement affix, function definition parameters, function call arguments, and arbitrary expressions), inspired by https://github.com/jquery/sizzle/pull/330/files#r27985694 . This PR implements only requireSpacesInsideParenthesizedExpression, but if you like the concepts herein I will add disallowSpacesInsideParenthesizedExpression so it can merge.

The obvious next step is to introduce similar pairs for SpacesInsideParenthesizedArguments, SpacesInsideParenthesizedParameters, and SpacesInsideParenthesizedStatement (names subject to change, but chosen for convenient alphabetic grouping) in a pattern analogous to that embodied by the "SpacesInFunction" rules but rooted at "SpacesInsideParentheses".

I believe this also relates to existing work:
Ref #1069 (comment)
Ref gh-812
Ref gh-431

@coveralls
Copy link

Coverage Status

Coverage decreased (-1.12%) to 97.97% when pulling 38bbab1 on gibson042:spaces-inside-parenthesized-expression into da3cb06 on jscs-dev:master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-1.07%) to 98.03% when pulling e04a4a9 on gibson042:spaces-inside-parenthesized-expression into da3cb06 on jscs-dev:master.

@gibson042 gibson042 changed the title [POC] requireSpacesInsideParenthesizedExpression: new rule [POC] New Rule: requireSpacesInsideParenthesizedExpression Apr 12, 2015
@gibson042
Copy link
Contributor Author

@jscs-dev is there something more to do for feedback on this?

gibson042 referenced this pull request in jquery/jquery May 4, 2015
- This effectively implements our "Embrace HTML5" option
- Related: http://goo.gl/GcQAtn

Fixes gh-2257
@mrjoelkemp
Copy link
Member

@gibson042 Sorry this slipped through the cracks. This needs to be rebased and the coverage needs to be increased.

@hzoo Does this look good aside from the above issues? I see it's holding up the Idiomatic Preset PR: #1069. Would like to land both (this and Idiomatic) prs.

@gibson042 gibson042 force-pushed the spaces-inside-parenthesized-expression branch from e04a4a9 to ace28ea Compare July 1, 2015 14:36
@gibson042
Copy link
Contributor Author

Rebase complete. Why did the coverage report not pick up use of the new util functions by rules requiring them, though? But at any rate, they are now specifically tested.

@mikesherov
Copy link
Contributor

Why did the coverage report not pick up use of the new util functions by rules requiring them, though?

That's a feature, not a bug. The unit coverage runner, written by @mdevils, explains the philosophy here: https://github.com/unit-coverage/unit-coverage#the-idea

@gibson042
Copy link
Contributor Author

Where does this PR stand? The missing coverage seemed reasonable to me (and consistent with preexisting files), but I can extend it if there's a non-decrease requirement. More than that, though, I want feedback on the approach and the ideas... as noted, this is a POC.

var value = nextToken.value;

// Skip empty parentheses and explicit exceptions
if (value === ')' || value in exceptions) {
Copy link
Member

Choose a reason for hiding this comment

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

Why not set ')' as a default part of the exceptions object? You can then simplify this if statement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because it's only an exception in one direction—if I universally except ")", then the immediately following close-parenthesis logic would erroneously allow "((…))".

@mrjoelkemp
Copy link
Member

This is really great work, @gibson042. Bravo.

@gibson042
Copy link
Contributor Author

Thanks for the review. Am I correct in assuming that this has legs and that I should round it out with the above TokenCategorizer suggestion and disallowSpacesInsideParenthesizedExpression inverse rule?

@gibson042
Copy link
Contributor Author

(and then the SpacesInsideParenthesizedArguments [function call], /SpacesInsideParenthesizedParameters [function definition], and SpacesInsideParenthesizedStatement [if/for/while/etc.] pairs, of course). Any thoughts on the names?

@mrjoelkemp
Copy link
Member

Sounds like a plan to me. Maybe wait for the second go ahead from
@markelog, @hzoo, or @zxqfox.
On Jul 25, 2015 12:46 PM, "Richard Gibson" notifications@github.com wrote:

(and then the SpacesInsideParenthesizedArguments [function call], /
SpacesInsideParenthesizedParameters [function definition], and
SpacesInsideParenthesizedStatement [if/for/while/etc.] pairs, of
course). Any thoughts on the names?


Reply to this email directly or view it on GitHub
#1254 (comment).

'(((function(){ function f(){} if(0) return((f)(0, (1), ((2)))+0); throw(f()+(0)); })))'
);
var closeParens = [];
sharedFile.iterateTokenByValue(')', function(token) {
Copy link
Member

Choose a reason for hiding this comment

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

I believe it should be wrapped to before statement inside this describe.

@gibson042 gibson042 force-pushed the spaces-inside-parenthesized-expression branch from ace28ea to 02404f1 Compare August 20, 2015 15:29
@gibson042
Copy link
Contributor Author

Ok, I believe this is ready. Points for special consideration:

  • comments handling: is configuration like allExcept: ['//', '/*', '*/'] reasonable?
  • naming: ParenthesizedExpression, ParenthesizedArguments, ParenthesizedParameters, and ParenthesizedStatement alphabetize conveniently, but may not be as intuitive as e.g. ParenthesizedExpression, Call(Expression)?Arguments, (Function)?Parameters, and StatementParentheses

@markelog
Copy link
Member

How would we enforce

(options || { x: true } ).x

but disallow

(options || { x: true }).x

?

assert(checker.checkString('(//comment\n foo //comment\n)').getErrorCount() === 1);
});

it('should not look inside comments', function() {
Copy link
Member

Choose a reason for hiding this comment

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

is this description correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. These rules should look only at the characters beginning or ending comments, not at their contents.

@markelog
Copy link
Member

Did you run it on core source?

comments handling: is configuration like allExcept: ['//', '/', '/'] reasonable?

It is for me, don't see any better way

Naming: ParenthesizedExpression, ParenthesizedArguments, ParenthesizedParameters, and ParenthesizedStatement alphabetize conveniently, but may not be as intuitive as e.g. ParenthesizedExpression, Call(Expression)?Arguments, (Function)?Parameters, and StatementParentheses

What would those rules do? Could you give me couple examples?

@gibson042
Copy link
Contributor Author

How would we enforce

(options || { x: true } ).x

but disallow

(options || { x: true }).x

?

I'm not sure I understand... can you provide an English explanation of desired behavior? I've followed the other JSCS patterns, so it's possible to require spaces with a finite set of exceptions and also possible to disallow spaces with a finite set of exceptions, but AFAIK not possible to require spaces only for a finite set of "inside" characters.

Did you run it on core source?

For jQuery? Not yet.

Naming: ParenthesizedExpression, ParenthesizedArguments, ParenthesizedParameters, and ParenthesizedStatement alphabetize conveniently, but may not be as intuitive as e.g. ParenthesizedExpression, Call(Expression)?Arguments, (Function)?Parameters, and StatementParentheses

What would those rules do? Could you give me couple examples?

ParenthesizedArguments or CallArguments or CallExpressionArguments: foo(‸a, b, …‸), foo.bar(‸a, b, …‸), (foo)(‸a, b, …‸), etc.
ParenthesizedParameters or FunctionParameters or Parameters: function(‸a, b, …‸) { … }, function foo(‸a, b, …‸) { … }, etc.
ParenthesizedStatement or StatementParentheses: if (‸…‸), for(‸…; …; …‸), catch (‸x‸), etc.
ParenthesizedExpression: everything else

@gibson042
Copy link
Contributor Author

I'm not sure I understand... can you provide an English explanation of desired behavior? I've followed the other JSCS patterns, so it's possible to require spaces with a finite set of exceptions and also possible to disallow spaces with a finite set of exceptions, but AFAIK not possible to require spaces only for a finite set of "inside" characters.

I stand corrected... disallowSpacesInsideParentheses has an only option, although it appears to be unique. Would it be acceptable to add and/or reassess that outside of this PR?

Did you run it on core source?

For jQuery? Not yet.

I checked master-branch jquery.js with { disallowSpacesInsideParenthesizedExpression: true }, and found over 100 exceptions (which is not surprising, because jQuery will likely use the other three rules and leave this one unspecified... cf. https://github.com/jquery/sizzle/pull/330/files#r27985694 ). However, file analysis took two minutes. I profiled jscs, and traced it down to inefficiencies in estraverse.traverse by way of JsFile#iterate by way of JsFile#getNodeByRange. Not wanting to dive into the dependency, I addressed the outermost of these in e97c8eb, which is technically out of scope for this PR but lowered runtime to 1.5 seconds (a reduction of 99%). If you'd rather see a separate PR for that, I could accommodate.

errors.assert.noWhitespaceBetween({
token: token,
nextToken: nextToken,
message: 'Illegal space after opening grouping round bracket'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose this is also worth calling out. "Round bracket" reads weird to me, but it seems to be the terminology used here.

Copy link
Member

Choose a reason for hiding this comment

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

We had a discussion about it somewhere, for standardizing error output and rule names, in the new approach it would be cool to follow common terminology - https://en.wikipedia.org/wiki/Bracket.

In other words, i think it would be okay to call it "parentheses".

Copy link
Member

Choose a reason for hiding this comment

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

I think it was #698 (comment).

() - parentheses, [] - square brackets/brackets, {} - braces, <> - angle brackets

#538

@markelog
Copy link
Member

Would it be acceptable to add and/or reassess that outside of this PR?

Totally

I addressed the outermost of these in e97c8eb, which is technically out of scope for this PR but lowered runtime to 1.5 seconds (a reduction of 99%).

Wow! That would be great to see it in the new release, i guess another PR would be best.

If no one has any objections, i will land this a bit later today.

Awesomely done Richard!

@gibson042 gibson042 force-pushed the spaces-inside-parenthesized-expression branch from e97c8eb to 5b98b26 Compare August 21, 2015 17:24
@gibson042
Copy link
Contributor Author

"Round bracket" references replaced and getNodeByRange improvement moved to a new PR.

@gibson042 gibson042 changed the title [POC] New Rule: requireSpacesInsideParenthesizedExpression New Rule: requireSpacesInsideParenthesizedExpression Aug 21, 2015
@markelog markelog removed the WIP label Aug 22, 2015
@markelog markelog closed this in 1acc0c0 Aug 22, 2015
@markelog
Copy link
Member

Hooray!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants