diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java index ff5bd703fd..8423b2cf5e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java @@ -53,4 +53,12 @@ public class MethodType { public boolean isAbstract() { return Modifier.isAbstract(method.getModifiers()); } + + public JavaTypeDefinition getArgTypeIncludingVararg(int index) { + if (index < argTypes.size() - 1) { + return argTypes.get(index); + } else { + return getVarargComponentType(); + } + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java index 1168422692..b8fd7fd2c9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java @@ -48,15 +48,37 @@ public final class MethodTypeResolution { } public static boolean checkSubtypeability(MethodType method, MethodType subtypeableMethod) { - List subtypeableArgs = subtypeableMethod.getParameterTypes(); - List methodTypeArgs = method.getParameterTypes(); + List subtypeableParams = subtypeableMethod.getParameterTypes(); + List methodParams = method.getParameterTypes(); - // TODO: add support for not matching arity methods - for (int index = 0; index < subtypeableArgs.size(); ++index) { - if (!isSubtypeable(methodTypeArgs.get(index), subtypeableArgs.get(index))) { - return false; + if (!method.getMethod().isVarArgs() && !subtypeableMethod.getMethod().isVarArgs()) { + for (int index = 0; index < subtypeableParams.size(); ++index) { + if (!isSubtypeable(methodParams.get(index), subtypeableParams.get(index))) { + return false; + } } + } else if (method.getMethod().isVarArgs() && subtypeableMethod.getMethod().isVarArgs()) { + + if (methodParams.size() < subtypeableParams.size()) { + for (int index = 0; index < subtypeableParams.size(); ++index) { + if (!isSubtypeable(method.getArgTypeIncludingVararg(index), + subtypeableMethod.getArgTypeIncludingVararg(index))) { + return false; + } + } + } else { + for (int index = 0; index < methodParams.size(); ++index) { + if (!isSubtypeable(method.getArgTypeIncludingVararg(index), + subtypeableMethod.getArgTypeIncludingVararg(index))) { + return false; + } + } + } + + } else { + throw new IllegalStateException("These methods can only be vararg at the same time:\n" + + method.toString() + "\n" + subtypeableMethod.toString()); } return true; @@ -202,10 +224,7 @@ public final class MethodTypeResolution { */ public static JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, List typeArgs) { - if (methods.size() == 1) { - return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests - } - + List selectedMethods = selectMethodsFirstPhase(methods, arguments, typeArgs); if (!selectedMethods.isEmpty()) { return selectMostSpecificMethod(selectedMethods).getReturnType(); @@ -218,10 +237,7 @@ public final class MethodTypeResolution { selectedMethods = selectMethodsThirdPhase(methods, arguments, typeArgs); if (!selectedMethods.isEmpty()) { - if (selectedMethods.size() == 1) { - return selectedMethods.get(0).getReturnType(); - // TODO: add selecting most specific vararg method - } + return selectMostSpecificMethod(selectedMethods).getReturnType(); } return null;