[前][次][番号順一覧][スレッド一覧]

ruby-changes:58854

From: zverok <ko1@a...>
Date: Wed, 20 Nov 2019 13:43:18 +0900 (JST)
Subject: [ruby-changes:58854] 4b583cff97 (master): Method parameters inspect

https://git.ruby-lang.org/ruby.git/commit/?id=4b583cff97

From 4b583cff97025394fab4a014a2a8606dfb557475 Mon Sep 17 00:00:00 2001
From: zverok <zverok.offline@g...>
Date: Sun, 27 Oct 2019 12:39:33 +0200
Subject: Method parameters inspect

Example:

    def m(a, b=nil, *c, d:, e: nil, **rest, &block)
    end
    p method(:m)
    #=> #<Method: m(a, b=<default>, *c, d:, e: <default>, **rest, &block) ...>

diff --git a/proc.c b/proc.c
index 2dc625b..e37ac1c 100644
--- a/proc.c
+++ b/proc.c
@@ -2827,7 +2827,64 @@ method_inspect(VALUE method) https://github.com/ruby/ruby/blob/trunk/proc.c#L2827
     }
 
     // parameter information
-    // TODO
+    {
+        VALUE params = rb_method_parameters(method);
+        VALUE pair, name, kind;
+        int arg_num = 1;
+        const VALUE req = ID2SYM(rb_intern("req"));
+        const VALUE opt = ID2SYM(rb_intern("opt"));
+        const VALUE keyreq = ID2SYM(rb_intern("keyreq"));
+        const VALUE key = ID2SYM(rb_intern("key"));
+        const VALUE rest = ID2SYM(rb_intern("rest"));
+        const VALUE keyrest = ID2SYM(rb_intern("keyrest"));
+        const VALUE block = ID2SYM(rb_intern("block"));
+        const VALUE nokey = ID2SYM(rb_intern("nokey"));
+
+        rb_str_buf_cat2(str, "(");
+
+        for (int i = 0; i < RARRAY_LEN(params); i++) {
+            pair = RARRAY_AREF(params, i);
+            kind = RARRAY_AREF(pair, 0);
+            name = RARRAY_AREF(pair, 1);
+            // FIXME: in tests it turns out that kind, name = [:req] produces name to be false. Why?..
+            if (NIL_P(name) || name == Qfalse) {
+                // FIXME: can it be reduced to switch/case?
+                if (kind == req || kind == opt) {
+                    name = rb_sprintf("arg%d", arg_num);
+                    arg_num++;
+                } else if (kind == rest || kind == keyrest) {
+                    name = rb_str_new2("");
+                } else if (kind == block) {
+                    name = rb_str_new2("block");
+                } else if (kind == nokey) {
+                    name = rb_str_new2("nil");
+                }
+            }
+
+            if (kind == req) {
+                rb_str_catf(str, "%"PRIsVALUE, name);
+            } else if (kind == opt) {
+                rb_str_catf(str, "%"PRIsVALUE"=<default>", name);
+            } else if (kind == keyreq) {
+                rb_str_catf(str, "%"PRIsVALUE":", name);
+            } else if (kind == key) {
+                rb_str_catf(str, "%"PRIsVALUE": <default>", name);
+            } else if (kind == rest) {
+                rb_str_catf(str, "*%"PRIsVALUE, name);
+            } else if (kind == keyrest) {
+                rb_str_catf(str, "**%"PRIsVALUE, name);
+            } else if (kind == block) {
+                rb_str_catf(str, "&%"PRIsVALUE, name);
+            } else if (kind == nokey) {
+                rb_str_buf_cat2(str, "**nil");
+            }
+
+            if (i < RARRAY_LEN(params) - 1) {
+                rb_str_buf_cat2(str, ", ");
+            }
+        }
+        rb_str_buf_cat2(str, ")");
+    }
 
     { // source location
         VALUE loc = rb_method_location(method);
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 3942e04..efd5fae 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -22,6 +22,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L22
   def mo5(a, *b, c) end
   def mo6(a, *b, c, &d) end
   def mo7(a, b = nil, *c, d, &e) end
+  def mo8(a, b = nil, *, d, &e) end
   def ma1((a), &b) nil && a end
   def mk1(**) end
   def mk2(**o) nil && o end
@@ -30,6 +31,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L31
   def mk5(a, b = nil, **o) nil && o end
   def mk6(a, b = nil, c, **o) nil && o end
   def mk7(a, b = nil, *c, d, **o) nil && o end
+  def mk8(a, b = nil, *c, d, e:, f: nil, **o) nil && o end
   def mnk(**nil) end
 
   class Base
@@ -435,27 +437,27 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L437
     o = Object.new
     def o.foo; end; line_no = __LINE__
     m = o.method(:foo)
-    assert_equal("#<Method: #{ o.inspect }.foo #{__FILE__}:#{line_no}>", m.inspect)
+    assert_equal("#<Method: #{ o.inspect }.foo() #{__FILE__}:#{line_no}>", m.inspect)
     m = o.method(:foo)
-    assert_match("#<UnboundMethod: #{ class << o; self; end.inspect }#foo #{__FILE__}:#{line_no}", m.unbind.inspect)
+    assert_match("#<UnboundMethod: #{ class << o; self; end.inspect }#foo() #{__FILE__}:#{line_no}", m.unbind.inspect)
 
     c = Class.new
     c.class_eval { def foo; end; }; line_no = __LINE__
     m = c.new.method(:foo)
-    assert_equal("#<Method: #{ c.inspect }#foo #{__FILE__}:#{line_no}>", m.inspect)
+    assert_equal("#<Method: #{ c.inspect }#foo() #{__FILE__}:#{line_no}>", m.inspect)
     m = c.instance_method(:foo)
-    assert_equal("#<UnboundMethod: #{ c.inspect }#foo #{__FILE__}:#{line_no}>", m.inspect)
+    assert_equal("#<UnboundMethod: #{ c.inspect }#foo() #{__FILE__}:#{line_no}>", m.inspect)
 
     c2 = Class.new(c)
     c2.class_eval { private :foo }
     m2 = c2.new.method(:foo)
-    assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo #{__FILE__}:#{line_no}>", m2.inspect)
+    assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo() #{__FILE__}:#{line_no}>", m2.inspect)
 
     bug7806 = '[ruby-core:52048] [Bug #7806]'
     c3 = Class.new(c)
     c3.class_eval { alias bar foo }
     m3 = c3.new.method(:bar)
-    assert_equal("#<Method: #{c3.inspect}(#{c.inspect})#bar(foo) #{__FILE__}:#{line_no}>", m3.inspect, bug7806)
+    assert_equal("#<Method: #{c3.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m3.inspect, bug7806)
   end
 
   def test_callee_top_level
@@ -527,6 +529,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L529
   define_method(:pmk5) {|a, b = nil, **o|}
   define_method(:pmk6) {|a, b = nil, c, **o|}
   define_method(:pmk7) {|a, b = nil, *c, d, **o|}
+  define_method(:pmk8) {|a, b = nil, *c, d, e:, f: nil, **o|}
   define_method(:pmnk) {|**nil|}
 
   def test_bound_parameters
@@ -540,6 +543,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L543
     assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:mo5).parameters)
     assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:mo6).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:mo7).parameters)
