Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test define method visibility #3873

Merged
merged 5 commits into from May 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 12 additions & 2 deletions core/src/main/java/org/jruby/RubyModule.java
Expand Up @@ -1868,10 +1868,19 @@ public IRubyObject newMethod(IRubyObject receiver, final String methodName, bool

@JRubyMethod(name = "define_method", visibility = PRIVATE, reads = VISIBILITY)
public IRubyObject define_method(ThreadContext context, IRubyObject arg0, Block block) {
Visibility visibility = context.getCurrentVisibility();
Visibility visibility = getVisibilityForDefineMethod(context);

return defineMethodFromBlock(context, arg0, block, visibility);
}

private Visibility getVisibilityForDefineMethod(ThreadContext context) {
Visibility visibility = PUBLIC;

// These checks are similar to rb_vm_cref_in_context from MRI.
if (context.getCurrentFrame().getSelf() == this) visibility = context.getCurrentVisibility();
return visibility;
}

public IRubyObject defineMethodFromBlock(ThreadContext context, IRubyObject arg0, Block block, Visibility visibility) {
final Ruby runtime = context.runtime;
RubySymbol nameSym = TypeConverter.checkID(arg0);
Expand Down Expand Up @@ -1913,7 +1922,8 @@ public IRubyObject defineMethodFromBlock(ThreadContext context, IRubyObject arg0

@JRubyMethod(name = "define_method", visibility = PRIVATE, reads = VISIBILITY)
public IRubyObject define_method(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
Visibility visibility = context.getCurrentVisibility();
Visibility visibility = getVisibilityForDefineMethod(context);

return defineMethodFromCallable(context, arg0, arg1, visibility);
}

Expand Down
61 changes: 51 additions & 10 deletions spec/ruby/core/module/define_method_spec.rb
Expand Up @@ -73,19 +73,60 @@ def test_method

describe "Module#define_method when name is not a special private name" do
describe "given an UnboundMethod" do
it "sets the visibility of the method to the current visibility" do
m = Module.new do
def foo
describe "and called from the target module" do
it "sets the visibility of the method to the current visibility" do
klass = Class.new do
define_method(:bar, ModuleSpecs::EmptyFooMethod)
private
define_method(:baz, ModuleSpecs::EmptyFooMethod)
end
private :foo

klass.should have_public_instance_method(:bar)
klass.should have_private_instance_method(:baz)
end
klass = Class.new do
define_method(:bar, m.instance_method(:foo))
private
define_method(:baz, m.instance_method(:foo))
end

describe "and called from another module" do
it "sets the visibility of the method to public" do
klass = Class.new
Class.new do
klass.send(:define_method, :bar, ModuleSpecs::EmptyFooMethod)
private
klass.send(:define_method, :baz, ModuleSpecs::EmptyFooMethod)
end

klass.should have_public_instance_method(:bar)
klass.should have_public_instance_method(:baz)
end
end
end

describe "passed a block" do
describe "and called from the target module" do
it "sets the visibility of the method to the current visibility" do
klass = Class.new do
define_method(:bar) {}
private
define_method(:baz) {}
end

klass.should have_public_instance_method(:bar)
klass.should have_private_instance_method(:baz)
end
end

describe "and called from another module" do
it "sets the visibility of the method to public" do
klass = Class.new
Class.new do
klass.send(:define_method, :bar) {}
private
klass.send(:define_method, :baz) {}
end

klass.should have_public_instance_method(:bar)
klass.should have_public_instance_method(:baz)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

end
klass.should have_public_instance_method(:bar)
klass.should have_private_instance_method(:baz)
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions spec/ruby/core/module/fixtures/classes.rb
Expand Up @@ -576,6 +576,13 @@ def self.===(*)
raise 'method contents are irrelevant to test'
end
end

m = Module.new do
def foo
end
private :foo
end
EmptyFooMethod = m.instance_method(:foo)
end

class Object
Expand Down
2 changes: 2 additions & 0 deletions spec/truffle/tags/core/module/define_method_tags.txt
@@ -0,0 +1,2 @@
fails:Module#define_method when name is not a special private name given an UnboundMethod and called from another module sets the visibility of the method to public
fails:Module#define_method when name is not a special private name passed a block and called from another module sets the visibility of the method to public