Skip to content

Commit

Permalink
This enhancement allows a user to add the -s flag if they want to acc…
Browse files Browse the repository at this point in the history
…ess a methods origin definition. It allows for chaining of multiple esses to further go up the classes as needed.
  • Loading branch information
paulreece committed Nov 24, 2023
1 parent afbba64 commit 7476427
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/irb/cmd/show_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ def bold(str)
end
end
end
end
end
11 changes: 11 additions & 0 deletions lib/irb/source_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def initialize(irb_context)

def find_source(signature)
context_binding = @irb_context.workspace.binding
if signature.include? " -s"
signature, esses = signature.split(" -")
s_count = esses.count("^s").zero? ? esses.size : 1
end
case signature
when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
eval(signature, context_binding) # trigger autoload
Expand All @@ -26,6 +30,13 @@ def find_source(signature)
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 s_count
super_owner = owner
s_count.times {|s| super_owner = super_owner.superclass}
if super_owner.respond_to?(:instance_method)
owner = super_owner
end
end
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)
Expand Down
110 changes: 110 additions & 0 deletions test/irb/test_cmd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,116 @@ def test_show_source_method
assert_match(%r[/irb\/init\.rb], out)
end

def test_show_source_method_s
code = <<~RUBY
class Baz
def foo
end
end
class Bar < Baz
def foo
super
end
end
RUBY
File.write("#{@tmpdir}/bazbar.rb", code)
out, err = execute_lines(
"irb_load '#{@tmpdir}/bazbar.rb'\n",
"show_source Bar#foo -s",
)
assert_match(%r[bazbar.rb:2\n\n def foo\n end\n\n=> nil\n], out)
end

def test_show_source_method_multiple_s
code = <<~RUBY
class Baz
def foo
end
end
class Bar < Baz
def foo
super
end
end
class Bob < Bar
def foo
super
end
end
RUBY
File.write("#{@tmpdir}/bazbarbob.rb", code)
out, err = execute_lines(
"irb_load '#{@tmpdir}/bazbarbob.rb'\n",
"show_source Bob#foo -ss",
)
assert_match(%r[bazbarbob.rb:2\n\n def foo\n end\n\n=> nil\n], out)
end

def test_show_source_method_no_instance_method
code = <<~RUBY
class Baz
end
class Bar < Baz
def foo
super
end
end
RUBY
File.write("#{@tmpdir}/bazbar.rb", code)
out, err = execute_lines(
"irb_load '#{@tmpdir}/bazbar.rb'\n",
"show_source Bar#foo -s",
)
assert_match(%r[Error: Couldn't locate a definition for Bar#foo -s\n=> nil\n], out)
end

def test_show_source_method_exceeds_super_chain
code = <<~RUBY
class Baz
def foo
end
end
class Bar < Baz
def foo
super
end
end
RUBY
File.write("#{@tmpdir}/bazbar.rb", code)
out, err = execute_lines(
"irb_load '#{@tmpdir}/bazbar.rb'\n",
"show_source Bar#foo -ss",
)
assert_match(%r[Error: Couldn't locate a definition for Bar#foo -ss\n=> nil\n], out)
end

def test_show_source_method_accidental_characters
code = <<~RUBY
class Baz
def foo
end
end
class Bar < Baz
def foo
super
end
end
RUBY
File.write("#{@tmpdir}/bazbar.rb", code)
out, err = execute_lines(
"irb_load '#{@tmpdir}/bazbar.rb'\n",
"show_source Bar#foo -sddddd",
)
assert_empty err
assert_match(%r[bazbar.rb:2\n\n def foo\n end\n\n=> nil\n], out)
end

def test_show_source_string
out, err = execute_lines(
"show_source 'IRB.conf'\n",
Expand Down

0 comments on commit 7476427

Please sign in to comment.