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

Rule Proposal: Inverse of ConditionalAssignment #2828

Closed
ptarjan opened this issue Feb 10, 2016 · 7 comments
Closed

Rule Proposal: Inverse of ConditionalAssignment #2828

ptarjan opened this issue Feb 10, 2016 · 7 comments

Comments

@ptarjan
Copy link
Contributor

ptarjan commented Feb 10, 2016

We'd like to ban all conditional assignment. Can we get an option to invert this? Basically we want all

# bad
foo = if bar
  1
else
  2
end

to become

# good
if bar
  foo = 1
else
  foo = 2
end
@bbatsov
Copy link
Collaborator

bbatsov commented Feb 10, 2016

I'm fine with the suggestion. @rrosenblum can you tackle this?

@rrosenblum
Copy link
Contributor

I can code up this change. It is going to take a while to implement. There are a ton of test cases for this. Also, the code for the cop is going to need to be cleaned up quite a bit. If I remember correctly, this cop is at limit for most of the Metrics cops.

@rrosenblum
Copy link
Contributor

I have the new configuration for the cop functionally complete. I need to do some refactoring to reduce the complexity.

@rrosenblum
Copy link
Contributor

I hit a bit of a snag with this. Assignment using a send method to a ternary operator, does not parse the same way as operator assignment.

Example:

bar = foo? ? 1 : 2

# parses as: bar = foo? ? 1 : 2

s(:ivasgn, :@bar,
  s(:if,
    s(:send, nil, :foo?),
    s(:int, 1),
    s(:int, 2))
bar << foo? ? 1 : 2

# parses as: "bar << foo?"

s(:send,
  s(:send, nil, :bar), :<<,
  s(:send, nil, :foo?))

# node.parent  
# "bar << foo? ? 1 : 2"

s(:if,
  s(:send,
    s(:send, nil, :bar), :<<,
    s(:send, nil, :foo?)),
  s(:int, 1),
  s(:int, 2))

This isn't a problem for registering an offense, but it is a problem for auto-correcting. I have a few ideas on how to account for this.

@rrosenblum
Copy link
Contributor

I figured out why the ternary operation was not parsing the way that I thought it would. The issue is order of operations. Reading bar << foo? ? 1 : 2, I was assuming that the result of the ternary operation was getting shoveled into bar, but in actuality, the result of bar << foo? is being used as the condition for the ternary operator.

Using parentheses to show it off

bar << foo? ? 1 : 2

is actually

(bar << foo?) ? 1 : 2

when what I really wanted is

bar << (foo? ? 1 : 2)

I need to check the auto-correction of ternary operators for the current use case of this cop. We might be introducing bugs with the correction.

@ptarjan
Copy link
Contributor Author

ptarjan commented Mar 4, 2016

Good catch @rrosenblum and thanks for working on this

@bbatsov
Copy link
Collaborator

bbatsov commented Mar 20, 2016

Fixed in #2915.

@bbatsov bbatsov closed this as completed Mar 20, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants