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

False positive from Lint/UselessAssignment with if/unless modifier #3591

Closed
savef opened this issue Oct 9, 2016 · 11 comments
Closed

False positive from Lint/UselessAssignment with if/unless modifier #3591

savef opened this issue Oct 9, 2016 · 11 comments
Labels

Comments

@savef
Copy link
Contributor

savef commented Oct 9, 2016

Variable assignments in if and unless modifiers can be regarded as useless if they are only used in the conditional expression. See the examples below.


Expected behavior

The following examples should not be treated as useless assignments.

Actual behavior

The following examples are in fact treated as useless assignments.

Steps to reproduce the problem

Put this in a file and run RuboCop on it:

# frozen_string_literal: true

a.to_f if (a = 123)
b.to_f if /(?<b>\d+)/ =~ '123'

You'll see this:

$ bin/rubocop -D x.rb 
Inspecting 1 file
W

Offenses:

x.rb:3:12: W: Lint/UselessAssignment: Useless assignment to variable - a.
a.to_f if (a = 123)
           ^
x.rb:4:11: W: Lint/UselessAssignment: Useless assignment to variable - b.
b.to_f if /(?<b>\d+)/ =~ '123'
          ^^^^^^^^^^^

1 file inspected, 2 offenses detected

RuboCop version

$ rubocop -V
0.43.0 (using Parser 2.3.1.4, running on ruby 2.3.0 x86_64-linux)
@mikegee
Copy link
Contributor

mikegee commented Oct 10, 2016

I confirmed the reported behavior and the following equivalent code does not have UselessAssignment offenses:

if (a = 123)
  a.to_f
end

if /(?<b>\d+)/ =~ '123'
  b.to_f
end

@jonas054
Copy link
Collaborator

If you run the program

puts a if (a = 123)

you'll get

/tmp/3591.rb:1: warning: found = in conditional, should be ==
/tmp/3591.rb:1:in `<main>': undefined local variable or method `a' for main:Object (NameError)

and pretty much the same for

puts b if /(?<b>\d+)/ =~ '123'

so it's not entirely wrong to say that it's a useless assignment.

That doesn't mean that there are no bugs in Lint::UselessAssignment, though. Running rubocop on

a = b = nil
puts a if (a = 123)
puts b if /(?<b>\d+)/ =~ '456'

we get

/tmp/3591.rb:1:1: W: Useless assignment to variable - a.
a = b = nil
^
/tmp/3591.rb:1:5: W: Useless assignment to variable - b.
a = b = nil
    ^

and in that case the assignments are necessary to create the scope for a and b.

@jonas054 jonas054 added the bug label Nov 13, 2016
@dominicsayers
Copy link
Contributor

Still an issue with Rubocop 0.47.1 (using Parser 2.4.0.0, running on ruby 2.4.0 x86_64-linux)

@triplepointfive
Copy link

Looks like the same error with loop modifiers, e.g.

d = nil
puts(d) while (d = a.pop)

This gives false complain

3.rb:1:1: W: Lint/UselessAssignment: Useless assignment to variable - d.
d = nil
^

Reproducing in 0.63.1 (using Parser 2.6.0.0, running on ruby 2.6.0 x86_64-darwin18)

@TheDeepestSpace
Copy link

Same problem with assignments in map or each:

a = [1, 2, 3, 4]
a.map! { |e| e = 42 }

This code results with:

x.rb:2:11: W: Lint/UnusedBlockArgument: Unused block argument - e. You can omit the argument if you don't care about it.
a.map! { |e| e = 4 }
          ^
x.rb:2:14: W: Lint/UselessAssignment: Useless assignment to variable - e.
a.map! { |e| e = 4 }
             ^

(the first offense is dropped if using something like e = e == 42 ? 0 : e)

0.67.2 (using Parser 2.6.2.0, running on ruby 2.5.1 x86_64-linux)

@mikegee
Copy link
Contributor

mikegee commented Apr 29, 2019

@TheDeepestSpace I don't think Rubocop is wrong to complain about your example. This code behaves exactly the same as your example:

a = [1, 2, 3, 4]
a.map! { 42 }

In both examples, a becomes [42, 42, 42, 42] and e is undefined outside the block.

@TheDeepestSpace
Copy link

Good catch, @mikegee. Thanks for the clarification.

@stale
Copy link

stale bot commented Jul 28, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

@stale stale bot added the stale Issues that haven't been active in a while label Jul 28, 2019
@stale
Copy link

stale bot commented Aug 27, 2019

This issues been automatically closed due to lack of activity. Feel free to re-open it if you ever come back to it.

@stale stale bot closed this as completed Aug 27, 2019
@jonas054
Copy link
Collaborator

jonas054 commented Sep 2, 2019

I think I have a solution. PR coming up.

@jonas054 jonas054 reopened this Sep 2, 2019
@stale stale bot removed the stale Issues that haven't been active in a while label Sep 2, 2019
jonas054 added a commit to jonas054/rubocop that referenced this issue Sep 8, 2019
Assignments in modifier if/unless conditions are special. The following program
exits with the error "undefined local variable or method `a' for main:Object"
when executed.

