* proc.c (rb_mod_method_arity): return original arity of the method if
  aliased because of visibility change, like as Method#arity.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38967 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2013-01-29 07:49:22 +00:00
Родитель 2d55537dce
Коммит b0c4ac7779
6 изменённых файлов: 98 добавлений и 1 удалений

Просмотреть файл

@ -1,3 +1,8 @@
Tue Jan 29 16:49:19 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* proc.c (rb_mod_method_arity): return original arity of the method if
aliased because of visibility change, like as Method#arity.
Tue Jan 29 12:05:18 2013 Tanaka Akira <akr@fsij.org>
* test/ruby/test_marshal.rb: remove temporally files early.

22
ext/-test-/method/arity.c Normal file
Просмотреть файл

@ -0,0 +1,22 @@
#include "ruby.h"
static VALUE
obj_method_arity(VALUE self, VALUE obj, VALUE mid)
{
int arity = rb_obj_method_arity(obj, rb_check_id(&mid));
return INT2FIX(arity);
}
static VALUE
mod_method_arity(VALUE self, VALUE mod, VALUE mid)
{
int arity = rb_mod_method_arity(mod, rb_check_id(&mid));
return INT2FIX(arity);
}
void
Init_arity(VALUE mod)
{
rb_define_module_function(mod, "obj_method_arity", obj_method_arity, 2);
rb_define_module_function(mod, "mod_method_arity", mod_method_arity, 2);
}

Просмотреть файл

@ -0,0 +1,6 @@
$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
inits = $srcs.map {|s| File.basename(s, ".*")}
inits.delete("init")
inits.map! {|s|"X(#{s})"}
$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
create_makefile("-test-/method")

11
ext/-test-/method/init.c Normal file
Просмотреть файл

@ -0,0 +1,11 @@
#include "ruby.h"
#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
void
Init_method(void)
{
VALUE mBug = rb_define_module("Bug");
VALUE klass = rb_define_module_under(mBug, "Method");
TEST_INIT_FUNCS(init);
}

18
proc.c
Просмотреть файл

@ -1743,10 +1743,26 @@ method_arity(VALUE method)
return rb_method_entry_arity(data->me);
}
static rb_method_entry_t *
original_method_entry(VALUE mod, ID id)
{
VALUE rclass;
rb_method_entry_t *me;
while ((me = rb_method_entry(mod, id, &rclass)) != 0) {
rb_method_definition_t *def = me->def;
if (!def) break;
if (def->type != VM_METHOD_TYPE_ZSUPER) break;
mod = RCLASS_SUPER(rclass);
id = def->original_id;
}
return me;
}
int
rb_mod_method_arity(VALUE mod, ID id)
{
rb_method_entry_t *me = rb_method_entry(mod, id, 0);
rb_method_entry_t *me = original_method_entry(mod, id);
if (!me) return 0; /* should raise? */
return rb_method_entry_arity(me);
}

Просмотреть файл

@ -0,0 +1,37 @@
require '-test-/method'
require 'test/unit'
class TestMethod < Test::Unit::TestCase
class TestArity < Test::Unit::TestCase
class A
def foo0()
end
def foom1(*a)
end
def foom2(a,*b)
end
def foo1(a)
end
def foo2(a,b)
end
end
class B<A
private :foo1, :foo2
end
METHODS = {foo0: 0, foo1: 1, foo2: 2, foom1: -1, foom2: -2}
def test_base
METHODS.each do |name, arity|
assert_equal(arity, Bug::Method.mod_method_arity(A, name), "A##{name}")
end
end
def test_zsuper
METHODS.each do |name, arity|
assert_equal(arity, Bug::Method.mod_method_arity(B, name), "B##{name}")
end
end
end
end