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
[Fix #9144] Add aggressive
and conservative
enforced styles for Style/StringConcatenation
cop
#9153
Conversation
This is a small step forward, but I want to be clear that my aim in opening #9144 was simply to show that the + operator could not be trusted to indicate a concatenation operation. What's being addressed in this PR is only my very contrived counterexample. A more common counterexample would be in a form like this: def for_example(a_pathname)
a_pathname + "a_string"
end RuboCop really has no business pretending that string concatenation is the only thing that |
I also don't like the proposed change as I don't think the problem is solvable by ignoring some cases. Fundamentally, the problem is that with operator overloading we can never know what happens in certain cases and we can only guess. The cop is already marked as unsafe because of this. The only thing I can think of is to add a mode that ignores cases where the first operand is not a string literal. |
Yes I had the same thing in mind, but thought
That sounds a lot better. I will change this PR accordingly. |
Cross posting my latest comment from #9144, I think this could be expanded to say "only consider cases where the first and last operands in a chain of def some_fn(var_of_unknown_type)
puts "hello" + "world" # string concatenation
puts var_of_unknown_type + "world" # insufficient info to decide
puts "hello" + var_of_unknown_type # string concatenation (I think? Is there a case where that's not true?)
puts "hello" + var_of_unknown_type + "world" # string concatenation
end |
Style/StringConcatenation
literal_first_operand
enforced-style for Style/StringConcatenation
cop
@bbatsov Changed this PR to use a config option. |
I'm also thinking we can have some more generic names for the enforced style (e.g. |
Ping :-) |
I forgot about this PR. I will fix this in a day or two. |
@tejasbubane another friendly reminder about this PR :-) |
27beed5
to
210b091
Compare
@bbatsov Changes done. Sorry for the delay. |
210b091
to
0895a25
Compare
@@ -15,7 +15,13 @@ module Style | |||
# lines, this cop does not register an offense; instead, | |||
# `Style/LineEndConcatenation` will pick up the offense if enabled. | |||
# | |||
# @example | |||
# Two modes are supported: |
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.
You should also mention how this ties to the cop safety - e.g. with the Pathname
example.
Seems I totally forgot about this myself. After some further thought let's not use |
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.
Overall things look good. We just need to add some safety documentation and adopt some dedicated configuration option for the two modes of operation.
it 'does not register offense' do | ||
expect_no_offenses(<<~RUBY) | ||
user.name + "!!" | ||
user.name + "<" + "user.email" + ">" |
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.
Actually, I would expect an offense here. Not on user.name + "<"
, but on "<" + "user.email"
(and "user.email" + ">"
).
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.
Good catch!
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 disagree.
# yes, I know that a variable called user.name is unlikely to be a Pathname
user.name = Pathname.new("user.name")
result = user.name + "<" + "user.email" + ">"
puts "result is #{result}" # result is user.name/</user.email/>
# which is in no way equivalent to "user.name<user.email>"
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.
@tejasbubane -- I think the fix that was called for here was in error. See my above comment
3871cec
to
e381cbf
Compare
literal_first_operand
enforced-style for Style/StringConcatenation
copaggressive
and conservative
enforced styles for Style/StringConcatenation
cop
cc708b1
to
7932e00
Compare
Review comments fixed.
|
# either the left or right side of `+` is a string literal. | ||
# 2. `conservative` style on the other hand, checks and corrects only if | ||
# left side (receiver of `+` method call) is a string literal. | ||
# This is useful when the receiver is some expression that returns string like `Pathname` |
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.
Pathname.new
returns a Pathname
, not a string. Pathname.new("x") + "y"
also returns a Pathname
.
I think this comment should read
This is useful when the receiver is an object whose
+
operator accepts a string, but does not return a string -- such asPathname
@@ -0,0 +1 @@ | |||
* [#9144](https://github.com/rubocop/rubocop/issues/9144): Add `aggressive` and `conservative` enforced styles for `Style/StringConcatenation` cop. ([@tejasbubane][]) |
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.
Those are not enforced styles, but "modes of operation".
@@ -203,4 +203,36 @@ | |||
RUBY | |||
end | |||
end | |||
|
|||
context 'EnforcedStyle = conservative' do |
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.
Mode
@tejasbubane ping :-) |
…tyle/StringConcatenation` cop Closes rubocop#9144
@bbatsov Minor wording changes done. |
Fixes rubocop#10685. This PR fixes a false positive for `Style/StringConcatenation` when `Mode: conservative` and first operand is not string literal. This also resolves the following feedback: rubocop#9153 (comment) `Mode: conservative` should be allowed considering the possibility that receiver is a `Pathname` object.
Closes #9144
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.