ruby/irb

`show_source` can't find some sources defined in the session

amomchilov opened this issue · 1 comments

Description

irb can find the source of a method defined during the repl session, but not its parent class.

irb(main):001* class Foo
irb(main):002*   def x = "Hello, world!"
irb(main):003> end
=> :x
irb(main):004> Foo.instance_method(:x).source_location
=> ["(irb)", 2]
irb(main):005> show_source Foo#x # Works ✅

From: (irb):2

def x = "Hello, world!"

=> nil
irb(main):006> show_source Foo # Not found ❌
Error: Couldn't locate a definition for Foo
=> nil

A similar thing happens if you execute a script from standard input

$ ruby
class Foo
  def x = "Hello, world!"
end

binding.irb
< I press ctrl-d to send EOF >
irb(main):001> Foo.instance_method(:x).source_location
=> ["-", 2]
irb(main):002> show_source Foo#x # Not found ❌
Error: Couldn't locate a definition for Foo#x # Not found ❌
=> nil
irb(main):003> show_source Foo # Not found ❌
Error: Couldn't locate a definition for Foo # Not found ❌
=> nil

Notes

This does work if running from a saved script:

# example_script.rb
class Foo
  def x = "Hello, world!"
end

binding.irb
ruby ./example_script.rb

From: ./example_script.rb @ line 5 :

    1: class Foo
    2:   def x = "Hello, world!"
    3: end
    4:
 => 5: binding.irb

irb(main):001> show_source Foo

From: ./example_script.rb:1

class Foo
  def x = "Hello, world!"
end

nil

Result of irb_info

irb(main):001> irb_info
Ruby version: 3.3.0
IRB version: irb 1.13.1 (2024-05-05)
InputMethod: RelineInputMethod with Reline 0.5.8
Completion: Autocomplete, RegexpCompletor
RUBY_PLATFORM: x86_64-linux
LANG env: en_US.UTF-8
LC_ALL env: en_US.UTF-8
East Asian Ambiguous Width: 1

## Terminal Emulator

What's your terminal emulator? **iTerm 2.**

## Setting Files

Are you using `~/.irbrc` and `~/.inputrc`? **Nope.**

If the source file exist, source is available.
Even if the file does not exist, IRB can show method source defined in IRB because RubyVM::AbstractSyntaxTree.keep_script_lines is enabled in IRB session.

if you execute a script from standard input

It is impossible now. keep_script_lines can't be enabled before evaluating script from standard input.

show_source Foo # Not found

Constant source is not available from AST.
We need to add an identifier to the source file '(irb)' like '(irb[session_id])' and store all input lines, which I avoid and use keep_script_lines = true instead in #862.

$ ruby -e "loop{binding.irb}"
irb(main):001> A=1 # defined in line 1
irb(main):002> exit
irb(main):001> B=1 # also defined in line 1. source file string should be different to distinguish B from A
irb(main):002> Object.const_source_location(:A) == Object.const_source_location(:B)
#=> true # should be false to implement constant source defined in irb session