From c82b56891a473dd350be286326b2fc36ff181654 Mon Sep 17 00:00:00 2001 From: tompng Date: Thu, 28 Nov 2024 02:28:49 +0900 Subject: [PATCH] Don't show 'Maybe IRB bug!' in show_source and ls command --- lib/irb/command/ls.rb | 34 +++++++++++++++++++--------- lib/irb/source_finder.rb | 5 ++-- test/irb/command/test_show_source.rb | 13 +++++++++++ test/irb/test_command.rb | 13 +++++++++++ 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/lib/irb/command/ls.rb b/lib/irb/command/ls.rb index cbd9998bc..944efd757 100644 --- a/lib/irb/command/ls.rb +++ b/lib/irb/command/ls.rb @@ -11,7 +11,7 @@ module IRB module Command class Ls < Base - include RubyArgsExtractor + class EvaluationError < StandardError; end category "Context" description "Show methods, constants, and variables." @@ -22,24 +22,35 @@ class Ls < Base -g [query] Filter the output with a query. HELP_MESSAGE + def evaluate(code) + @irb_context.workspace.binding.eval(code) + rescue Exception => e + puts "#{e.class}: #{e.message}" + raise EvaluationError + end + def execute(arg) if match = arg.match(/\A(?.+\s|)(-g|-G)\s+(?.+)$/) - if match[:target].empty? - use_main = true - else - obj = @irb_context.workspace.binding.eval(match[:target]) - end + target = match[:target] grep = Regexp.new(match[:grep]) + elsif match = arg.match(/\A((?.+),|)\s*grep:(?.+)/) + # Legacy style `ls obj, grep: /regexp/` + # Evaluation order should be eval(target) then eval(grep) + target = match[:target] || '' + grep_regexp_code = match[:grep] else - args, kwargs = ruby_args(arg) - use_main = args.empty? - obj = args.first - grep = kwargs[:grep] + target = arg.strip end - if use_main + if target.empty? obj = irb_context.workspace.main locals = irb_context.workspace.binding.local_variables + else + obj = evaluate(target) + end + + if grep_regexp_code + grep = evaluate(grep_regexp_code) end o = Output.new(grep: grep) @@ -52,6 +63,7 @@ def execute(arg) o.dump("class variables", klass.class_variables) o.dump("locals", locals) if locals o.print_result + rescue EvaluationError end def dump_methods(o, klass, obj) diff --git a/lib/irb/source_finder.rb b/lib/irb/source_finder.rb index c515da570..6e1e58069 100644 --- a/lib/irb/source_finder.rb +++ b/lib/irb/source_finder.rb @@ -125,9 +125,8 @@ def method_target(owner_receiver, super_level, method, type) end def eval_receiver_or_owner(code) - context_binding = @irb_context.workspace.binding - eval(code, context_binding) - rescue NameError + @irb_context.workspace.binding.eval(code) + rescue Exception raise EvaluationError end diff --git a/test/irb/command/test_show_source.rb b/test/irb/command/test_show_source.rb index d014c78fc..a4227231e 100644 --- a/test/irb/command/test_show_source.rb +++ b/test/irb/command/test_show_source.rb @@ -65,6 +65,19 @@ def test_show_source_with_missing_constant assert_match(%r[Couldn't locate a definition for Foo], out) end + def test_show_source_with_eval_error + write_ruby <<~'RUBY' + binding.irb + RUBY + + out = run_ruby_file do + type "show_source raise(Exception).itself" + type "exit" + end + + assert_match(%r[Couldn't locate a definition for raise\(Exception\)\.itself], out) + end + def test_show_source_string write_ruby <<~'RUBY' binding.irb diff --git a/test/irb/test_command.rb b/test/irb/test_command.rb index 69931e3e4..21e05752b 100644 --- a/test/irb/test_command.rb +++ b/test/irb/test_command.rb @@ -742,6 +742,19 @@ def test_ls_grep_empty end end + def test_ls_with_eval_error + [ + "ls raise(Exception,'foo')\n", + "ls raise(Exception,'foo'), grep: /./\n", + "ls Integer, grep: raise(Exception,'foo')\n", + ].each do |line| + out, err = execute_lines(line) + assert_empty err + assert_match(/Exception: foo/, out) + assert_not_match(/Maybe IRB bug!/, out) + end + end + def test_ls_with_no_singleton_class out, err = execute_lines( "ls 42",