Skip to content

Commit d8e1f94

Browse files
Earlopainbbatsov
authored andcommitted
[Fix #14062] Fix false positives for Lint/ReturnInVoidContext when returning inside define_method or a nested singleton method
In addition to `lambda`, `define_method` and `define_singleton_method` must also be handled
1 parent f5e9ca9 commit d8e1f94

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#14062](https://github.com/rubocop/rubocop/issues/14062): Fix false positives for `Lint/ReturnInVoidContext` when returning inside `define_method` or a nested singleton method. ([@earlopain][])

lib/rubocop/cop/lint/return_in_void_context.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,17 @@ module Lint
3232
class ReturnInVoidContext < Base
3333
MSG = 'Do not return a value in `%<method>s`.'
3434

35+
# Returning out of these methods only exits the block itself.
36+
SCOPE_CHANGING_METHODS = %i[lambda define_method define_singleton_method].freeze
37+
3538
def on_return(return_node)
3639
return unless return_node.descendants.any?
3740

38-
def_node = return_node.each_ancestor(:def).first
41+
def_node = return_node.each_ancestor(:def, :defs).first
3942
return unless def_node&.void_context?
40-
return if return_node.each_ancestor(:any_block).any?(&:lambda?)
43+
return if return_node.each_ancestor(:any_block).any? do |block_node|
44+
SCOPE_CHANGING_METHODS.include?(block_node.method_name)
45+
end
4146

4247
add_offense(
4348
return_node.loc.keyword,

spec/rubocop/cop/lint/return_in_void_context_spec.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,66 @@ def initialize
5454
RUBY
5555
end
5656

57+
it 'registers no offense when return is used in `define_method`' do
58+
expect_no_offenses(<<~RUBY)
59+
class A
60+
def initialize
61+
define_method(:foo) do
62+
return bar
63+
end
64+
end
65+
end
66+
RUBY
67+
end
68+
69+
it 'registers no offense when return is used in `define_method` with receiver' do
70+
expect_no_offenses(<<~RUBY)
71+
class A
72+
def initialize
73+
self.define_method(:foo) do
74+
return bar
75+
end
76+
end
77+
end
78+
RUBY
79+
end
80+
81+
it 'registers no offense when return is used in `define_singleton_method`' do
82+
expect_no_offenses(<<~RUBY)
83+
class A
84+
def initialize
85+
define_singleton_method(:foo) do
86+
return bar
87+
end
88+
end
89+
end
90+
RUBY
91+
end
92+
93+
it 'registers no offense when return is used in nested method definition' do
94+
expect_no_offenses(<<~RUBY)
95+
class A
96+
def initialize
97+
def foo
98+
return bar
99+
end
100+
end
101+
end
102+
RUBY
103+
end
104+
105+
it 'registers no offense when return is used in nested singleton method definition' do
106+
expect_no_offenses(<<~RUBY)
107+
class A
108+
def initialize
109+
def self.foo
110+
return bar
111+
end
112+
end
113+
end
114+
RUBY
115+
end
116+
57117
it 'registers an offense when the value is returned from inside a proc' do
58118
expect_offense(<<~RUBY)
59119
class A

0 commit comments

Comments
 (0)