[ruby/irb] Allow show_source for private methods

(https://github.com/ruby/irb/pull/589)

* Allow `show_source` for private methods

Fix https://github.com/ruby/irb/pull/577

* Pend tests on TruffleRuby

It seems `eval(..., __LINE__ + 1)` does not work.
Other similar tests are also pended on TruffleRuby, so I think it
is acceptable.

* Use `private_method_defined?` instead of `defined?`
This commit is contained in:
TSUYUSATO Kitsune 2023-05-24 01:16:32 +09:00 committed by git
parent 24a6609ccb
commit 92d6c9a7b1
2 changed files with 45 additions and 3 deletions

View File

@ -31,13 +31,14 @@ module IRB
when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
owner = eval(Regexp.last_match[:owner], irb_context.workspace.binding)
method = Regexp.last_match[:method]
if owner.respond_to?(:instance_method) && owner.instance_methods.include?(method.to_sym)
file, line = owner.instance_method(method).source_location
if owner.respond_to?(:instance_method)
methods = owner.instance_methods + owner.private_instance_methods
file, line = owner.instance_method(method).source_location if methods.include?(method.to_sym)
end
when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
receiver = eval(Regexp.last_match[:receiver] || 'self', irb_context.workspace.binding)
method = Regexp.last_match[:method]
file, line = receiver.method(method).source_location if receiver.respond_to?(method)
file, line = receiver.method(method).source_location if receiver.respond_to?(method, true)
end
if file && line
Source.new(file: file, first_line: line, last_line: find_end(file, line, irb_context))

View File

@ -488,6 +488,47 @@ module TestIRB
assert_empty err
assert_include(out, code)
end
def test_show_source_private_instance
pend if RUBY_ENGINE == 'truffleruby'
eval(code = <<-EOS, binding, __FILE__, __LINE__ + 1)
class PrivateInstanceTest
private def show_source_test_method
unless true
end
end unless private_method_defined?(:show_source_test_method)
end
EOS
out, err = execute_lines(
"show_source '#{self.class.name}::PrivateInstanceTest#show_source_test_method'\n",
)
assert_empty err
assert_include(out, code.lines[1..-2].join)
end
def test_show_source_private
pend if RUBY_ENGINE == 'truffleruby'
eval(code = <<-EOS, binding, __FILE__, __LINE__ + 1)
class PrivateTest
private def show_source_test_method
unless true
end
end unless private_method_defined?(:show_source_test_method)
end
Instance = PrivateTest.new unless defined?(Instance)
EOS
out, err = execute_lines(
"show_source '#{self.class.name}::Instance.show_source_test_method'\n",
)
assert_empty err
assert_include(out, code.lines[1..-4].join)
end
end
class WorkspaceCommandTestCase < CommandTestCase