diff options
author | Jeremy Evans <code@jeremyevans.net> | 2022-06-06 09:57:32 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-06 09:57:32 -0700 |
commit | 7cda7fbbdc14f4262afaa94cdeb5a5987f1eb01a (patch) | |
tree | 6f7da1ed9ce694564c932f9dcc15fd6b04b86c0b | |
parent | b737998d25f1379117fbf11a578462e6ba12037e (diff) | |
download | ruby-7cda7fbbdc14f4262afaa94cdeb5a5987f1eb01a.tar.gz |
Add Module#undefined_instance_methods
Implements [Feature #12655]
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
-rw-r--r-- | NEWS.md | 2 | ||||
-rw-r--r-- | class.c | 24 | ||||
-rw-r--r-- | internal/class.h | 1 | ||||
-rw-r--r-- | object.c | 2 | ||||
-rw-r--r-- | test/ruby/test_module.rb | 9 |
5 files changed, 38 insertions, 0 deletions
@@ -112,6 +112,7 @@ Note: We're only listing outstanding class updates. * Module.used_refinements has been added. [[Feature #14332]] * Module#refinements has been added. [[Feature #12737]] * Module#const_added has been added. [[Feature #17881]] + * Module#undefined_instance_methods has been added. [[Feature #12655]] * Proc * Proc#dup returns an instance of subclass. [[Bug #17545]] @@ -235,6 +236,7 @@ The following deprecated APIs are removed. ## Miscellaneous changes [Feature #12005]: https://bugs.ruby-lang.org/issues/12005 +[Feature #12655]: https://bugs.ruby-lang.org/issues/12655 [Feature #12737]: https://bugs.ruby-lang.org/issues/12737 [Feature #13110]: https://bugs.ruby-lang.org/issues/13110 [Feature #14332]: https://bugs.ruby-lang.org/issues/14332 @@ -1638,6 +1638,15 @@ ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) return ins_methods_type_i(name, type, ary, METHOD_VISI_PUBLIC); } +static int +ins_methods_undef_i(st_data_t name, st_data_t type, st_data_t ary) +{ + if ((rb_method_visibility_t)type == METHOD_VISI_UNDEF) { + ins_methods_push(name, ary); + } + return ST_CONTINUE; +} + struct method_entry_arg { st_table *list; int recur; @@ -1809,6 +1818,21 @@ rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod) /* * call-seq: + * mod.undefined_instance_methods -> array + * + * Returns a list of the undefined instance methods defined in <i>mod</i>. + * The undefined methods of any ancestors are not included. + */ + +VALUE +rb_class_undefined_instance_methods(VALUE mod) +{ + VALUE include_super = Qfalse; + return class_instance_method_list(1, &include_super, mod, 0, ins_methods_undef_i); +} + +/* + * call-seq: * obj.methods(regular=true) -> array * * Returns a list of the names of public and protected methods of diff --git a/internal/class.h b/internal/class.h index 70e671b2c2..ae680564a6 100644 --- a/internal/class.h +++ b/internal/class.h @@ -149,6 +149,7 @@ VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj); VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj); VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj); VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_class_undefined_instance_methods(VALUE mod); VALUE rb_special_singleton_class(VALUE); VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach); VALUE rb_singleton_class_get(VALUE obj); @@ -4398,6 +4398,8 @@ InitVM_Object(void) rb_class_protected_instance_methods, -1); /* in class.c */ rb_define_method(rb_cModule, "private_instance_methods", rb_class_private_instance_methods, -1); /* in class.c */ + rb_define_method(rb_cModule, "undefined_instance_methods", + rb_class_undefined_instance_methods, 0); /* in class.c */ rb_define_method(rb_cModule, "constants", rb_mod_constants, -1); /* in variable.c */ rb_define_method(rb_cModule, "const_get", rb_mod_const_get, -1); diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index c7245ab2db..3dae3916ff 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -994,6 +994,15 @@ class TestModule < Test::Unit::TestCase assert_equal([:bClass1], BClass.public_instance_methods(false)) end + def test_undefined_instance_methods + assert_equal([], AClass.undefined_instance_methods) + assert_equal([], BClass.undefined_instance_methods) + c = Class.new(AClass) {undef aClass} + assert_equal([:aClass], c.undefined_instance_methods) + c = Class.new(c) + assert_equal([], c.undefined_instance_methods) + end + def test_s_public o = (c = Class.new(AClass)).new assert_raise(NoMethodError, /private method/) {o.aClass1} |