diff options
| -rw-r--r-- | src/class.c | 38 | ||||
| -rw-r--r-- | test/t/module.rb | 14 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/class.c b/src/class.c index fe2baa4f2..ed1b0cd25 100644 --- a/src/class.c +++ b/src/class.c @@ -722,6 +722,43 @@ mrb_mod_include(mrb_state *mrb, mrb_value klass) return klass; } +/* 15.2.2.4.28 */ +/* + * call-seq: + * mod.include?(module) -> true or false + * + * Returns <code>true</code> if <i>module</i> is included in + * <i>mod</i> or one of <i>mod</i>'s ancestors. + * + * module A + * end + * class B + * include A + * end + * class C < B + * end + * B.include?(A) #=> true + * C.include?(A) #=> true + * A.include?(A) #=> false + */ +static mrb_value +mrb_mod_include_p(mrb_state *mrb, mrb_value mod) +{ + mrb_value mod2; + struct RClass *c = mrb_class_ptr(mod); + + mrb_get_args(mrb, "o", &mod2); + mrb_check_type(mrb, mod2, MRB_TT_MODULE); + + while (c) { + if (c->tt == MRB_TT_ICLASS) { + if (c->c == mrb_class_ptr(mod2)) return mrb_true_value(); + } + c = c->super; + } + return mrb_false_value(); +} + static mrb_value mrb_mod_ancestors(mrb_state *mrb, mrb_value self) { @@ -1424,6 +1461,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, ARGS_REQ(1)); /* 15.2.2.4.25 */ mrb_define_method(mrb, mod, "extended", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.26 */ mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY()); /* 15.2.2.4.27 */ + mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, ARGS_REQ(1)); /* 15.2.2.4.28 */ mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, ARGS_REQ(1)); /* 15.2.2.4.10 */ mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.29 */ mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */ diff --git a/test/t/module.rb b/test/t/module.rb index 511658150..96bded1ee 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -92,6 +92,20 @@ assert('Module#include', '15.2.2.4.27') do Test4Include2.const_get(:Const4Include) == 42 end +assert('Module#include?', '15.2.2.4.28') do + module Test4IncludeP + end + class Test4IncludeP2 + include Test4IncludeP + end + class Test4IncludeP3 < Test4IncludeP2 + end + + Test4IncludeP2.include?(Test4IncludeP) && + Test4IncludeP3.include?(Test4IncludeP) && + ! Test4IncludeP.include?(Test4IncludeP) +end + assert('Module#included', '15.2.2.4.29') do module Test4Included Const4Included = 42 |
