diff --git a/changelog/fix_fix_lintdebugger_to_be_able_to_handle.md b/changelog/fix_fix_lintdebugger_to_be_able_to_handle.md new file mode 100644 index 00000000000..a52a521c95d --- /dev/null +++ b/changelog/fix_fix_lintdebugger_to_be_able_to_handle.md @@ -0,0 +1 @@ +* [#10859](https://github.com/rubocop/rubocop/issues/10859): Fix `Lint/Debugger` to be able to handle method chains correctly. ([@dvandersluis][]) diff --git a/config/default.yml b/config/default.yml index 2f9b1f89f96..cdcaeb1998d 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1604,6 +1604,7 @@ Lint/Debugger: # a user's configuration, but are otherwise not significant. Kernel: - binding.irb + - Kernel.binding.irb Byebug: - byebug - remote_byebug @@ -1621,6 +1622,9 @@ Lint/Debugger: - binding.pry - binding.remote_pry - binding.pry_remote + - Kernel.binding.pry + - Kernel.binding.remote_pry + - Kernel.binding.pry_remote - Pry.rescue Rails: - debugger diff --git a/lib/rubocop/cop/lint/debugger.rb b/lib/rubocop/cop/lint/debugger.rb index 15ed8665e3f..105dc7fb5a7 100644 --- a/lib/rubocop/cop/lint/debugger.rb +++ b/lib/rubocop/cop/lint/debugger.rb @@ -67,19 +67,6 @@ module Lint class Debugger < Base MSG = 'Remove debugger entry point `%s`.' - # @!method kernel?(node) - def_node_matcher :kernel?, <<~PATTERN - (const {nil? cbase} :Kernel) - PATTERN - - # @!method valid_receiver?(node, arg1) - def_node_matcher :valid_receiver?, <<~PATTERN - { - (const {nil? cbase} %1) - (send {nil? #kernel?} %1) - } - PATTERN - def on_send(node) return unless debugger_method?(node) @@ -101,7 +88,7 @@ def debugger_methods *receiver, method_name = v.split('.') { - receiver: receiver.empty? ? nil : receiver.join.to_sym, + receiver: receiver.empty? ? nil : receiver.map(&:to_sym), method_name: method_name.to_sym } end.compact @@ -115,10 +102,23 @@ def debugger_method?(send_node) if method[:receiver].nil? send_node.receiver.nil? else - valid_receiver?(send_node.receiver, method[:receiver]) + method[:receiver] == receiver_chain(send_node) end end end + + def receiver_chain(send_node) + receivers = [] + receiver = send_node.receiver + + while receiver + name = receiver.send_type? ? receiver.method_name : receiver.const_name&.to_sym + receivers.unshift(name) + receiver = receiver.receiver + end + + receivers + end end end end diff --git a/spec/rubocop/cop/lint/debugger_spec.rb b/spec/rubocop/cop/lint/debugger_spec.rb index debd54d4ab2..842416530e7 100644 --- a/spec/rubocop/cop/lint/debugger_spec.rb +++ b/spec/rubocop/cop/lint/debugger_spec.rb @@ -27,6 +27,39 @@ RUBY end end + + context 'with a method chain' do + let(:cop_config) { { 'DebuggerMethods' => %w[debugger.foo.bar] } } + + it 'registers an offense for a `debugger.foo.bar` call' do + expect_offense(<<~RUBY) + debugger.foo.bar + ^^^^^^^^^^^^^^^^ Remove debugger entry point `debugger.foo.bar`. + RUBY + end + end + + context 'with a const chain' do + let(:cop_config) { { 'DebuggerMethods' => %w[Foo::Bar::Baz.debug] } } + + it 'registers an offense for a `Foo::Bar::Baz.debug` call' do + expect_offense(<<~RUBY) + Foo::Bar::Baz.debug + ^^^^^^^^^^^^^^^^^^^ Remove debugger entry point `Foo::Bar::Baz.debug`. + RUBY + end + end + + context 'with a const chain and a method chain' do + let(:cop_config) { { 'DebuggerMethods' => %w[Foo::Bar::Baz.debug.this.code] } } + + it 'registers an offense for a `Foo::Bar::Baz.debug.this.code` call' do + expect_offense(<<~RUBY) + Foo::Bar::Baz.debug.this.code + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Remove debugger entry point `Foo::Bar::Baz.debug.this.code`. + RUBY + end + end end context 'built-in methods' do