mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
proc.c: method_super_method
* proc.c (method_super_method): new method Method#super_method, which returns a method object of the method to be called by `super` in the receiver method object. [ruby-core:62202] [Feature #9781] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46964 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
042a162af1
commit
b4981594dd
4 changed files with 91 additions and 2 deletions
|
@ -1,3 +1,10 @@
|
|||
Sun Jul 27 01:22:39 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* proc.c (method_super_method): new method Method#super_method,
|
||||
which returns a method object of the method to be called by
|
||||
`super` in the receiver method object.
|
||||
[ruby-core:62202] [Feature #9781]
|
||||
|
||||
Sat Jul 26 17:22:14 2014 URABE Shyouhei <shyouhei@ruby-lang.org>
|
||||
|
||||
* ext/objspace/objspace_dump.c (dump_append): avoid fflush.
|
||||
|
|
2
NEWS
2
NEWS
|
@ -63,6 +63,8 @@ with all sufficient information, see the ChangeLog file.
|
|||
* Method
|
||||
* New methods:
|
||||
* Method#curry([arity]) returns a curried Proc.
|
||||
* Method#super_method returns a Method of superclass, which would be called
|
||||
when super is used.
|
||||
|
||||
=== Core classes compatibility issues (excluding feature bug fixes)
|
||||
|
||||
|
|
34
proc.c
34
proc.c
|
@ -1190,8 +1190,8 @@ rb_obj_is_method(VALUE m)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
|
||||
VALUE obj, ID id, VALUE mclass, int scope)
|
||||
mnew_internal(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
|
||||
VALUE obj, ID id, VALUE mclass, int scope, int error)
|
||||
{
|
||||
VALUE method;
|
||||
VALUE rclass = klass;
|
||||
|
@ -1213,12 +1213,14 @@ mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
|
|||
goto gen_method;
|
||||
}
|
||||
}
|
||||
if (!error) return Qnil;
|
||||
rb_print_undef(klass, id, 0);
|
||||
}
|
||||
def = me->def;
|
||||
if (flag == NOEX_UNDEF) {
|
||||
flag = me->flag;
|
||||
if (scope && (flag & NOEX_MASK) != NOEX_PUBLIC) {
|
||||
if (!error) return Qnil;
|
||||
rb_print_inaccessible(klass, id, flag & NOEX_MASK);
|
||||
}
|
||||
}
|
||||
|
@ -1271,6 +1273,13 @@ mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
|
|||
return method;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
|
||||
VALUE obj, ID id, VALUE mclass, int scope)
|
||||
{
|
||||
return mnew_internal(me, defined_class, klass, obj, id, mclass, scope, TRUE);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
|
||||
{
|
||||
|
@ -2413,6 +2422,25 @@ method_proc(VALUE method)
|
|||
return procval;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
method_super_method(VALUE method)
|
||||
{
|
||||
struct METHOD *data;
|
||||
VALUE defined_class, super_class;
|
||||
rb_method_entry_t *me;
|
||||
|
||||
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
|
||||
defined_class = data->defined_class;
|
||||
if (BUILTIN_TYPE(defined_class) == T_MODULE) defined_class = data->rclass;
|
||||
super_class = RCLASS_SUPER(defined_class);
|
||||
if (!super_class) return Qnil;
|
||||
me = rb_method_entry_without_refinements(super_class, data->id, &defined_class);
|
||||
if (!me) return Qnil;
|
||||
return mnew_internal(me, defined_class,
|
||||
super_class, data->recv, data->id,
|
||||
rb_obj_class(method), FALSE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* local_jump_error.exit_value -> obj
|
||||
|
@ -2759,6 +2787,7 @@ Init_Proc(void)
|
|||
rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
|
||||
rb_define_method(rb_cMethod, "source_location", rb_method_location, 0);
|
||||
rb_define_method(rb_cMethod, "parameters", rb_method_parameters, 0);
|
||||
rb_define_method(rb_cMethod, "super_method", method_super_method, 0);
|
||||
rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
|
||||
rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
|
||||
rb_define_method(rb_mKernel, "singleton_method", rb_obj_singleton_method, 1);
|
||||
|
@ -2780,6 +2809,7 @@ Init_Proc(void)
|
|||
rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
|
||||
rb_define_method(rb_cUnboundMethod, "source_location", rb_method_location, 0);
|
||||
rb_define_method(rb_cUnboundMethod, "parameters", rb_method_parameters, 0);
|
||||
rb_define_method(rb_cUnboundMethod, "super_method", method_super_method, 0);
|
||||
|
||||
/* Module#*_method */
|
||||
rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1);
|
||||
|
|
|
@ -806,4 +806,54 @@ class TestMethod < Test::Unit::TestCase
|
|||
}
|
||||
assert_curry_var_args(c.new.method(:var_args))
|
||||
end
|
||||
|
||||
Feature9781 = '[ruby-core:62202] [Feature #9781]'
|
||||
|
||||
def test_super_method
|
||||
o = Derived.new
|
||||
m = o.method(:foo).super_method
|
||||
assert_equal(Base, m.owner, Feature9781)
|
||||
assert_same(o, m.receiver, Feature9781)
|
||||
assert_equal(:foo, m.name, Feature9781)
|
||||
m = assert_nothing_raised(NameError, Feature9781) {break m.super_method}
|
||||
assert_nil(m, Feature9781)
|
||||
end
|
||||
|
||||
def test_super_method_unbound
|
||||
m = Derived.instance_method(:foo)
|
||||
m = m.super_method
|
||||
assert_equal(Base.instance_method(:foo), m, Feature9781)
|
||||
m = assert_nothing_raised(NameError, Feature9781) {break m.super_method}
|
||||
assert_nil(m, Feature9781)
|
||||
end
|
||||
|
||||
def test_super_method_module
|
||||
m1 = Module.new {def foo; end}
|
||||
c1 = Class.new(Derived) {include m1; def foo; end}
|
||||
m = c1.instance_method(:foo)
|
||||
assert_equal(c1, m.owner, Feature9781)
|
||||
m = m.super_method
|
||||
assert_equal(m1, m.owner, Feature9781)
|
||||
m = m.super_method
|
||||
assert_equal(Derived, m.owner, Feature9781)
|
||||
m = m.super_method
|
||||
assert_equal(Base, m.owner, Feature9781)
|
||||
m2 = Module.new {def foo; end}
|
||||
o = c1.new.extend(m2)
|
||||
m = o.method(:foo)
|
||||
assert_equal(m2, m.owner, Feature9781)
|
||||
m = m.super_method
|
||||
assert_equal(c1, m.owner, Feature9781)
|
||||
assert_same(o, m.receiver, Feature9781)
|
||||
end
|
||||
|
||||
def test_super_method_removed
|
||||
c1 = Class.new {private def foo; end}
|
||||
c2 = Class.new(c1) {public :foo}
|
||||
c3 = Class.new(c2) {def foo; end}
|
||||
c1.class_eval {undef foo}
|
||||
m = c3.instance_method(:foo)
|
||||
m = assert_nothing_raised(NameError, Feature9781) {break m.super_method}
|
||||
assert_nil(m, Feature9781)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue