[ruby/irb] Display and prioritise instance methods in `ls

<module/class>`
(https://github.com/ruby/irb/pull/496)

https://github.com/ruby/irb/commit/e3d21f9329
This commit is contained in:
Stan Lo 2023-02-28 22:36:06 +08:00 committed by git
parent 2d6097a0f5
commit 9ddd73060b
2 changed files with 80 additions and 7 deletions

View File

@ -38,21 +38,34 @@ module IRB
def dump_methods(o, klass, obj)
singleton_class = begin obj.singleton_class; rescue TypeError; nil end
maps = class_method_map((singleton_class || klass).ancestors)
dumped_mods = Array.new
# singleton_class' ancestors should be at the front
maps = class_method_map(singleton_class&.ancestors || [], dumped_mods) + class_method_map(klass.ancestors, dumped_mods)
maps.each do |mod, methods|
name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
o.dump(name, methods)
end
end
def class_method_map(classes)
dumped = Array.new
classes.reject { |mod| mod >= Object }.map do |mod|
methods = mod.public_instance_methods(false).select do |m|
dumped.push(m) unless dumped.include?(m)
def class_method_map(classes, dumped_mods)
dumped_methods = Array.new
classes = classes.reject { |mod| mod >= Object }
classes.map do |mod|
next if dumped_mods.include? mod
dumped_mods << mod
methods = mod.public_instance_methods(false).select do |method|
if dumped_methods.include? method
false
else
dumped_methods << method
true
end
end
[mod, methods]
end.reverse
end.compact
end
class Output

View File

@ -672,6 +672,66 @@ module TestIRB
assert_match(/C.methods:\s+m5\n/m, out)
end
def test_ls_class
out, err = execute_lines(
"module M1\n",
" def m2; end\n",
" def m3; end\n",
"end\n",
"class C1\n",
" def m1; end\n",
" def m2; end\n",
"end\n",
"class C2 < C1\n",
" include M1\n",
" def m3; end\n",
" def m4; end\n",
" def self.m3; end\n",
" def self.m5; end\n",
"end\n",
"ls C2"
)
assert_empty err
assert_match(/C2.methods:\s+m3\s+m5\n/, out)
assert_match(/C2#methods:\s+m3\s+m4\n.*M1#methods:\s+m2\n.*C1#methods:\s+m1\n/, out)
end
def test_ls_module
out, err = execute_lines(
"module M1\n",
" def m1; end\n",
" def m2; end\n",
"end\n",
"module M2\n",
" include M1\n",
" def m1; end\n",
" def m3; end\n",
" def self.m4; end\n",
"end\n",
"ls M2"
)
assert_empty err
assert_match(/M2\.methods:\s+m4\nModule#methods:/, out)
assert_match(/M2#methods:\s+m1\s+m3\n.*M1#methods:\s+m2\n/, out)
end
def test_ls_instance
out, err = execute_lines(
"class Foo; def bar; end; end\n",
"ls Foo.new"
)
assert_empty err
assert_match(/Foo#methods:\s+bar/, out)
# don't duplicate
assert_not_match(/Foo#methods:\s+bar\n.*Foo#methods/, out)
end
def test_ls_grep
pend if RUBY_ENGINE == 'truffleruby'
out, err = execute_lines("ls 42\n")