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

Commit 9ab1620

Browse files
authored
Merge pull request #345 from grddev/jruby-java-method-signature-verifier
Workaround JRuby incompatibilities
2 parents ef0d1e7 + 02a2193 commit 9ab1620

File tree

2 files changed

+63
-23
lines changed

2 files changed

+63
-23
lines changed

lib/rspec/support/method_signature_verifier.rb

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ def valid_non_kw_args?(positional_arg_count, optional_max_arg_count=positional_a
3333
optional_max_arg_count <= max_non_kw_args
3434
end
3535

36+
def classify_arity(arity=@method.arity)
37+
if arity < 0
38+
# `~` inverts the one's complement and gives us the
39+
# number of required args
40+
@min_non_kw_args = ~arity
41+
@max_non_kw_args = INFINITY
42+
else
43+
@min_non_kw_args = arity
44+
@max_non_kw_args = arity
45+
end
46+
end
47+
3648
if RubyFeatures.optional_and_splat_args_supported?
3749
def description
3850
@description ||= begin
@@ -137,36 +149,46 @@ def unlimited_args?
137149
false
138150
end
139151

140-
def classify_parameters
141-
arity = @method.arity
142-
if arity < 0
143-
# `~` inverts the one's complement and gives us the
144-
# number of required args
145-
@min_non_kw_args = ~arity
146-
@max_non_kw_args = INFINITY
147-
else
148-
@min_non_kw_args = arity
149-
@max_non_kw_args = arity
150-
end
151-
end
152+
alias_method :classify_parameters, :classify_arity
152153
end
153154

154155
INFINITY = 1 / 0.0
155156
end
156157

157-
# Some versions of JRuby have a nasty bug we have to work around :(.
158-
# https://github.com/jruby/jruby/issues/2816
159-
if RSpec::Support::Ruby.jruby? &&
160-
RubyFeatures.optional_and_splat_args_supported? &&
161-
Class.new { attr_writer :foo }.instance_method(:foo=).parameters == []
158+
if RSpec::Support::Ruby.jruby?
159+
# JRuby has only partial support for UnboundMethod#parameters, so we fall back on using #arity
160+
# https://github.com/jruby/jruby/issues/2816 and https://github.com/jruby/jruby/issues/2817
161+
if RubyFeatures.optional_and_splat_args_supported? &&
162+
Java::JavaLang::String.instance_method(:char_at).parameters == []
162163

163-
class MethodSignature < remove_const(:MethodSignature)
164-
private
164+
class MethodSignature < remove_const(:MethodSignature)
165+
private
165166

166-
def classify_parameters
167-
super
168-
return unless @method.parameters == [] && @method.arity == 1
169-
@max_non_kw_args = @min_non_kw_args = 1
167+
def classify_parameters
168+
super
169+
if (arity = @method.arity) != 0 && @method.parameters.empty?
170+
classify_arity(arity)
171+
end
172+
end
173+
end
174+
end
175+
176+
# JRuby used to always report -1 arity for Java proxy methods
177+
if Java::JavaLang::String.instance_method(:char_at).arity == -1
178+
class MethodSignature < remove_const(:MethodSignature)
179+
private
180+
181+
def classify_parameters
182+
super
183+
return unless @method.arity == -1 && @method.owner.respond_to?(:java_class)
184+
java_instance_methods = @method.owner.java_class.java_instance_methods
185+
compatible_overloads = java_instance_methods.select do |java_method|
186+
@method == @method.owner.instance_method(java_method.name)
187+
end
188+
if compatible_overloads.size == 1
189+
classify_arity(compatible_overloads.first.arity)
190+
end
191+
end
170192
end
171193
end
172194
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)