Class: IRB::SourceFinder

Inherits:
Object show all
Defined in:
lib/irb/source_finder.rb

Defined Under Namespace

Classes: EvaluationError

Instance Method Summary collapse

Constructor Details

#initialize(irb_context) ⇒ SourceFinder

Returns a new instance of SourceFinder.



66
67
68
# File 'lib/irb/source_finder.rb', line 66

def initialize(irb_context)
  @irb_context = irb_context
end

Instance Method Details

#find_source(signature, super_level = 0) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/irb/source_finder.rb', line 70

def find_source(signature, super_level = 0)
  case signature
  when /\A(::)?[A-Z]\w*(::[A-Z]\w*)*\z/ # ConstName, ::ConstName, ConstPath::ConstName
    eval_receiver_or_owner(signature) # trigger autoload
    *parts, name = signature.split('::', -1)
    base =
      if parts.empty? # ConstName
        find_const_owner(name)
      elsif parts == [''] # ::ConstName
        Object
      else # ConstPath::ConstName
        eval_receiver_or_owner(parts.join('::'))
      end
    file, line = base.const_source_location(name)
  when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
    owner = eval_receiver_or_owner(Regexp.last_match[:owner])
    method = Regexp.last_match[:method]
    return unless owner.respond_to?(:instance_method)
    method = method_target(owner, super_level, method, "owner")
    file, line = method&.source_location
  when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
    receiver = eval_receiver_or_owner(Regexp.last_match[:receiver] || 'self')
    method = Regexp.last_match[:method]
    return unless receiver.respond_to?(method, true)
    method = method_target(receiver, super_level, method, "receiver")
    file, line = method&.source_location
  end
  return unless file && line

  if File.exist?(file)
    Source.new(file, line)
  elsif method
    # Method defined with eval, probably in IRB session
    source = RubyVM::InstructionSequence.of(method)&.script_lines&.join rescue nil
    Source.new(file, line, source)
  end
rescue EvaluationError
  nil
end