Skip to content

Commit dceb22e

Browse files
fix for method and unbound method super_method method
1 parent 489cd92 commit dceb22e

File tree

5 files changed

+89
-22
lines changed

5 files changed

+89
-22
lines changed

core/src/main/java/org/jruby/RubyMethod.java

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* Copyright (C) 2002 Anders Bengtsson <ndrsbngtssn@yahoo.se>
1717
* Copyright (C) 2004 Charles O Nutter <headius@headius.com>
1818
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
19-
*
19+
*
2020
* Alternatively, the contents of this file may be used under the terms of
2121
* either of the GNU General Public License Version 2 or later (the "GPL"),
2222
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -38,6 +38,7 @@
3838
import org.jruby.internal.runtime.methods.DelegatingDynamicMethod;
3939
import org.jruby.internal.runtime.methods.DynamicMethod;
4040
import org.jruby.internal.runtime.methods.IRMethodArgs;
41+
import org.jruby.internal.runtime.methods.PartialDelegatingMethod;
4142
import org.jruby.internal.runtime.methods.ProcMethod;
4243
import org.jruby.runtime.ArgumentDescriptor;
4344
import org.jruby.runtime.Block;
@@ -51,13 +52,13 @@
5152
import org.jruby.runtime.builtin.IRubyObject;
5253
import org.jruby.runtime.callsite.CacheEntry;
5354

54-
/**
55+
/**
5556
* The RubyMethod class represents a RubyMethod object.
56-
*
57+
*
5758
* You can get such a method by calling the "method" method of an object.
58-
*
59+
*
5960
* Note: This was renamed from Method.java
60-
*
61+
*
6162
* @author jpetersen
6263
* @since 0.2.3
6364
*/
@@ -70,7 +71,7 @@ protected RubyMethod(Ruby runtime, RubyClass rubyClass) {
7071
}
7172

7273
/** Create the RubyMethod class and add it to the Ruby runtime.
73-
*
74+
*
7475
*/
7576
public static RubyClass createMethodClass(Ruby runtime) {
7677
// TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here. Confirm. JRUBY-415
@@ -81,7 +82,7 @@ public static RubyClass createMethodClass(Ruby runtime) {
8182

8283
methodClass.defineAnnotatedMethods(AbstractRubyMethod.class);
8384
methodClass.defineAnnotatedMethods(RubyMethod.class);
84-
85+
8586
return methodClass;
8687
}
8788

@@ -108,7 +109,7 @@ public static RubyMethod newMethod(
108109
}
109110

110111
/** Call the method.
111-
*
112+
*
112113
*/
113114
@JRubyMethod(name = {"call", "[]"})
114115
public IRubyObject call(ThreadContext context, Block block) {
@@ -132,7 +133,7 @@ public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block)
132133
}
133134

134135
/** Returns the number of arguments a method accepted.
135-
*
136+
*
136137
* @return the number of arguments of a method.
137138
*/
138139
@JRubyMethod
@@ -206,7 +207,7 @@ public RubyMethod rbClone() {
206207
}
207208

