Skip to content

Commit 73edff2

Browse files
committed
Dump ancestors' methods by ls command
1 parent 109cbfc commit 73edff2

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

lib/irb/cmd/ls.rb

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require "reline"
4+
require 'set'
45
require_relative "nop"
56
require_relative "../color"
67

@@ -16,13 +17,36 @@ def execute(*arg, grep: nil)
1617
klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
1718

1819
o.dump("constants", obj.constants) if obj.respond_to?(:constants)
19-
o.dump("#{klass}.methods", obj.singleton_methods(false))
20-
o.dump("#{klass}#methods", klass.public_instance_methods(false))
20+
dump_singleton_methods(o, klass, obj)
21+
dump_instance_methods(o, klass)
2122
o.dump("instance variables", obj.instance_variables)
2223
o.dump("class variables", klass.class_variables)
2324
o.dump("locals", locals)
2425
end
2526

27+
def dump_singleton_methods(o, klass, obj)
28+
maps = class_method_map(obj.singleton_class.ancestors.take_while { |c| c != klass })
29+
maps.each do |mod, methods|
30+
name = mod == obj.singleton_class ? "#{klass}.methods" : "#{mod}#methods"
31+
o.dump(name, methods)
32+
end
33+
end
34+
35+
def dump_instance_methods(o, klass)
36+
maps = class_method_map(klass.ancestors)
37+
maps.each do |mod, methods|
38+
o.dump("#{mod}#methods", methods)
39+
end
40+
end
41+
42+
def class_method_map(classes)
43+
dumped = Set.new
44+
classes.reject { |mod| mod >= Object }.map do |mod|
45+
methods = mod.public_instance_methods(false).select { |m| dumped.add?(m) }
46+
[mod, methods]
47+
end.reverse
48+
end
49+
2650
class Output
2751
MARGIN = " "
2852

test/irb/test_cmd.rb

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,24 @@ def test_irb_load
377377

378378
def test_ls
379379
input = TestInputMethod.new([
380-
"ls Object.new.tap { |o| o.instance_variable_set(:@a, 1) }\n",
380+
"class C\n",
381+
" def m1() end\n",
382+
"end\n",
383+
384+
"module M\n",
385+
" def m2() end\n",
386+
"end\n",
387+
388+
"module M2\n",
389+
" include M\n",
390+
" def m3() end\n",
391+
"end\n",
392+
393+
"obj = C.new\n",
394+
"obj.instance_variable_set(:@a, 1)\n",
395+
"obj.extend M2\n",
396+
"def obj.m4() end\n",
397+
"ls obj\n",
381398
])
382399
IRB.init_config(nil)
383400
workspace = IRB::WorkSpace.new(self)
@@ -390,6 +407,10 @@ def test_ls
390407
end
391408
assert_empty err
392409
assert_match(/^instance variables:\s+@a\n/m, out)
410+
assert_match(/C#methods: m1\n/m, out)
411+
assert_match(/M#methods: m2\n/m, out)
412+
assert_match(/M2#methods: m3\n/m, out)
413+
assert_match(/C.methods: m4\n/m, out)
393414
end
394415

395416
def test_show_source

0 commit comments

Comments
 (0)