diff --git a/core/src/main/java/org/jruby/java/dispatch/CallableSelector.java b/core/src/main/java/org/jruby/java/dispatch/CallableSelector.java index 4a69de79dea..d34990df07f 100644 --- a/core/src/main/java/org/jruby/java/dispatch/CallableSelector.java +++ b/core/src/main/java/org/jruby/java/dispatch/CallableSelector.java @@ -2,6 +2,7 @@ import java.lang.reflect.Member; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import org.jruby.Ruby; @@ -169,12 +170,18 @@ private static ParameterTypes findCallable(ParameterTypes[] callables, CallableA private static List findCallableCandidates(final ParameterTypes[] callables, final IRubyObject[] args) { + // in case of an exact match prefer to return it early : + for ( int c = 0; c < callables.length; c++ ) { + final ParameterTypes callable = callables[c]; + if ( exactMatch(callable, args ) ) return Collections.singletonList(callable); + } + final ArrayList retained = new ArrayList(callables.length); ParameterTypes[] incoming = callables.clone(); for ( int i = 0; i < args.length; i++ ) { retained.clear(); - for ( final Matcher matcher : MATCH_SEQUENCE ) { + for ( final Matcher matcher : NON_EXACT_MATCH_SEQUENCE ) { for ( int c = 0; c < incoming.length; c++ ) { ParameterTypes callable = incoming[c]; if ( callable == null ) continue; // removed (matched) @@ -277,7 +284,8 @@ public boolean match(Class type, IRubyObject arg) { } }; - private static final Matcher[] MATCH_SEQUENCE = new Matcher[] { EXACT, PRIMITIVABLE, ASSIGNABLE, DUCKABLE }; + //private static final Matcher[] MATCH_SEQUENCE = new Matcher[] { EXACT, PRIMITIVABLE, ASSIGNABLE, DUCKABLE }; + private static final Matcher[] NON_EXACT_MATCH_SEQUENCE = new Matcher[] { PRIMITIVABLE, ASSIGNABLE, DUCKABLE }; private static boolean exactMatch(ParameterTypes paramTypes, IRubyObject... args) { Class[] types = paramTypes.getParameterTypes(); @@ -347,7 +355,7 @@ private static boolean assignableAndPrimitivableWithVarargs(ParameterTypes param return true; } - private static boolean assignable(Class type, IRubyObject arg) { + private static boolean assignable(Class type, final IRubyObject arg) { return JavaClass.assignable(type, getJavaClass(arg)); } @@ -359,7 +367,7 @@ private static boolean assignable(Class type, IRubyObject arg) { * @param arg The argument to convert * @return Whether the argument can be directly converted to the target primitive type */ - private static boolean primitivable(Class type, IRubyObject arg) { + private static boolean primitivable(final Class type, final IRubyObject arg) { final Class argClass = getJavaClass(arg); if (type.isPrimitive()) { // TODO: This is where we would want to do precision checks to see diff --git a/test/test_higher_javasupport.rb b/test/test_higher_javasupport.rb index 1532aef2401..29d4c439e4c 100644 --- a/test/test_higher_javasupport.rb +++ b/test/test_higher_javasupport.rb @@ -1040,4 +1040,25 @@ def test_concurrent_proxy_class_initialization_dead_lock end end + def test_no_ambiguous_java_constructor_warning_for_exact_match + output = with_stderr_captured do # exact match should not warn : + java.awt.Color.new(1.to_java(:int), 1.to_java(:int), 1.to_java(:int)) + end + # warning: ambiguous Java methods found, using java.awt.Color(int,int,int) + assert ! output.index('ambiguous'), output + end + + private + + def with_stderr_captured + stderr = $stderr; require 'stringio' + begin + $stderr = StringIO.new + yield + $stderr.string + ensure + $stderr = stderr + end + end + end