+    assert_equal([[:req, :a], [:opt, :b], [:rest], [:req, :d], [:block, :e]], method(:mo8).parameters)
     assert_equal([[:req], [:block, :b]], method(:ma1).parameters)
     assert_equal([[:keyrest]], method(:mk1).parameters)
     assert_equal([[:keyrest, :o]], method(:mk2).parameters)
@@ -548,6 +552,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L552
     assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], method(:mk5).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], method(:mk6).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], method(:mk7).parameters)
+    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:mk8).parameters)
     assert_equal([[:nokey]], method(:mnk).parameters)
   end
 
@@ -562,6 +567,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L567
     assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:mo5).parameters)
     assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:mo6).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:mo7).parameters)
+    assert_equal([[:req, :a], [:opt, :b], [:rest], [:req, :d], [:block, :e]], self.class.instance_method(:mo8).parameters)
     assert_equal([[:req], [:block, :b]], self.class.instance_method(:ma1).parameters)
     assert_equal([[:keyrest]], self.class.instance_method(:mk1).parameters)
     assert_equal([[:keyrest, :o]], self.class.instance_method(:mk2).parameters)
@@ -570,6 +576,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L576
     assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], self.class.instance_method(:mk5).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], self.class.instance_method(:mk6).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], self.class.instance_method(:mk7).parameters)
+    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:mk8).parameters)
     assert_equal([[:nokey]], self.class.instance_method(:mnk).parameters)
   end
 
@@ -592,6 +599,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L599
     assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], method(:pmk5).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], method(:pmk6).parameters)
     assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], method(:pmk7).parameters)
+    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:pmk8).parameters)
     assert_equal([[:nokey]], method(:pmnk).parameters)
   end
 
@@ -615,6 +623,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L623
     assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], self.class.instance_method(:pmk5).parameters)
     assert_equal([[:req, : (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]