Merge branch 'pr-501'
This commit is contained in:
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user