fix method resolution when they are varargs

This commit is contained in:
Amirouche Boubekki 2012-09-30 22:39:38 +02:00
parent c58de98b8a
commit b8ee0f8ab5
5 changed files with 90 additions and 13 deletions

View File

@ -9,4 +9,5 @@ html:
tests: build_ext tests: build_ext
cd tests && javac org/jnius/HelloWorld.java cd tests && javac org/jnius/HelloWorld.java
cd tests && javac org/jnius/BasicsTest.java cd tests && javac org/jnius/BasicsTest.java
cd tests && javac org/jnius/MultipleMethods.java
cd tests && env PYTHONPATH=..:$(PYTHONPATH) nosetests -v cd tests && env PYTHONPATH=..:$(PYTHONPATH) nosetests -v

View File

@ -735,7 +735,7 @@ cdef class JavaMultipleMethod(object):
else: else:
args_ = args args_ = args
score = calculate_score(sign_args, args_) score = calculate_score(sign_args, args_, jm.is_varargs)
if score <= 0: if score <= 0:
continue continue

View File

@ -85,16 +85,28 @@ cdef bytes lookup_java_object_name(JNIEnv *j_env, jobject j_obj):
return name.replace('.', '/') 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 index
cdef int score = 0 cdef int score = 0
cdef bytes r cdef bytes r
cdef JavaClass jc 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 return -1
elif len(args) == len(sign_args) and not is_varargs:
score += 10 # 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)): for index in range(len(sign_args)):
r = sign_args[index] r = sign_args[index]
@ -193,12 +205,16 @@ cdef int calculate_score(sign_args, args) except *:
return -1 return -1
# calculate the score for our subarray # calculate the score for our subarray
subscore = calculate_score([r[1:]] * len(arg), arg) if len(arg) > 0:
if subscore == -1: # if there are supplemantal arguments we compute the score
return -1 subscore = calculate_score([r[1:]] * len(arg), arg)
if subscore == -1:
# look like the array is matching, accept it. return -1
score += 10 # the supplemental arguments match the varargs arguments
continue 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 return score

View File

@ -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";
}
}

View File

@ -16,3 +16,31 @@ class MultipleSignature(unittest.TestCase):
self.assertEquals(s.getBytes('utf8'), [104, 101, 108, 108, 111]) self.assertEquals(s.getBytes('utf8'), [104, 101, 108, 108, 111])
self.assertEquals(s.indexOf(ord('e')), 1) self.assertEquals(s.indexOf(ord('e')), 1)
self.assertEquals(s.indexOf(ord('e'), 2), -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')