Fix specificity test for varargs vs fixed
- We used to fail upon mixing varargs with fixed arity instead of treating the vararg as a fixed arity as per the spec
This commit is contained in:
@ -69,34 +69,21 @@ public final class MethodTypeResolution {
|
||||
List<JavaTypeDefinition> subtypeableParams = subtypeableMethod.getParameterTypes();
|
||||
List<JavaTypeDefinition> methodParams = method.getParameterTypes();
|
||||
|
||||
|
||||
if (!method.getMethod().isVarArgs() && !subtypeableMethod.getMethod().isVarArgs()) {
|
||||
// If we come from third-phase, both are varargs, otherwhise, treat all as fixed-arity
|
||||
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 {
|
||||
final int maxSize = Math.max(subtypeableParams.size(), methodParams.size());
|
||||
for (int index = 0; index < maxSize; ++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;
|
||||
@ -110,13 +97,12 @@ public final class MethodTypeResolution {
|
||||
List<MethodType> methodsToSearch, ASTArgumentList argList) {
|
||||
// TODO: check if explicit type arguments are applicable to the type parameter bounds
|
||||
List<MethodType> selectedMethods = new ArrayList<>();
|
||||
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
||||
|
||||
outter:
|
||||
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
|
||||
MethodType methodType = methodsToSearch.get(methodIndex);
|
||||
|
||||
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
||||
|
||||
// vararg methods are considered fixed arity here, see 3rd phase
|
||||
if (getArity(methodType.getMethod()) == argCount) {
|
||||
if (!methodType.isParameterized()) {
|
||||
@ -260,6 +246,7 @@ public final class MethodTypeResolution {
|
||||
public static List<MethodType> selectMethodsSecondPhase(List<MethodType> methodsToSearch, ASTArgumentList argList) {
|
||||
// TODO: check if explicit type arguments are applicable to the type parameter bounds
|
||||
List<MethodType> selectedMethods = new ArrayList<>();
|
||||
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
||||
|
||||
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
|
||||
MethodType methodType = methodsToSearch.get(methodIndex);
|
||||
@ -267,8 +254,6 @@ public final class MethodTypeResolution {
|
||||
throw new ResolutionFailedException();
|
||||
}
|
||||
|
||||
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
||||
|
||||
// vararg methods are considered fixed arity here, see 3rd phase
|
||||
if (getArity(methodType.getMethod()) == argCount) {
|
||||
// check method convertability of each argument to the corresponding parameter
|
||||
|
@ -105,6 +105,7 @@ import net.sourceforge.pmd.typeresolution.testdata.SubTypeUsage;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.SuperExpression;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.ThisExpression;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.VarArgsMethodUseCase;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.VarargsAsFixedArity;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.VarargsZeroArity;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.Converter;
|
||||
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
|
||||
@ -1542,6 +1543,35 @@ public class ClassTypeResolverTest {
|
||||
// Make sure we got them all
|
||||
assertEquals("All expressions not tested", index, expressions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodTypeInferenceVarargsAsFixedArity() throws JaxenException {
|
||||
ASTCompilationUnit acu = parseAndTypeResolveForClass15(VarargsAsFixedArity.class);
|
||||
|
||||
List<AbstractJavaTypeNode> expressions = convertList(
|
||||
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"),
|
||||
AbstractJavaTypeNode.class);
|
||||
|
||||
int index = 0;
|
||||
|
||||
// int var = aMethod("");
|
||||
assertEquals(int.class, expressions.get(index++).getType());
|
||||
|
||||
// String var2 = aMethod();
|
||||
assertEquals(String.class, expressions.get(index++).getType());
|
||||
|
||||
// String var3 = aMethod("", "");
|
||||
assertEquals(String.class, expressions.get(index++).getType());
|
||||
|
||||
// String var4 = aMethod(new Object[] { null });
|
||||
assertEquals(String.class, expressions.get(index++).getType());
|
||||
|
||||
// null literal has null type
|
||||
assertNull(expressions.get(index++).getType());
|
||||
|
||||
// Make sure we got them all
|
||||
assertEquals("All expressions not tested", index, expressions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJavaTypeDefinitionEquals() {
|
||||
|
23
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/VarargsAsFixedArity.java
vendored
Normal file
23
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/VarargsAsFixedArity.java
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.typeresolution.testdata;
|
||||
|
||||
public class VarargsAsFixedArity {
|
||||
|
||||
public void tester() {
|
||||
int var = aMethod("");
|
||||
String var2 = aMethod();
|
||||
String var3 = aMethod("", "");
|
||||
String var4 = aMethod(new Object[] { null });
|
||||
}
|
||||
|
||||
public int aMethod(Object s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String aMethod(Object... s) {
|
||||
return null;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user