Merge branch 'pr-501'

This commit is contained in:
Juan Martín Sotuyo Dodero
2017-07-13 15:42:52 -03:00
5 changed files with 53 additions and 16 deletions

View File

@ -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();
}
}
}

View File

@ -48,15 +48,37 @@ public final class MethodTypeResolution {
}
public static boolean checkSubtypeability(MethodType method, MethodType subtypeableMethod) {
List<JavaTypeDefinition> subtypeableArgs = subtypeableMethod.getParameterTypes();
List<JavaTypeDefinition> methodTypeArgs = method.getParameterTypes();
List<JavaTypeDefinition> subtypeableParams = subtypeableMethod.getParameterTypes();
List<JavaTypeDefinition> 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<MethodType> methods, ASTArgumentList arguments,
List<JavaTypeDefinition> typeArgs) {
if (methods.size() == 1) {
return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests
}
List<MethodType> 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;

View File

@ -1325,6 +1325,10 @@ public class ClassTypeResolverTest {
assertEquals(int.class, expressions.get(index).getType());
assertEquals(int.class, getChildType(expressions.get(index), 0));
assertEquals(int.class, getChildType(expressions.get(index++), 1));
// String d = mostSpecific(10, 10, 10);
assertEquals(String.class, expressions.get(index).getType());
assertEquals(String.class, getChildType(expressions.get(index), 0));
assertEquals(String.class, getChildType(expressions.get(index++), 1));
// Make sure we got them all
assertEquals("All expressions not tested", index, expressions.size());

View File

@ -15,8 +15,16 @@ public class MethodThirdPhase {
// component type determined properly
int c = vararg(10, "", "", "");
// TODO: add most specific tests among vararg conversion
// most specific vararg method
String d = mostSpecific(10, 10, 10);
}
Exception mostSpecific(Number... b) {
return null;
}
String mostSpecific(Integer... b) {
return null;
}
Exception vararg(int a, Number... b) {

View File

@ -34,7 +34,7 @@ CPD will therefore have less false positives and false negatives.
As part of Google Summer of Code 2017, [Bendegúz Nagy](https://github.com/WinterGrascph)'s work on type resolution for Java continues.
For this release he has extended support for method calls.
Method shadowing and overloading are supported, as is varargs management. However, the selection of the target method upon the presence
Method shadowing and overloading are supported, as are varargs. However, the selection of the target method upon the presence
of generics and type inference is still work in progress. Expect it in forecoming releases.
#### Metrics Framework
@ -83,4 +83,5 @@ Based on those metrics, rules like "GodClass" detection can be implemented more
* [#486](https://github.com/pmd/pmd/pull/486): \[java] Add basic method typeresolution - [Bendegúz Nagy](https://github.com/WinterGrascph)
* [#492](https://github.com/pmd/pmd/pull/492): \[java] Typeresolution for overloaded methods - [Bendegúz Nagy](https://github.com/WinterGrascph)
* [#495](https://github.com/pmd/pmd/pull/495): \[core] Custom rule reinitialization code - [Clément Fournier](https://github.com/oowekyala)
* [#501](https://github.com/pmd/pmd/pull/501): \[java] Add support for most specific vararg method type resolution - [Bendegúz Nagy](https://github.com/WinterGrascph)