зеркало из https://github.com/github/ruby.git
Fix problem about notimplemented case
Re-revert r64340, and take care about notimplemented case. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64343 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
7496672904
Коммит
67d87b192b
|
@ -468,17 +468,42 @@ class TestModule < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_method_defined?
|
def test_method_defined?
|
||||||
assert !User.method_defined?(:wombat)
|
[User, Class.new{include User}, Class.new{prepend User}].each do |klass|
|
||||||
assert User.method_defined?(:mixin)
|
[[], [true]].each do |args|
|
||||||
assert User.method_defined?(:user)
|
assert !klass.method_defined?(:wombat, *args)
|
||||||
assert User.method_defined?(:user2)
|
assert klass.method_defined?(:mixin, *args)
|
||||||
assert !User.method_defined?(:user3)
|
assert klass.method_defined?(:user, *args)
|
||||||
|
assert klass.method_defined?(:user2, *args)
|
||||||
|
assert !klass.method_defined?(:user3, *args)
|
||||||
|
|
||||||
assert !User.method_defined?("wombat")
|
assert !klass.method_defined?("wombat", *args)
|
||||||
assert User.method_defined?("mixin")
|
assert klass.method_defined?("mixin", *args)
|
||||||
assert User.method_defined?("user")
|
assert klass.method_defined?("user", *args)
|
||||||
assert User.method_defined?("user2")
|
assert klass.method_defined?("user2", *args)
|
||||||
assert !User.method_defined?("user3")
|
assert !klass.method_defined?("user3", *args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_method_defined_without_include_super
|
||||||
|
assert User.method_defined?(:user, false)
|
||||||
|
assert !User.method_defined?(:mixin, false)
|
||||||
|
assert Mixin.method_defined?(:mixin, false)
|
||||||
|
|
||||||
|
User.const_set(:FOO, c = Class.new)
|
||||||
|
|
||||||
|
c.prepend(User)
|
||||||
|
assert !c.method_defined?(:user, false)
|
||||||
|
c.define_method(:user){}
|
||||||
|
assert c.method_defined?(:user, false)
|
||||||
|
|
||||||
|
assert !c.method_defined?(:mixin, false)
|
||||||
|
c.define_method(:mixin){}
|
||||||
|
assert c.method_defined?(:mixin, false)
|
||||||
|
|
||||||
|
assert !c.method_defined?(:userx, false)
|
||||||
|
c.define_method(:userx){}
|
||||||
|
assert c.method_defined?(:userx, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def module_exec_aux
|
def module_exec_aux
|
||||||
|
@ -974,8 +999,8 @@ class TestModule < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_method_defined
|
def test_method_defined
|
||||||
c = Class.new
|
cl = Class.new
|
||||||
c.class_eval do
|
def_methods = proc do
|
||||||
def foo; end
|
def foo; end
|
||||||
def bar; end
|
def bar; end
|
||||||
def baz; end
|
def baz; end
|
||||||
|
@ -983,33 +1008,47 @@ class TestModule < Test::Unit::TestCase
|
||||||
protected :bar
|
protected :bar
|
||||||
private :baz
|
private :baz
|
||||||
end
|
end
|
||||||
|
cl.class_eval(&def_methods)
|
||||||
|
sc = Class.new(cl)
|
||||||
|
mod = Module.new(&def_methods)
|
||||||
|
only_prepend = Class.new{prepend(mod)}
|
||||||
|
empty_prepend = cl.clone
|
||||||
|
empty_prepend.prepend(Module.new)
|
||||||
|
overlap_prepend = cl.clone
|
||||||
|
overlap_prepend.prepend(mod)
|
||||||
|
|
||||||
assert_equal(true, c.public_method_defined?(:foo))
|
[[], [true], [false]].each do |args|
|
||||||
assert_equal(false, c.public_method_defined?(:bar))
|
[cl, sc, only_prepend, empty_prepend, overlap_prepend].each do |c|
|
||||||
assert_equal(false, c.public_method_defined?(:baz))
|
always_false = [sc, only_prepend].include?(c) && args == [false]
|
||||||
|
|
||||||
# Test if string arguments are converted to symbols
|
assert_equal(always_false ? false : true, c.public_method_defined?(:foo, *args))
|
||||||
assert_equal(true, c.public_method_defined?("foo"))
|
assert_equal(always_false ? false : false, c.public_method_defined?(:bar, *args))
|
||||||
assert_equal(false, c.public_method_defined?("bar"))
|
assert_equal(always_false ? false : false, c.public_method_defined?(:baz, *args))
|
||||||
assert_equal(false, c.public_method_defined?("baz"))
|
|
||||||
|
|
||||||
assert_equal(false, c.protected_method_defined?(:foo))
|
# Test if string arguments are converted to symbols
|
||||||
assert_equal(true, c.protected_method_defined?(:bar))
|
assert_equal(always_false ? false : true, c.public_method_defined?("foo", *args))
|
||||||
assert_equal(false, c.protected_method_defined?(:baz))
|
assert_equal(always_false ? false : false, c.public_method_defined?("bar", *args))
|
||||||
|
assert_equal(always_false ? false : false, c.public_method_defined?("baz", *args))
|
||||||
|
|
||||||
# Test if string arguments are converted to symbols
|
assert_equal(always_false ? false : false, c.protected_method_defined?(:foo, *args))
|
||||||
assert_equal(false, c.protected_method_defined?("foo"))
|
assert_equal(always_false ? false : true, c.protected_method_defined?(:bar, *args))
|
||||||
assert_equal(true, c.protected_method_defined?("bar"))
|
assert_equal(always_false ? false : false, c.protected_method_defined?(:baz, *args))
|
||||||
assert_equal(false, c.protected_method_defined?("baz"))
|
|
||||||
|
|
||||||
assert_equal(false, c.private_method_defined?(:foo))
|
# Test if string arguments are converted to symbols
|
||||||
assert_equal(false, c.private_method_defined?(:bar))
|
assert_equal(always_false ? false : false, c.protected_method_defined?("foo", *args))
|
||||||
assert_equal(true, c.private_method_defined?(:baz))
|
assert_equal(always_false ? false : true, c.protected_method_defined?("bar", *args))
|
||||||
|
assert_equal(always_false ? false : false, c.protected_method_defined?("baz", *args))
|
||||||
|
|
||||||
# Test if string arguments are converted to symbols
|
assert_equal(always_false ? false : false, c.private_method_defined?(:foo, *args))
|
||||||
assert_equal(false, c.private_method_defined?("foo"))
|
assert_equal(always_false ? false : false, c.private_method_defined?(:bar, *args))
|
||||||
assert_equal(false, c.private_method_defined?("bar"))
|
assert_equal(always_false ? false : true, c.private_method_defined?(:baz, *args))
|
||||||
assert_equal(true, c.private_method_defined?("baz"))
|
|
||||||
|
# Test if string arguments are converted to symbols
|
||||||
|
assert_equal(always_false ? false : false, c.private_method_defined?("foo", *args))
|
||||||
|
assert_equal(always_false ? false : false, c.private_method_defined?("bar", *args))
|
||||||
|
assert_equal(always_false ? false : true, c.private_method_defined?("baz", *args))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_top_public_private
|
def test_top_public_private
|
||||||
|
|
135
vm_method.c
135
vm_method.c
|
@ -1278,14 +1278,44 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rb_method_visibility_t
|
||||||
|
check_definition_visibility(VALUE mod, int argc, VALUE *argv)
|
||||||
|
{
|
||||||
|
const rb_method_entry_t *me;
|
||||||
|
VALUE mid, include_super, lookup_mod = mod;
|
||||||
|
int inc_super;
|
||||||
|
ID id;
|
||||||
|
|
||||||
|
rb_scan_args(argc, argv, "11", &mid, &include_super);
|
||||||
|
id = rb_check_id(&mid);
|
||||||
|
if (!id) return METHOD_VISI_UNDEF;
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
inc_super = 1;
|
||||||
|
} else {
|
||||||
|
inc_super = RTEST(include_super);
|
||||||
|
if (!inc_super) {
|
||||||
|
lookup_mod = RCLASS_ORIGIN(mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me = rb_method_entry_without_refinements(lookup_mod, id, NULL);
|
||||||
|
if (me) {
|
||||||
|
if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) return METHOD_VISI_UNDEF;
|
||||||
|
if (!inc_super && me->owner != mod) return METHOD_VISI_UNDEF;
|
||||||
|
return METHOD_ENTRY_VISI(me);
|
||||||
|
}
|
||||||
|
return METHOD_VISI_UNDEF;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* mod.method_defined?(symbol) -> true or false
|
* mod.method_defined?(symbol, inherit=true) -> true or false
|
||||||
* mod.method_defined?(string) -> true or false
|
* mod.method_defined?(string, inherit=true) -> true or false
|
||||||
*
|
*
|
||||||
* Returns +true+ if the named method is defined by
|
* Returns +true+ if the named method is defined by
|
||||||
* _mod_ (or its included modules and, if _mod_ is a class,
|
* _mod_. If _inherit_ is set, the lookup will also search _mod_'s
|
||||||
* its ancestors). Public and protected methods are matched.
|
* ancestors. Public and protected methods are matched.
|
||||||
* String arguments are converted to symbols.
|
* String arguments are converted to symbols.
|
||||||
*
|
*
|
||||||
* module A
|
* module A
|
||||||
|
@ -1306,6 +1336,8 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
|
||||||
* A.method_defined? :method1 #=> true
|
* A.method_defined? :method1 #=> true
|
||||||
* C.method_defined? "method1" #=> true
|
* C.method_defined? "method1" #=> true
|
||||||
* C.method_defined? "method2" #=> true
|
* C.method_defined? "method2" #=> true
|
||||||
|
* C.method_defined? "method2", true #=> true
|
||||||
|
* C.method_defined? "method2", false #=> false
|
||||||
* C.method_defined? "method3" #=> true
|
* C.method_defined? "method3" #=> true
|
||||||
* C.method_defined? "protected_method1" #=> true
|
* C.method_defined? "protected_method1" #=> true
|
||||||
* C.method_defined? "method4" #=> false
|
* C.method_defined? "method4" #=> false
|
||||||
|
@ -1313,37 +1345,26 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_method_defined(VALUE mod, VALUE mid)
|
rb_mod_method_defined(int argc, VALUE *argv, VALUE mod)
|
||||||
{
|
{
|
||||||
ID id = rb_check_id(&mid);
|
rb_method_visibility_t visi = check_definition_visibility(mod, argc, argv);
|
||||||
if (!id || !rb_method_boundp(mod, id, 1)) {
|
return (visi == METHOD_VISI_PUBLIC || visi == METHOD_VISI_PROTECTED) ? Qtrue : Qfalse;
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
return Qtrue;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
check_definition(VALUE mod, VALUE mid, rb_method_visibility_t visi)
|
check_definition(VALUE mod, int argc, VALUE *argv, rb_method_visibility_t visi)
|
||||||
{
|
{
|
||||||
const rb_method_entry_t *me;
|
return (check_definition_visibility(mod, argc, argv) == visi) ? Qtrue : Qfalse;
|
||||||
ID id = rb_check_id(&mid);
|
|
||||||
if (!id) return Qfalse;
|
|
||||||
me = rb_method_entry_without_refinements(mod, id, NULL);
|
|
||||||
if (me) {
|
|
||||||
if (METHOD_ENTRY_VISI(me) == visi) return Qtrue;
|
|
||||||
}
|
|
||||||
return Qfalse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* mod.public_method_defined?(symbol) -> true or false
|
* mod.public_method_defined?(symbol, inherit=true) -> true or false
|
||||||
* mod.public_method_defined?(string) -> true or false
|
* mod.public_method_defined?(string, inherit=true) -> true or false
|
||||||
*
|
*
|
||||||
* Returns +true+ if the named public method is defined by
|
* Returns +true+ if the named public method is defined by
|
||||||
* _mod_ (or its included modules and, if _mod_ is a class,
|
* _mod_. If _inherit_ is set, the lookup will also search _mod_'s
|
||||||
* its ancestors).
|
* ancestors.
|
||||||
* String arguments are converted to symbols.
|
* String arguments are converted to symbols.
|
||||||
*
|
*
|
||||||
* module A
|
* module A
|
||||||
|
@ -1358,26 +1379,28 @@ check_definition(VALUE mod, VALUE mid, rb_method_visibility_t visi)
|
||||||
* def method3() end
|
* def method3() end
|
||||||
* end
|
* end
|
||||||
*
|
*
|
||||||
* A.method_defined? :method1 #=> true
|
* A.method_defined? :method1 #=> true
|
||||||
* C.public_method_defined? "method1" #=> true
|
* C.public_method_defined? "method1" #=> true
|
||||||
* C.public_method_defined? "method2" #=> false
|
* C.public_method_defined? "method1", true #=> true
|
||||||
* C.method_defined? "method2" #=> true
|
* C.public_method_defined? "method1", false #=> true
|
||||||
|
* C.public_method_defined? "method2" #=> false
|
||||||
|
* C.method_defined? "method2" #=> true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
rb_mod_public_method_defined(int argc, VALUE *argv, VALUE mod)
|
||||||
{
|
{
|
||||||
return check_definition(mod, mid, METHOD_VISI_PUBLIC);
|
return check_definition(mod, argc, argv, METHOD_VISI_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* mod.private_method_defined?(symbol) -> true or false
|
* mod.private_method_defined?(symbol, inherit=true) -> true or false
|
||||||
* mod.private_method_defined?(string) -> true or false
|
* mod.private_method_defined?(string, inherit=true) -> true or false
|
||||||
*
|
*
|
||||||
* Returns +true+ if the named private method is defined by
|
* Returns +true+ if the named private method is defined by
|
||||||
* _ mod_ (or its included modules and, if _mod_ is a class,
|
* _mod_. If _inherit_ is set, the lookup will also search _mod_'s
|
||||||
* its ancestors).
|
* ancestors.
|
||||||
* String arguments are converted to symbols.
|
* String arguments are converted to symbols.
|
||||||
*
|
*
|
||||||
* module A
|
* module A
|
||||||
|
@ -1392,26 +1415,28 @@ rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
||||||
* def method3() end
|
* def method3() end
|
||||||
* end
|
* end
|
||||||
*
|
*
|
||||||
* A.method_defined? :method1 #=> true
|
* A.method_defined? :method1 #=> true
|
||||||
* C.private_method_defined? "method1" #=> false
|
* C.private_method_defined? "method1" #=> false
|
||||||
* C.private_method_defined? "method2" #=> true
|
* C.private_method_defined? "method2" #=> true
|
||||||
* C.method_defined? "method2" #=> false
|
* C.private_method_defined? "method2", true #=> true
|
||||||
|
* C.private_method_defined? "method2", false #=> false
|
||||||
|
* C.method_defined? "method2" #=> false
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
rb_mod_private_method_defined(int argc, VALUE *argv, VALUE mod)
|
||||||
{
|
{
|
||||||
return check_definition(mod, mid, METHOD_VISI_PRIVATE);
|
return check_definition(mod, argc, argv, METHOD_VISI_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* mod.protected_method_defined?(symbol) -> true or false
|
* mod.protected_method_defined?(symbol, inherit=true) -> true or false
|
||||||
* mod.protected_method_defined?(string) -> true or false
|
* mod.protected_method_defined?(string, inherit=true) -> true or false
|
||||||
*
|
*
|
||||||
* Returns +true+ if the named protected method is defined
|
* Returns +true+ if the named protected method is defined
|
||||||
* by _mod_ (or its included modules and, if _mod_ is a
|
* _mod_. If _inherit_ is set, the lookup will also search _mod_'s
|
||||||
* class, its ancestors).
|
* ancestors.
|
||||||
* String arguments are converted to symbols.
|
* String arguments are converted to symbols.
|
||||||
*
|
*
|
||||||
* module A
|
* module A
|
||||||
|
@ -1426,16 +1451,18 @@ rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
||||||
* def method3() end
|
* def method3() end
|
||||||
* end
|
* end
|
||||||
*
|
*
|
||||||
* A.method_defined? :method1 #=> true
|
* A.method_defined? :method1 #=> true
|
||||||
* C.protected_method_defined? "method1" #=> false
|
* C.protected_method_defined? "method1" #=> false
|
||||||
* C.protected_method_defined? "method2" #=> true
|
* C.protected_method_defined? "method2" #=> true
|
||||||
* C.method_defined? "method2" #=> true
|
* C.protected_method_defined? "method2", true #=> true
|
||||||
|
* C.protected_method_defined? "method2", false #=> false
|
||||||
|
* C.method_defined? "method2" #=> true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
|
rb_mod_protected_method_defined(int argc, VALUE *argv, VALUE mod)
|
||||||
{
|
{
|
||||||
return check_definition(mod, mid, METHOD_VISI_PROTECTED);
|
return check_definition(mod, argc, argv, METHOD_VISI_PROTECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2121,10 +2148,10 @@ Init_eval_method(void)
|
||||||
rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
|
rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
|
||||||
rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
|
rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
|
||||||
|
|
||||||
rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
|
rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, -1);
|
||||||
rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
|
rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, -1);
|
||||||
rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
|
rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, -1);
|
||||||
rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
|
rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, -1);
|
||||||
rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
|
rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
|
||||||
rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
|
rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче