Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit a232b2b

Browse files
committed
Workaround JRuby incompatibility
JRuby apparently only supports #arity (and not #parameters) for Java proxy methods (see jruby/jruby#2817), but verifying doubles in RSpec use #parameters to infer required method parameters, and thus doesn't work for Java classes. This extends the previously existing JRuby workaround that returns an empty list from #parameters so that it fallbacks to the legacy method of using #arity. In addition, it turns out that the #arity method is broken for Java proxy methods in JRuby 1.7.x. While JRuby 1.7 has been sunset, the test suite still uses it, and thus this introduces another workaround to account for that. This looks up the corresponding JavaMethod overloads, and if there is only one, retrieves the arity from that one instead. In the presence of multiple overloads, -1 is returned. While this obviously doesn't cover all cases, it does cover the cases the previous workaround covered, and also allows using verifying doubles for many Java classes in JRuby.
1 parent c41e875 commit a232b2b

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

lib/rspec/support/method_signature_verifier.rb

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,57 @@ def classify_parameters
154154
INFINITY = 1 / 0.0
155155
end
156156

157-
# Some versions of JRuby have a nasty bug we have to work around :(.
158-
# https://github.com/jruby/jruby/issues/2816
157+
# JRuby has only partial support for UnboundMethod#parameters, so we fall back on using #arity
158+
# https://github.com/jruby/jruby/issues/2816 and https://github.com/jruby/jruby/issues/2817
159159
if RSpec::Support::Ruby.jruby? &&
160160
RubyFeatures.optional_and_splat_args_supported? &&
161-
Class.new { attr_writer :foo }.instance_method(:foo=).parameters == []
161+
Java::JavaLang::String.instance_method(:char_at).parameters == []
162+
class MethodSignature < remove_const(:MethodSignature)
163+
private
164+
165+
def classify_parameters
166+
super
167+
if (arity = @method.arity) != 0 && @method.parameters.empty?
168+
if arity < 0
169+
@min_non_kw_args = ~arity
170+
@max_non_kw_args = INFINITY
171+
else
172+
@min_non_kw_args = arity
173+
@max_non_kw_args = arity
174+
end
175+
end
176+
end
177+
end
178+
end
162179

180+
if RSpec::Support::Ruby.jruby? &&
181+
Java::JavaLang::String.instance_method(:char_at).arity == -1
163182
class MethodSignature < remove_const(:MethodSignature)
164183
private
165184

166185
def classify_parameters
167186
super
168-
return unless @method.parameters == [] && @method.arity == 1
169-
@max_non_kw_args = @min_non_kw_args = 1
187+
if @method.arity == -1 && (arity = java_method_arity)
188+
if arity < 0
189+
@min_non_kw_args = ~arity
190+
@max_non_kw_args = INFINITY
191+
else
192+
@min_non_kw_args = arity
193+
@max_non_kw_args = arity
194+
end
195+
end
196+
end
197+
198+
def java_method_arity
199+
if @method.owner.respond_to?(:java_class)
200+
java_instance_methods = @method.owner.java_class.java_instance_methods
201+
overloads = java_instance_methods.select do |java_method|
202+
@method == @method.owner.instance_method(java_method.name)
203+
end
204+
if overloads.size == 1
205+
overloads.first.arity
206+
end
207+
end
170208
end
171209
end
172210
end

spec/rspec/support/method_signature_verifier_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,24 @@ def arity_block(_, &block); end
719719
expect(valid_non_kw_args?(2)).to eq false
720720
end
721721
end
722+
723+
if Ruby.jruby?
724+
describe 'a single-argument Java method' do
725+
let(:test_method) { Java::JavaLang::String.instance_method(:char_at) }
726+
727+
it 'validates against a single argument' do
728+
expect(valid_non_kw_args?(1)).to eq true
729+
end
730+
731+
it 'fails validation against 0 arguments' do
732+
expect(valid_non_kw_args?(0)).to eq false
733+
end
734+
735+
it 'fails validation against 2 arguments' do
736+
expect(valid_non_kw_args?(2)).to eq false
737+
end
738+
end
739+
end
722740
end
723741

724742
let(:fake_matcher) { Object.new }

0 commit comments

Comments
 (0)