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

ruby-changes:34881

From: nobu <ko1@a...>
Date: Sun, 27 Jul 2014 01:22:57 +0900 (JST)
Subject: [ruby-changes:34881] nobu:r46964 (trunk): proc.c: method_super_method

nobu	2014-07-27 01:22:41 +0900 (Sun, 27 Jul 2014)

  New Revision: 46964

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46964

  Log:
    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]

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/proc.c
    trunk/test/ruby/test_method.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 46963)
+++ ChangeLog	(revision 46964)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Jul 27 01:22:39 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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@r...>
 
 	* ext/objspace/objspace_dump.c (dump_append): avoid fflush.
Index: proc.c
===================================================================
--- proc.c	(revision 46963)
+++ proc.c	(revision 46964)
@@ -1190,8 +1190,8 @@ rb_obj_is_method(VALUE m) https://github.com/ruby/ruby/blob/trunk/proc.c#L1190
 }
 
 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, VALU https://github.com/ruby/ruby/blob/trunk/proc.c#L1213
 		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);
 	}
     }
@@ -1272,6 +1274,13 @@ mnew_from_me(rb_method_entry_t *me, VALU https://github.com/ruby/ruby/blob/trunk/proc.c#L1274
 }
 
 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)
 {
     VALUE defined_class;
@@ -2413,6 +2422,25 @@ method_proc(VALUE method) https://github.com/ruby/ruby/blob/trunk/proc.c#L2422
     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) https://github.com/ruby/ruby/blob/trunk/proc.c#L2787
     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) https://github.com/ruby/ruby/blob/trunk/proc.c#L2809
     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);
Index: NEWS
===================================================================
--- NEWS	(revision 46963)
+++ NEWS	(revision 46964)
@@ -63,6 +63,8 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L63
 * 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)
 
Index: test/ruby/test_method.rb
===================================================================
--- test/ruby/test_method.rb	(revision 46963)
+++ test/ruby/test_method.rb	(revision 46964)
@@ -806,4 +806,54 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L806
     }
     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

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

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