Skip to content

Commit bca5d33

Browse files
committed
Merge beanshell2 fork commit: 5fea7c4
Merge pejobo/beanshell2@5fea7c4 issue pejobo/beanshell2#13 - added support for java varargs
1 parent 89d09cd commit bca5d33

File tree

1 file changed

+46
-10
lines changed

1 file changed

+46
-10
lines changed

src/main/java/bsh/Reflect.java

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
having to catch the exceptions. Method lookups are now cached at a high
5050
level so they are less important, however the logic is messy.
5151
*/
52-
class Reflect
53-
{
52+
final class Reflect {
53+
5454
/**
5555
Invoke method on arbitrary object instance.
5656
invocation may be static (through the object instance) or dynamic.
@@ -113,13 +113,31 @@ static Object invokeMethod(
113113

114114
logInvokeMethod( "Invoking method (entry): ", method, args );
115115

116+
boolean isVarArgs = method.isVarArgs();
117+
116118
// Map types to assignable forms, need to keep this fast...
117-
Object [] tmpArgs = new Object [ args.length ];
118119
Class [] types = method.getParameterTypes();
120+
Object [] tmpArgs = new Object [ types.length ];
121+
int fixedArgLen = types.length;
122+
if( isVarArgs ) {
123+
if( fixedArgLen==args.length && types[fixedArgLen-1].isAssignableFrom(args[fixedArgLen-1].getClass()) ) {
124+
isVarArgs = false;
125+
} else {
126+
fixedArgLen--;
127+
}
128+
}
119129
try {
120-
for (int i=0; i<args.length; i++)
130+
for (int i=0; i<fixedArgLen; i++)
121131
tmpArgs[i] = Types.castObject(
122132
args[i]/*rhs*/, types[i]/*lhsType*/, Types.ASSIGNMENT );
133+
if( isVarArgs ) {
134+
Class varType = types[fixedArgLen].getComponentType();
135+
Object varArgs = Array.newInstance( varType, args.length - fixedArgLen );
136+
for( int i=fixedArgLen, j=0; i<args.length; i++, j++ )
137+
Array.set( varArgs,j, Primitive.unwrap( Types.castObject(
138+
args[i]/*rhs*/, varType/*lhsType*/, Types.ASSIGNMENT ) ) );
139+
tmpArgs[fixedArgLen] = varArgs;
140+
}
123141
} catch ( UtilEvalError e ) {
124142
throw new InterpreterError(
125143
"illegal argument type in method invocation: "+e );
@@ -542,7 +560,8 @@ private static void gatherMethodsRecursive(
542560
baseClass.getMethods() : baseClass.getDeclaredMethods();
543561
for( Method m : methods ) {
544562
if ( m.getName().equals( methodName )
545-
&& ( m.getParameterTypes().length == numArgs )
563+
&& ( m.isVarArgs() ? m.getParameterTypes().length-1 <= numArgs
564+
: m.getParameterTypes().length == numArgs )
546565
) {
547566
if( isPublicClass && isPublic(m) ) {
548567
publicMethods.add( m );
@@ -653,12 +672,29 @@ private static Method findMostSpecificMethod(
653672
Class[] idealMatch, List<Method> methods )
654673
{
655674
// copy signatures into array for findMostSpecificMethod()
656-
Class [][] candidateSigs = new Class [ methods.size() ][];
657-
for(int i=0; i<candidateSigs.length; i++)
658-
candidateSigs[i] = methods.get(i).getParameterTypes();
675+
List<Class[]> candidateSigs = new ArrayList<Class[]>();
676+
List<Method> methodList = new ArrayList<Method>();
677+
for( Method method : methods ) {
678+
Class[] parameterTypes = method.getParameterTypes();
679+
methodList.add( method );
680+
candidateSigs.add( parameterTypes );
681+
if( method.isVarArgs() ) {
682+
Class[] candidateSig = new Class[idealMatch.length];
683+
int j = 0;
684+
for( ; j<parameterTypes.length-1; j++ ) {
685+
candidateSig[j] = parameterTypes[j];
686+
}
687+
Class varType = parameterTypes[j].getComponentType();
688+
for( ; j<idealMatch.length; j++ ) {
689+
candidateSig[j] = varType;
690+
}
691+
methodList.add( method );
692+
candidateSigs.add( candidateSig );
693+
}
694+
}
659695

660-
int match = findMostSpecificSignature( idealMatch, candidateSigs );
661-
return match == -1 ? null : methods.get(match);
696+
int match = findMostSpecificSignature( idealMatch, candidateSigs.toArray(new Class[0][]) );
697+
return match == -1 ? null : methodList.get(match);
662698
}
663699

664700
/**

0 commit comments

Comments
 (0)