Skip to content

Commit bceaa02

Browse files
authored
Merge pull request #754 from koic/make_redundant_receiver_in_with_options_and_reversible_migration_aware_of_numblock
Make `Rails/RedundantReceiverInWithOptions` and `Rails/ReversibleMigration` aware of numblock
2 parents 6fc6d22 + 62ebebe commit bceaa02

9 files changed

+80
-32
lines changed

.rubocop_todo.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ InternalAffairs/NodeDestructuring:
1414
- 'lib/rubocop/cop/rails/relative_date_constant.rb'
1515
- 'lib/rubocop/cop/rails/time_zone.rb'
1616

17-
InternalAffairs/NumblockHandler:
18-
Enabled: false
19-
2017
# Offense count: 10
2118
Metrics/AbcSize:
2219
Max: 17
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#754](https://github.com/rubocop/rubocop-rails/pull/754): Make `Rails/RedundantReceiverInWithOptions` and `Rails/ReversibleMigration` cops aware of numbered block parameter. ([@koic][])

lib/rubocop/cop/mixin/index_method.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Cop
66
module IndexMethod # rubocop:disable Metrics/ModuleLength
77
RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
88

9-
def on_block(node)
9+
def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
1010
on_bad_each_with_object(node) do |*match|
1111
handle_possible_offense(node, match, 'each_with_object')
1212
end

lib/rubocop/cop/rails/action_filter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class ActionFilter < Base
6969

7070
RESTRICT_ON_SEND = FILTER_METHODS + ACTION_METHODS
7171

72-
def on_block(node)
72+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
7373
check_method_node(node.send_node)
7474
end
7575

lib/rubocop/cop/rails/rake_environment.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class RakeEnvironment < Base
3939
(block $(send nil? :task ...) ...)
4040
PATTERN
4141

42-
def on_block(node)
42+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
4343
task_definition?(node) do |task_method|
4444
return if task_name(task_method) == :default
4545
return if with_dependencies?(task_method)

lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,6 @@ class RedundantReceiverInWithOptions < Base
6060

6161
MSG = 'Redundant receiver in `with_options`.'
6262

63-
def_node_matcher :with_options?, <<~PATTERN
64-
(block
65-
(send nil? :with_options
66-
(...))
67-
(args
68-
$_arg)
69-
$_body)
70-
PATTERN
71-
7263
def_node_search :all_block_nodes_in, <<~PATTERN
7364
(block ...)
7465
PATTERN
@@ -78,29 +69,40 @@ class RedundantReceiverInWithOptions < Base
7869
PATTERN
7970

8071
def on_block(node)
81-
with_options?(node) do |arg, body|
82-
return if body.nil?
83-
return unless all_block_nodes_in(body).count.zero?
84-
85-
send_nodes = all_send_nodes_in(body)
86-
87-
if send_nodes.all? { |n| same_value?(arg, n.receiver) }
88-
send_nodes.each do |send_node|
89-
receiver = send_node.receiver
90-
add_offense(receiver.source_range) do |corrector|
91-
autocorrect(corrector, send_node)
92-
end
93-
end
72+
return unless node.method?(:with_options)
73+
return unless (body = node.body)
74+
return unless all_block_nodes_in(body).count.zero?
75+
76+
send_nodes = all_send_nodes_in(body)
77+
return unless redundant_receiver?(send_nodes, node)
78+
79+
send_nodes.each do |send_node|
80+
receiver = send_node.receiver
81+
add_offense(receiver.source_range) do |corrector|
82+
autocorrect(corrector, send_node, node)
9483
end
9584
end
9685
end
9786

87+
alias on_numblock on_block
88+
9889
private
9990

100-
def autocorrect(corrector, node)
101-
corrector.remove(node.receiver.source_range)
102-
corrector.remove(node.loc.dot)
103-
corrector.remove(block_argument_range(node))
91+
def autocorrect(corrector, send_node, node)
92+
corrector.remove(send_node.receiver.source_range)
93+
corrector.remove(send_node.loc.dot)
94+
corrector.remove(block_argument_range(send_node)) unless node.numblock_type?
95+
end
96+
97+
def redundant_receiver?(send_nodes, node)
98+
proc = if node.numblock_type?
99+
->(n) { n.receiver.lvar_type? && n.receiver.source == '_1' }
100+
else
101+
arg = node.arguments.first
102+
->(n) { same_value?(arg, n.receiver) }
103+
end
104+
105+
send_nodes.all?(&proc)
104106
end
105107

106108
def block_argument_range(node)

lib/rubocop/cop/rails/reversible_migration.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ def on_block(node)
229229
check_change_table_node(node.send_node, node.body)
230230
end
231231

232+
alias on_numblock on_block
233+
232234
private
233235

234236
def check_irreversible_schema_statement_node(node)

spec/rubocop/cop/rails/redundant_receiver_in_with_options_spec.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,36 @@ class Account < ApplicationRecord
2929
RUBY
3030
end
3131

32+
context 'Ruby >= 2.7', :ruby27 do
33+
it 'registers an offense and corrects using explicit receiver in `with_options`' do
34+
expect_offense(<<~RUBY)
35+
class Account < ApplicationRecord
36+
with_options dependent: :destroy do
37+
_1.has_many :customers
38+
^^ Redundant receiver in `with_options`.
39+
_1.has_many :products
40+
^^ Redundant receiver in `with_options`.
41+
_1.has_many :invoices
42+
^^ Redundant receiver in `with_options`.
43+
_1.has_many :expenses
44+
^^ Redundant receiver in `with_options`.
45+
end
46+
end
47+
RUBY
48+
49+
expect_correction(<<~RUBY)
50+
class Account < ApplicationRecord
51+
with_options dependent: :destroy do
52+
has_many :customers
53+
has_many :products
54+
has_many :invoices
55+
has_many :expenses
56+
end
57+
end
58+
RUBY
59+
end
60+
end
61+
3262
it 'does not register an offense when using implicit receiver in `with_options`' do
3363
expect_no_offenses(<<~RUBY)
3464
class Account < ApplicationRecord

spec/rubocop/cop/rails/reversible_migration_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ def change
3535
end
3636
RUBY
3737

38+
context 'Ruby >= 2.7', :ruby27 do
39+
it_behaves_like 'accepts', 'create_table using numbered parameter', <<~RUBY
40+
create_table :users do
41+
_1.string :name
42+
end
43+
RUBY
44+
end
45+
3846
it_behaves_like 'offense', 'execute', <<~RUBY
3947
execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
4048
RUBY
@@ -227,6 +235,14 @@ def change
227235
end
228236
RUBY
229237

238+
context 'Ruby >= 2.7', :ruby27 do
239+
it_behaves_like 'offense', 'change_table(with change_default)', <<~RUBY
240+
change_table :users do
241+
_1.change_default :authorized, 1
242+
end
243+
RUBY
244+
end
245+
230246
context 'remove' do
231247
context 'Rails >= 6.1', :rails61 do
232248
it_behaves_like 'accepts', 't.remove (with type)', <<~RUBY

0 commit comments

Comments
 (0)