208209
/** Create a Proc object.
209-
*
210+
*
210211
*/
211212
@JRubyMethod
212213
public IRubyObject to_proc(ThreadContext context) {
@@ -225,19 +226,19 @@ public IRubyObject to_proc(ThreadContext context) {
225226
body = new MethodBlockBody(runtime.getStaticScopeFactory().getDummyScope(), signature, entry, argsDesc,
226227
receiver, originModule, originName, getFilename(), line == -1 ? -1 : line - 1);
227228
Block b = MethodBlockBody.createMethodBlock(body);
228-
229+
229230
return RubyProc.newProc(runtime, b, Block.Type.LAMBDA);
230231
}
231232

232233
@JRubyMethod
233234
public RubyUnboundMethod unbind() {
234235
RubyUnboundMethod unboundMethod =
235-
RubyUnboundMethod.newUnboundMethod(implementationModule, methodName, originModule, originName, entry);
236+
RubyUnboundMethod.newUnboundMethod(implementationModule, methodName, originModule, originName, entry);
236237
unboundMethod.infectBy(this);
237-
238+
238239
return unboundMethod;
239240
}
240-
241+
241242
@JRubyMethod(name = {"inspect", "to_s"})
242243
@Override
243244
public IRubyObject inspect() {
@@ -246,7 +247,7 @@ public IRubyObject inspect() {
246247

247248
RubyString str = RubyString.newString(runtime, "#<");
248249
String sharp = "#";
249-
250+
250251
str.catString(getType().getName()).catString(": ");
251252

252253
RubyModule definedClass;
@@ -347,7 +348,19 @@ public IRubyObject curry(ThreadContext context, IRubyObject[] args) {
347348

348349
@JRubyMethod
349350
public IRubyObject super_method(ThreadContext context) {
350-
return super_method(context, receiver, sourceModule.getSuperClass());
351+
RubyModule superClass = null;
352+
if (method instanceof PartialDelegatingMethod) {
353+
PartialDelegatingMethod delegate = (PartialDelegatingMethod)method;
354+
RubyModule definedClass = delegate.getRealMethod().getDefinedClass();
355+
RubyModule module = definedClass.findImplementer(sourceModule.getDelegate());
356+
357+
if (module != null) {
358+
superClass = module.getSuperClass();
359+
}
360+
} else {
361+
superClass = sourceModule.getSuperClass();
362+
}
363+
return super_method(context, receiver, superClass);
351364
}
352365

353366
@JRubyMethod

core/src/main/java/org/jruby/RubyUnboundMethod.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
* Copyright (C) 2004 Charles O Nutter <headius@headius.com>
1515
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
16-
*
16+
*
1717
* Alternatively, the contents of this file may be used under the terms of
1818
* either of the GNU General Public License Version 2 or later (the "GPL"),
1919
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -32,6 +32,7 @@
3232
import org.jruby.anno.JRubyMethod;
3333
import org.jruby.anno.JRubyClass;
3434
import org.jruby.internal.runtime.methods.DynamicMethod;
35+
import org.jruby.internal.runtime.methods.PartialDelegatingMethod;
3536
import org.jruby.internal.runtime.methods.ProcMethod;
3637
import org.jruby.runtime.ClassIndex;
3738
import org.jruby.runtime.ObjectAllocator;
@@ -71,7 +72,7 @@ public static RubyUnboundMethod newUnboundMethod(
7172
}
7273

7374
public static RubyClass defineUnboundMethodClass(Ruby runtime) {
74-
RubyClass newClass =
75+
RubyClass newClass =
7576
runtime.defineClass("UnboundMethod", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
7677

7778
newClass.setClassIndex(ClassIndex.UNBOUNDMETHOD);
@@ -116,9 +117,9 @@ public int hashCode() {
116117
@JRubyMethod
117118
public RubyMethod bind(ThreadContext context, IRubyObject aReceiver) {
118119
RubyClass receiverClass = aReceiver.getMetaClass();
119-
120+
120121
receiverClass.checkValidBindTargetFrom(context, (RubyModule) owner(context), true);
121-
122+
122123
return RubyMethod.newMethod(implementationModule, methodName, receiverClass, originName, entry, aReceiver);
123124
}
124125

@@ -159,7 +160,20 @@ public IRubyObject inspect() {
159160
}
160161

161162
@JRubyMethod
162-
public IRubyObject super_method(ThreadContext context ) {
163-
return super_method(context, null, sourceModule.getSuperClass());
163+
public IRubyObject super_method(ThreadContext context) {
164+
RubyModule superClass = null;
165+
if (method instanceof PartialDelegatingMethod) {
166+
PartialDelegatingMethod delegate = (PartialDelegatingMethod)method;
167+
RubyModule definedClass = delegate.getRealMethod().getDefinedClass();
168+
169+
RubyModule module = definedClass.findImplementer(sourceModule.getDelegate());
170+
if (module != null) {
171+
superClass = module.getSuperClass();
172+
}
173+
} else {
174+
superClass = sourceModule.getSuperClass();
175+
}
176+
177+
return super_method(context, null, superClass);
164178
}
165179
}

spec/ruby/core/method/fixtures/classes.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,25 @@ def mul(n, m)
213213
n * m
214214
end
215215
end
216+
217+
module ChangedVisibility
218+
module A
219+
private
220+
def derp(message)
221+
500
222+
end
223+
end
224+
225+
module B
226+
private
227+
def derp
228+
super('superclass')
229+
end
230+
end
231+
232+
class C
233+
include A
234+
include B
235+
end
236+
end
216237
end

spec/ruby/core/method/super_method_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,13 @@ def overridden; end
4242

4343
method.super_method.should == nil
4444
end
45+
46+
# jruby:7240
47+
context "after changing an inherited methods visiblity" do
48+
it "returns the expected super_method" do
49+
MethodSpecs::ChangedVisibility::C.send :public, :derp
50+
51+
MethodSpecs::ChangedVisibility::C.instance_method(:derp).super_method.owner.should == MethodSpecs::ChangedVisibility::A
52+
end
53+
end
4554
end

spec/ruby/core/unboundmethod/super_method_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require_relative '../../spec_helper'
22
require_relative 'fixtures/classes'
3+
require_relative '../method/fixtures/classes'
34

45
describe "UnboundMethod#super_method" do
56
it "returns the method that would be called by super in the method" do
@@ -25,4 +26,13 @@
2526

2627
method.super_method.should == nil
2728
end
29+
30+
# jruby:7240
31+
context "after changing an inherited methods visiblity" do
32+
it "returns the expected super_method" do
33+
MethodSpecs::ChangedVisibility::C.send :public, :derp
34+
35+
MethodSpecs::ChangedVisibility::C.new.method(:derp).super_method.owner.should == MethodSpecs::ChangedVisibility::A
36+
end
37+
end
2838
end

0 commit comments

Comments
 (0)