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> subtypeableParams = subtypeableMethod.getParameterTypes();
|
||||||
List<JavaTypeDefinition> methodParams = method.getParameterTypes();
|
List<JavaTypeDefinition> methodParams = method.getParameterTypes();
|
||||||
|
|
||||||
|
// If we come from third-phase, both are varargs, otherwhise, treat all as fixed-arity
|
||||||
if (!method.getMethod().isVarArgs() && !subtypeableMethod.getMethod().isVarArgs()) {
|
if (!method.getMethod().isVarArgs() || !subtypeableMethod.getMethod().isVarArgs()) {
|
||||||
for (int index = 0; index < subtypeableParams.size(); ++index) {
|
for (int index = 0; index < subtypeableParams.size(); ++index) {
|
||||||
if (!isSubtypeable(methodParams.get(index), subtypeableParams.get(index))) {
|
if (!isSubtypeable(methodParams.get(index), subtypeableParams.get(index))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (method.getMethod().isVarArgs() && subtypeableMethod.getMethod().isVarArgs()) {
|
} else {
|
||||||
|
final int maxSize = Math.max(subtypeableParams.size(), methodParams.size());
|
||||||
if (methodParams.size() < subtypeableParams.size()) {
|
for (int index = 0; index < maxSize; ++index) {
|
||||||
for (int index = 0; index < subtypeableParams.size(); ++index) {
|
if (!isSubtypeable(method.getArgTypeIncludingVararg(index),
|
||||||
if (!isSubtypeable(method.getArgTypeIncludingVararg(index),
|
subtypeableMethod.getArgTypeIncludingVararg(index))) {
|
||||||
subtypeableMethod.getArgTypeIncludingVararg(index))) {
|
return false;
|
||||||
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;
|
return true;
|
||||||
@ -110,13 +97,12 @@ public final class MethodTypeResolution {
|
|||||||
List<MethodType> methodsToSearch, ASTArgumentList argList) {
|
List<MethodType> methodsToSearch, ASTArgumentList argList) {
|
||||||
// TODO: check if explicit type arguments are applicable to the type parameter bounds
|
// TODO: check if explicit type arguments are applicable to the type parameter bounds
|
||||||
List<MethodType> selectedMethods = new ArrayList<>();
|
List<MethodType> selectedMethods = new ArrayList<>();
|
||||||
|
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
||||||
|
|
||||||
outter:
|
outter:
|
||||||
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
|
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
|
||||||
MethodType methodType = methodsToSearch.get(methodIndex);
|
MethodType methodType = methodsToSearch.get(methodIndex);
|
||||||
|
|
||||||
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
|
||||||
|
|
||||||
// vararg methods are considered fixed arity here, see 3rd phase
|
// vararg methods are considered fixed arity here, see 3rd phase
|
||||||
if (getArity(methodType.getMethod()) == argCount) {
|
if (getArity(methodType.getMethod()) == argCount) {
|
||||||
if (!methodType.isParameterized()) {
|
if (!methodType.isParameterized()) {
|
||||||
@ -260,6 +246,7 @@ public final class MethodTypeResolution {
|
|||||||
public static List<MethodType> selectMethodsSecondPhase(List<MethodType> methodsToSearch, ASTArgumentList argList) {
|
public static List<MethodType> selectMethodsSecondPhase(List<MethodType> methodsToSearch, ASTArgumentList argList) {
|
||||||
// TODO: check if explicit type arguments are applicable to the type parameter bounds
|
// TODO: check if explicit type arguments are applicable to the type parameter bounds
|
||||||
List<MethodType> selectedMethods = new ArrayList<>();
|
List<MethodType> selectedMethods = new ArrayList<>();
|
||||||
|
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
||||||
|
|
||||||
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
|
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
|
||||||
MethodType methodType = methodsToSearch.get(methodIndex);
|
MethodType methodType = methodsToSearch.get(methodIndex);
|
||||||
@ -267,8 +254,6 @@ public final class MethodTypeResolution {
|
|||||||
throw new ResolutionFailedException();
|
throw new ResolutionFailedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
|
|
||||||
|
|
||||||
// vararg methods are considered fixed arity here, see 3rd phase
|
// vararg methods are considered fixed arity here, see 3rd phase
|
||||||
if (getArity(methodType.getMethod()) == argCount) {
|
if (getArity(methodType.getMethod()) == argCount) {
|
||||||
// check method convertability of each argument to the corresponding parameter
|
// 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.SuperExpression;
|
||||||
import net.sourceforge.pmd.typeresolution.testdata.ThisExpression;
|
import net.sourceforge.pmd.typeresolution.testdata.ThisExpression;
|
||||||
import net.sourceforge.pmd.typeresolution.testdata.VarArgsMethodUseCase;
|
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.VarargsZeroArity;
|
||||||
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.Converter;
|
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.Converter;
|
||||||
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
|
import net.sourceforge.pmd.typeresolution.testdata.dummytypes.GenericClass;
|
||||||
@ -1542,6 +1543,35 @@ public class ClassTypeResolverTest {
|
|||||||
// Make sure we got them all
|
// Make sure we got them all
|
||||||
assertEquals("All expressions not tested", index, expressions.size());
|
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
|
@Test
|
||||||
public void testJavaTypeDefinitionEquals() {
|
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