diff --git a/Makefile b/Makefile index bf4a09a..61a237b 100644 --- a/Makefile +++ b/Makefile @@ -9,4 +9,5 @@ html: tests: build_ext cd tests && javac org/jnius/HelloWorld.java cd tests && javac org/jnius/BasicsTest.java + cd tests && javac org/jnius/MultipleMethods.java cd tests && env PYTHONPATH=..:$(PYTHONPATH) nosetests -v diff --git a/jnius/jnius_export_class.pxi b/jnius/jnius_export_class.pxi index 2c0e276..3bad086 100644 --- a/jnius/jnius_export_class.pxi +++ b/jnius/jnius_export_class.pxi @@ -735,7 +735,7 @@ cdef class JavaMultipleMethod(object): else: args_ = args - score = calculate_score(sign_args, args_) + score = calculate_score(sign_args, args_, jm.is_varargs) if score <= 0: continue diff --git a/jnius/jnius_utils.pxi b/jnius/jnius_utils.pxi index 04fba92..d5d5726 100644 --- a/jnius/jnius_utils.pxi +++ b/jnius/jnius_utils.pxi @@ -85,16 +85,28 @@ cdef bytes lookup_java_object_name(JNIEnv *j_env, jobject j_obj): return name.replace('.', '/') -cdef int calculate_score(sign_args, args) except *: +cdef int calculate_score(sign_args, args, is_varargs=False) except *: cdef int index cdef int score = 0 cdef bytes r cdef JavaClass jc - if len(args) != len(sign_args): + if len(args) != len(sign_args) and not is_varargs: + # if the number of arguments expected is not the same + # as the number of arguments the method gets + # it can not be the method we are looking for except + # if the method has varargs aka. it takes + # an undefined number of arguments return -1 - - score += 10 + elif len(args) == len(sign_args) and not is_varargs: + # if the method has the good number of arguments and + # the method doesn't take varargs increment the score + # so that it takes precedence over a method with the same + # signature and varargs e.g. + # (Integer, Integer) takes precedence over (Integer, Integer, Integer...) + # and + # (Integer, Integer, Integer) takes precedence over (Integer, Integer, Integer...) + score += 10 for index in range(len(sign_args)): r = sign_args[index] @@ -193,12 +205,16 @@ cdef int calculate_score(sign_args, args) except *: return -1 # calculate the score for our subarray - subscore = calculate_score([r[1:]] * len(arg), arg) - if subscore == -1: - return -1 - - # look like the array is matching, accept it. - score += 10 - continue - + if len(arg) > 0: + # if there are supplemantal arguments we compute the score + subscore = calculate_score([r[1:]] * len(arg), arg) + if subscore == -1: + return -1 + # the supplemental arguments match the varargs arguments + score += 10 + continue + # else if there is no supplemental arguments + # it might be the good method but there may be + # a method with a better signature so we don't + # change this method score return score diff --git a/tests/org/jnius/MultipleMethods.java b/tests/org/jnius/MultipleMethods.java new file mode 100644 index 0000000..982a22f --- /dev/null +++ b/tests/org/jnius/MultipleMethods.java @@ -0,0 +1,32 @@ +package org.jnius; + +public class MultipleMethods { + + public static String resolve() { + return "resolved no args"; + } + + public static String resolve(String i) { + return "resolved one arg"; + } + + public static String resolve(String i, String j) { + return "resolved two args"; + } + + public static String resolve(String i, String j, int k) { + return "resolved two string and an integer"; + } + + public static String resolve(String i, String j, int k, int l) { + return "resolved two string and two integers"; + } + + public static String resolve(String i, String j, int... integers) { + return "resolved two args and varargs"; + } + + public static String resolve(int... integers) { + return "resolved varargs"; + } +} diff --git a/tests/test_method_multiple_signatures.py b/tests/test_method_multiple_signatures.py index e740189..b13db57 100644 --- a/tests/test_method_multiple_signatures.py +++ b/tests/test_method_multiple_signatures.py @@ -16,3 +16,31 @@ class MultipleSignature(unittest.TestCase): self.assertEquals(s.getBytes('utf8'), [104, 101, 108, 108, 111]) self.assertEquals(s.indexOf(ord('e')), 1) self.assertEquals(s.indexOf(ord('e'), 2), -1) + + def test_multiple_methods_no_args(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve(), 'resolved no args') + + def test_multiple_methods_one_arg(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve('arg'), 'resolved one arg') + + def test_multiple_methods_two_args(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve('one', 'two'), 'resolved two args') + + def test_multiple_methods_two_string_and_an_integer(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve('one', 'two', 1), 'resolved two string and an integer') + + def test_multiple_methods_two_string_and_two_integers(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve('one', 'two', 1, 2), 'resolved two string and two integers') + + def test_multiple_methods_varargs(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve(1, 2, 3), 'resolved varargs') + + def test_multiple_methods_two_args_and_varargs(self): + MultipleMethods = autoclass('org.jnius.MultipleMethods') + self.assertEqual(MultipleMethods.resolve('one', 'two', 1, 2, 3), 'resolved two args and varargs')