```
puts a if (a = @x)
```

A preceding assignment to `a` is needed to put it in scope. So there are no
useless assignments in

```
a = nil
puts a if (a = @x)
```
@Drenmi
Copy link
Collaborator

Drenmi commented Sep 9, 2019

Nice one @jonas054! I can review your PR once I am back from my vacation. 🙂

tas50 added a commit to chef/cookstyle that referenced this issue Oct 30, 2019
This resolves a large number of warnings and gives us a new cop for
automatically migrating the namespace of the cop disables in comments

* [#7407](rubocop/rubocop#7407): Make `Style/FormatStringToken` work inside hashes. ([@buehmann][])
* [#7389](rubocop/rubocop#7389): Fix an issue where passing a formatter might result in an error depending on what character it started with. ([@jfhinchcliffe][])
* [#7397](rubocop/rubocop#7397): Fix extra comments being added to the correction of `Style/SafeNavigation`. ([@rrosenblum][])
* [#7378](rubocop/rubocop#7378): Fix heredoc edge cases in `Layout/EmptyLineAfterGuardClause`. ([@gsamokovarov][])
* [#7404](rubocop/rubocop#7404): Fix a false negative for `Layout/IndentAssignment` when multiple assignment with line breaks on each line. ([@koic][])
* [#7256](rubocop/rubocop#7256): Fix an error of `Style/RedundantParentheses` on method calls where the first argument begins with a hash literal. ([@halfwhole][])
* [#7263](rubocop/rubocop#7263): Make `Layout/SpaceInsideArrayLiteralBrackets` properly handle tab-indented arrays. ([@buehmann][])
* [#7252](rubocop/rubocop#7252): Prevent infinite loops by making `Layout/SpaceInsideStringInterpolation` skip over interpolations that start or end with a line break. ([@buehmann][])
* [#7262](rubocop/rubocop#7262): `Lint/FormatParameterMismatch` did not recognize named format sequences like `%.2<name>f` where the name appears after some modifiers. ([@buehmann][])
* [#7253](rubocop/rubocop#7253): Fix an error for `Lint/NumberConversion` when `#to_i` called without a receiver. ([@koic][])
* [#7271](rubocop/rubocop#7271), [#6498](rubocop/rubocop#6498): Fix an interference between `Style/TrailingCommaIn*Literal` and `Layout/Multiline*BraceLayout` for arrays and hashes. ([@buehmann][])
* [#7241](rubocop/rubocop#7241): Make `Style/FrozenStringLiteralComment` match only true & false. ([@tejasbubane][])
* [#7290](rubocop/rubocop#7290): Handle inner conditional inside `else` in `Style/ConditionalAssignment`. ([@jonas054][])
* [#5788](rubocop/rubocop#5788): Allow block arguments on separate lines if line would be too long in `Layout/MultilineBlockLayout`. ([@jonas054][])
* [#7305](rubocop/rubocop#7305): Register `Style/BlockDelimiters` offense when block result is assigned to an attribute. ([@mvz][])
* [#4802](rubocop/rubocop#4802): Don't leave any `Lint/UnneededCopEnableDirective` offenses undetected/uncorrected. ([@jonas054][])
* [#7326](rubocop/rubocop#7326): Fix a false positive for `Style/AccessModifierDeclarations` when access modifier name is used for hash literal value. ([@koic][])
* [#3591](rubocop/rubocop#3591): Handle modifier `if`/`unless` correctly in `Lint/UselessAssignment`. ([@jonas054][])
* [#7161](rubocop/rubocop#7161): Fix `Style/SafeNavigation` cop for preserve comments inside if expression. ([@tejasbubane][])
* [#5212](rubocop/rubocop#5212): Avoid false positive for braces that are needed to preserve semantics in `Style/BracesAroundHashParameters`. ([@jonas054][])
* [#7353](rubocop/rubocop#7353): Fix a false positive for `Style/RedundantSelf` when receiver and multiple assigned lvalue have the same name. ([@koic][])
* [#7353](rubocop/rubocop#7353): Fix a false positive for `Style/RedundantSelf` when a self receiver is used as a method argument. ([@koic][])
* [#7358](rubocop/rubocop#7358): Fix an incorrect autocorrect for `Style/NestedModifier` when parentheses are required in method arguments. ([@koic][])
* [#7361](rubocop/rubocop#7361): Fix a false positive for `Style/TernaryParentheses` when only the closing parenthesis is used in the last line of condition. ([@koic][])
* [#7369](rubocop/rubocop#7369): Fix an infinite loop error for `Layout/IndentAssignment` with `Layout/IndentFirstArgument` when using multiple assignment. ([@koic][])
* [#7177](rubocop/rubocop#7177), [#7370](rubocop/rubocop#7370): When correcting alignment, do not insert spaces into string literals. ([@buehmann][])
* [#7367](rubocop/rubocop#7367): Fix an error for `Style/OrAssignment` cop when `then` branch body is empty. ([@koic][])
* [#7363](rubocop/rubocop#7363): Fix an incorrect autocorrect for `Layout/SpaceInsideBlockBraces` and `Style/BlockDelimiters` when using multiline empty braces. ([@koic][])
* [#7212](rubocop/rubocop#7212): Fix a false positive for `Layout/EmptyLinesAroundAccessModifier` and `UselessAccessModifier` when using method with the same name as access modifier around a method definition. ([@koic][])
* [#7217](rubocop/rubocop#7217): Make `Style/TrailingMethodEndStatement` work on more than the first `def`. ([@buehmann][])
* [#7190](rubocop/rubocop#7190): Support lower case drive letters on Windows. ([@jonas054][])
* Fix the auto-correction of `Lint/UnneededSplatExpansion` when the splat expansion of `Array.new` with a block is assigned to a variable. ([@rrosenblum][])
* [#5628](rubocop/rubocop#5628): Fix an error of `Layout/SpaceInsideStringInterpolation` on interpolations with multiple statements. ([@buehmann][])
* [#7128](rubocop/rubocop#7128): Make `Metrics/LineLength` aware of shebang. ([@koic][])
* [#6861](rubocop/rubocop#6861): Fix a false positive for `Layout/IndentationWidth` when using `EnforcedStyle: outdent` of `Layout/AccessModifierIndentation`. ([@koic][])
* [#7235](rubocop/rubocop#7235): Fix an error where `Style/ConditionalAssignment` would swallow a nested `if` condition. ([@buehmann][])
* [#7242](rubocop/rubocop#7242): Make `Style/ConstantVisibility` work on non-trivial class and module bodies. ([@buehmann][])
* [#5265](rubocop/rubocop#5265): Improved `Layout/ExtraSpacing` cop to handle nested consecutive assignments. ([@jfelchner][])
* [#7215](rubocop/rubocop#7215): Make it clear what's wrong in the message from `Style/GuardClause`. ([@jonas054][])
* [#7245](rubocop/rubocop#7245): Make cops detect string interpolations in more contexts: inside of backticks, regular expressions, and symbols. ([@buehmann][])
 [#7275](rubocop/rubocop#7275): Make `Style/VariableName` aware argument names when invoking a method. ([@koic][])
* [#3534](rubocop/rubocop#3534): Make `Style/IfUnlessModifier` report and auto-correct modifier lines that are too long. ([@jonas054][])
* [#7261](rubocop/rubocop#7261): `Style/FrozenStringLiteralComment` no longer inserts an empty line after the comment. This is left to `Layout/EmptyLineAfterMagicComment`. ([@buehmann][])
* [#7091](rubocop/rubocop#7091): `Style/FormatStringToken` now detects format sequences with flags and modifiers. ([@buehmann][])
* [#7319](rubocop/rubocop#7319): Rename `IgnoredMethodPatterns` option to `IgnoredPatterns` option for `Style/MethodCallWithArgsParentheses`. ([@koic][])
* [#7345](rubocop/rubocop#7345): Mark unsafe for `Style/YodaCondition`. ([@koic][])
* [#7170](rubocop/rubocop#7170): Fix a false positive for `Layout/RescueEnsureAlignment` when def line is preceded with `private_class_method`. ([@tatsuyafw][])
* [#7186](rubocop/rubocop#7186): Fix a false positive for `Style/MixinUsage` when using inside multiline block and `if` condition is after `include`. ([@koic][])
* [#7099](rubocop/rubocop#7099): Fix an error of `Layout/RescueEnsureAlignment` on assigned blocks. ([@tatsuyafw][])
* [#5088](rubocop/rubocop#5088): Fix an error of `Layout/MultilineMethodCallIndentation` on method chains inside an argument. ([@buehmann][])
* [#4719](rubocop/rubocop#4719): Make `Layout/Tab` detect tabs between string literals. ([@buehmann][])
* [#7203](rubocop/rubocop#7203): Fix an infinite loop error for `Layout/SpaceInsideBlockBraces` when `EnforcedStyle: no_space` with `SpaceBeforeBlockParameters: false` are set in multiline block. ([@koic][])
* [#6653](rubocop/rubocop#6653): Fix a bug where `Layout/IndentHeredoc` would remove empty lines when autocorrecting heredocs. ([@buehmann][])
* [#7188](rubocop/rubocop#7188): Include inspected file location in auto-correction error. ([@pocke][])

Signed-off-by: Tim Smith <tsmith@chef.io>
bfad added a commit to bfad/rubocop that referenced this issue Feb 23, 2023
…eference!

The modifier `if` and `unless` expressions were fixed in [fca7d43][],
but it didn't also fix it for the modifier forms of `while` and `until`.
This commit builds on that commit so that the following code no longer
fails the Lint/UselessAssignment cop:

```
middleware = nil
middleware.call(env) while (middleware = rack_middleware.next)
```

[fca7d43]: rubocop@fca7d43
bbatsov pushed a commit that referenced this issue Feb 26, 2023
The modifier `if` and `unless` expressions were fixed in [fca7d43][],
but it didn't also fix it for the modifier forms of `while` and `until`.
This commit builds on that commit so that the following code no longer
fails the Lint/UselessAssignment cop:

```
middleware = nil
middleware.call(env) while (middleware = rack_middleware.next)
```

[fca7d43]: fca7d43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants