From fd4a4a9745e6321d702a83bea3f36606cdc944fe Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Mon, 9 Oct 2023 13:05:51 +0100 Subject: [PATCH] Upgrade the irb command to use irb:debug integration This means that user will get an IRB session that has access to the debug commands too by activating IRB's debug integration automatically: https://github.com/ruby/irb#debugging-with-irb --- debug.gemspec | 2 +- lib/debug/irb_integration.rb | 27 +++++++++++++++++++ lib/debug/session.rb | 5 ++-- lib/debug/thread_client.rb | 9 ++----- test/console/irb_test.rb | 45 +++++++++++++++++++++++++++++++ test/support/console_test_case.rb | 1 + 6 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 lib/debug/irb_integration.rb create mode 100644 test/console/irb_test.rb diff --git a/debug.gemspec b/debug.gemspec index a07018a77..7c0e2d022 100644 --- a/debug.gemspec +++ b/debug.gemspec @@ -27,6 +27,6 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.extensions = ['ext/debug/extconf.rb'] - spec.add_dependency "irb", ">= 1.5.0" # for binding.irb(show_code: false) + spec.add_dependency "irb", "~> 1.10" # for irb:debug integration spec.add_dependency "reline", ">= 0.3.8" end diff --git a/lib/debug/irb_integration.rb b/lib/debug/irb_integration.rb new file mode 100644 index 000000000..a2ea34b65 --- /dev/null +++ b/lib/debug/irb_integration.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'irb' + +module DEBUGGER__ + module IrbPatch + def evaluate(line, line_no) + SESSION.send(:restart_all_threads) + super + # This is to communicate with the test framework so it can feed the next input + puts "INTERNAL_INFO: {}" if ENV['RUBY_DEBUG_TEST_UI'] == 'terminal' + ensure + SESSION.send(:stop_all_threads) + end + end + + class ThreadClient + def activate_irb_integration + IRB.setup(location, argv: []) + workspace = IRB::WorkSpace.new(current_frame&.binding || TOPLEVEL_BINDING) + irb = IRB::Irb.new(workspace) + IRB.conf[:MAIN_CONTEXT] = irb.context + IRB::Debug.setup(irb) + IRB::Context.prepend(IrbPatch) + end + end +end diff --git a/lib/debug/session.rb b/lib/debug/session.rb index 321ba8231..e6cef5182 100644 --- a/lib/debug/session.rb +++ b/lib/debug/session.rb @@ -936,10 +936,11 @@ def register_default_command # * Invoke `irb` on the current frame. register_command 'irb' do |arg| if @ui.remote? - @ui.puts "not supported on the remote console." + @ui.puts "\nIRB is supported on the remote console." :retry + else + request_eval :irb, nil end - request_eval :irb, nil end ### Trace diff --git a/lib/debug/thread_client.rb b/lib/debug/thread_client.rb index 3ec53fb81..6f9da4af1 100644 --- a/lib/debug/thread_client.rb +++ b/lib/debug/thread_client.rb @@ -1048,13 +1048,8 @@ def wait_next_action_ when :call result = frame_eval(eval_src) when :irb - require 'irb' # prelude's binding.irb doesn't have show_code option - begin - result = frame_eval('binding.irb(show_code: false)', binding_location: true) - ensure - # workaround: https://github.com/ruby/debug/issues/308 - Reline.prompt_proc = nil if defined? Reline - end + require_relative "irb_integration" + activate_irb_integration when :display, :try_display failed_results = [] eval_src.each_with_index{|src, i| diff --git a/test/console/irb_test.rb b/test/console/irb_test.rb new file mode 100644 index 000000000..e8dd61d0f --- /dev/null +++ b/test/console/irb_test.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require_relative '../support/console_test_case' + +module DEBUGGER__ + class IrbTest < ConsoleTestCase + def setup + @original_pager = ENV["PAGER"] + ENV["PAGER"] = "cat" + end + + def teardown + ENV["PAGER"] = @original_pager + end + + def program + <<~RUBY + 1| a = 1 + 2| b = 2 + RUBY + end + + def test_irb_command_is_disabled_in_remote_mode + debug_code(program, remote: :remote_only) do + type 'irb' + assert_line_text 'IRB is supported on the remote console.' + type 'q!' + end + end + + def test_irb_command_switches_console_to_irb + debug_code(program, remote: false) do + type 'irb' + type '123' + assert_line_text 'irb:rdbg(main):002> 123' + type 'irb_info' + assert_line_text('IRB version:') + type 'next' + type 'info' + assert_line_text([/a = 1/, /b = nil/]) + type 'q!' + end + end + end +end diff --git a/test/support/console_test_case.rb b/test/support/console_test_case.rb index 49e0bb87f..efdc1bafe 100644 --- a/test/support/console_test_case.rb +++ b/test/support/console_test_case.rb @@ -217,6 +217,7 @@ def prepare_test_environment(program, test_steps, &block) ENV['RUBY_DEBUG_TEST_UI'] = 'terminal' ENV['RUBY_DEBUG_NO_RELINE'] = 'true' ENV['RUBY_DEBUG_HISTORY_FILE'] = '' + ENV['TERM'] = 'dumb' write_temp_file(strip_line_num(program)) @scenario = []