-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
The cop Style/CollectionCompact has unsafe autocorrect which changes calls to Hash#delete_if
to Hash#compact
.
This is incorrect because Hash#delete_if
modifies the object and Hash#compact
does not.
The correct replacement would be Hash#compact!
(the ! version).
The same applies to Array#delete_if
erroneously being converted to Array#compact
.
My reproduction below only shows the Hash case. I have not gone looking for other Array / Hash methods that modify the receiver.
Warning: Array#delete_if
returns self
after modifying the object. Array#compact!
sometimes returns nil:
`
$ ri --no-pager Array#compact!
Array#compact!
(from ruby core)
array.compact! -> self or nil
Removes all nil elements from self.
Returns self if any elements removed, otherwise nil.
So maybe it is not as simple as just changing
compactto
compact!` in the replacement.
Expected behavior
I expect a call to Hash#delete_if
to be replaced with Hash#compact!
(the ! version)
Actual behavior
Hash#delete_if
is replaced with Hash#compact
(the non ! version)
Steps to reproduce the problem
Example input:
#!/usr/bin/ruby
h = {
a: "a",
b: "b",
c: nil,
}
h.delete_if { |_, v| v.nil? }
pp h
This prints the following:
$ ruby test.rb
{:a=>"a", :b=>"b"}
After letting rubocop correct the source file, the output has changed:
$ rubocop -c /dev/null test.rb --only Style/CollectionCompact -A
Inspecting 1 file
C
Offenses:
test.rb:8:3: C: [Corrected] Style/CollectionCompact: Use compact instead of delete_if { |_, v| v.nil? }.
h.delete_if { |_, v| v.nil? }
^^^^^^^^^^^^^^^^^^^^^^^^^^^
1 file inspected, 1 offense detected, 1 offense corrected
$ ruby test.rb
{:a=>"a", :b=>"b", :c=>nil}
RuboCop version
$ rubocop -V
1.62.1 (using Parser 3.3.0.5, rubocop-ast 1.31.2, running on ruby 3.1.2) +server [x86_64-linux-gnu]