зеркало из https://github.com/github/ruby.git
[ruby/irb] Improve constant lookup in SourceFinder
(https://github.com/ruby/irb/pull/871) https://github.com/ruby/irb/commit/87c279ccf2
This commit is contained in:
Родитель
eea7ce55de
Коммит
d0412599e0
|
@ -69,10 +69,18 @@ module IRB
|
|||
|
||||
def find_source(signature, super_level = 0)
|
||||
case signature
|
||||
when /\A(::)?[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
|
||||
when /\A(::)?[A-Z]\w*(::[A-Z]\w*)*\z/ # ConstName, ::ConstName, ConstPath::ConstName
|
||||
eval_receiver_or_owner(signature) # trigger autoload
|
||||
base = @irb_context.workspace.binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object }
|
||||
file, line = base.const_source_location(signature)
|
||||
*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]
|
||||
|
@ -122,5 +130,10 @@ module IRB
|
|||
rescue NameError
|
||||
raise EvaluationError
|
||||
end
|
||||
|
||||
def find_const_owner(name)
|
||||
module_nesting = @irb_context.workspace.binding.eval('::Module.nesting')
|
||||
module_nesting.find { |mod| mod.const_defined?(name, false) } || module_nesting.find { |mod| mod.const_defined?(name) } || Object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -362,5 +362,36 @@ module TestIRB
|
|||
refute_match(/NameError/, out)
|
||||
assert_match(%r[Defined in binary file:.+io/console], out)
|
||||
end
|
||||
|
||||
def test_show_source_with_constant_lookup
|
||||
write_ruby <<~RUBY
|
||||
X = 1
|
||||
module M
|
||||
Y = 1
|
||||
Z = 2
|
||||
end
|
||||
class A
|
||||
Z = 1
|
||||
Array = 1
|
||||
class B
|
||||
include M
|
||||
Object.new.instance_eval { binding.irb }
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
out = run_ruby_file do
|
||||
type "show_source X"
|
||||
type "show_source Y"
|
||||
type "show_source Z"
|
||||
type "show_source Array"
|
||||
type "exit"
|
||||
end
|
||||
|
||||
assert_match(%r[#{@ruby_file.to_path}:1\s+X = 1], out)
|
||||
assert_match(%r[#{@ruby_file.to_path}:3\s+Y = 1], out)
|
||||
assert_match(%r[#{@ruby_file.to_path}:7\s+Z = 1], out)
|
||||
assert_match(%r[#{@ruby_file.to_path}:8\s+Array = 1], out)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче