summaryrefslogtreecommitdiff
path: root/lib/irb/source_finder.rb
diff options
context:
space:
mode:
authorpaulreece <[email protected]>2023-11-28 09:56:47 -0500
committergit <[email protected]>2023-11-28 14:56:51 +0000
commit891ce4614a7cab6eb76429a9972b5e8c2dc02a5d (patch)
treef31c36b4be59cf7a222a77c8a21caa809474e874 /lib/irb/source_finder.rb
parent5fc71feb6ca8b62d51f9b6421cb26c9f1228be17 (diff)
[ruby/irb] This enhancement allows a user to add the -s flag if they
want to access a methods origin definition. It allows for chaining of multiple esses to further go up the classes as needed. (https://github.com/ruby/irb/pull/770) https://github.com/ruby/irb/commit/eec1329d5a
Diffstat (limited to 'lib/irb/source_finder.rb')
-rw-r--r--lib/irb/source_finder.rb30
1 files changed, 24 insertions, 6 deletions
diff --git a/lib/irb/source_finder.rb b/lib/irb/source_finder.rb
index 959919e8ac..a9450d4571 100644
--- a/lib/irb/source_finder.rb
+++ b/lib/irb/source_finder.rb
@@ -16,7 +16,7 @@ module IRB
@irb_context = irb_context
end
- def find_source(signature)
+ def find_source(signature, s_count = nil)
context_binding = @irb_context.workspace.binding
case signature
when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
@@ -26,14 +26,13 @@ module IRB
when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
owner = eval(Regexp.last_match[:owner], context_binding)
method = Regexp.last_match[:method]
- 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
+ return unless owner.respond_to?(:instance_method)
+ file, line = method_target(owner, s_count, method, "owner")
when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
receiver = eval(Regexp.last_match[:receiver] || 'self', context_binding)
method = Regexp.last_match[:method]
- file, line = receiver.method(method).source_location if receiver.respond_to?(method, true)
+ return unless receiver.respond_to?(method, true)
+ file, line = method_target(receiver, s_count, method, "receiver")
end
if file && line && File.exist?(file)
Source.new(file: file, first_line: line, last_line: find_end(file, line))
@@ -60,5 +59,24 @@ module IRB
end
first_line
end
+
+ def method_target(owner_receiver, s_count, method, type)
+ case type
+ when "owner"
+ target_method = owner_receiver.instance_method(method)
+ return target_method.source_location unless s_count
+ when "receiver"
+ if s_count
+ target_method = owner_receiver.class.instance_method(method)
+ else
+ target_method = method
+ return owner_receiver.method(method).source_location
+ end
+ end
+ s_count.times do |s|
+ target_method = target_method.super_method if target_method
+ end
+ target_method.nil? ? nil : target_method.source_location
+ end
end
end