Skip to content

Commit 172f644

Browse files
committed
sketch out solution
1 parent 13da91d commit 172f644

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

src/main/java/org/openrewrite/staticanalysis/LambdaBlockToExpression.java

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import org.openrewrite.java.tree.*;
2424
import org.openrewrite.staticanalysis.java.JavaFileChecker;
2525

26+
import java.util.Collections;
2627
import java.util.List;
2728
import java.util.Optional;
29+
import java.util.stream.Collectors;
2830

2931
public class LambdaBlockToExpression extends Recipe {
3032
@Override
@@ -70,7 +72,7 @@ public J.Lambda visitLambda(J.Lambda lambda, ExecutionContext ctx) {
7072

7173
@Override
7274
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
73-
if (hasLambdaArgument(method) && hasMethodOverloading(method)) {
75+
if (hasLambdaArgument(method) && hasAmbiguousMethodOverloading(method)) {
7476
return method;
7577
}
7678
return super.visitMethodInvocation(method, ctx);
@@ -90,34 +92,53 @@ private static boolean hasLambdaArgument(J.MethodInvocation method) {
9092
return hasLambdaArgument;
9193
}
9294

93-
// Check whether a method has overloading methods in the declaring class
94-
private static boolean hasMethodOverloading(J.MethodInvocation method) {
95+
// Check whether a method has overloading methods in the declaring class
96+
static boolean hasAmbiguousMethodOverloading(J.MethodInvocation method) {
9597
JavaType.Method methodType = method.getMethodType();
98+
99+
if(methodType == null) {
100+
return false;
101+
}
96102
int numberOfArguments = method.getArguments().size();
97-
return methodType != null && hasMethodOverloading(methodType, numberOfArguments);
98-
}
99103

100104
// TODO this is actually more complex in the presence of generics and inheritance
101-
static boolean hasMethodOverloading(JavaType.Method methodType, int numberOfArguments) {
102105
String methodName = methodType.getName();
103-
return Optional.of(methodType)
106+
107+
//all methods of the given type
108+
List<JavaType.Method> methodsOfType = Optional.of(methodType)
104109
.map(JavaType.Method::getDeclaringType)
105110
.filter(JavaType.Class.class::isInstance)
106111
.map(JavaType.Class.class::cast)
107112
.map(JavaType.Class::getMethods)
108-
.map(methods -> {
109-
int overloadingCount = 0;
110-
for (JavaType.Method dm : methods) {
111-
if (dm.getName().equals(methodName) &&
112-
dm.getParameterTypes().size() == numberOfArguments) {
113-
if (++overloadingCount > 1) {
114-
return true;
115-
}
116-
}
117-
}
113+
.orElse(Collections.emptyList());
114+
115+
List<JavaType.Method> potentiallyOverLoadedMethods = methodsOfType.stream()
116+
.filter(dm -> dm.getName().equals(methodName))
117+
.filter(dm -> dm.getParameterTypes().size() == numberOfArguments)
118+
.collect(Collectors.toList());
119+
120+
//if there are less than 2 such methods, then there is no ambiguity
121+
if(potentiallyOverLoadedMethods.size() <= 1) {
122+
return false;
123+
}
124+
125+
//if there is a position where
126+
// - the argument is a lambda
127+
// - the parameters of all potential methods have the same type
128+
// then there is no ambiguity
129+
for (int i = 0; i < numberOfArguments; i++) {
130+
int finalI = i;
131+
if (method.getArguments().get(i) instanceof J.Lambda) {
132+
long distinctElementsCount = potentiallyOverLoadedMethods.stream()
133+
.map(m -> m.getParameterTypes().get(finalI))
134+
.distinct().count();
135+
if (distinctElementsCount == 1) {
118136
return false;
119-
})
120-
.orElse(false);
137+
}
138+
}
139+
}
140+
//otherwise, there must be ambiguity
141+
return true;
121142
}
122143

123144
}

0 commit comments

Comments
 (0)