Skip to content

Commit 357191e

Browse files
Add explicit type arguments to generic methods in UseVarForGenericMethodInvocations (#869)
* Added tests for issue #868 * Fix tests * Minimize implementation --------- Co-authored-by: Tim te Beek <[email protected]>
1 parent 45e12e2 commit 357191e

File tree

2 files changed

+104
-4
lines changed

2 files changed

+104
-4
lines changed

src/main/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocations.java

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@
2323
import org.openrewrite.internal.ListUtils;
2424
import org.openrewrite.java.JavaIsoVisitor;
2525
import org.openrewrite.java.search.UsesJavaVersion;
26-
import org.openrewrite.java.tree.Expression;
27-
import org.openrewrite.java.tree.J;
28-
import org.openrewrite.java.tree.JavaType;
29-
import org.openrewrite.java.tree.TypeTree;
26+
import org.openrewrite.java.tree.*;
27+
import org.openrewrite.marker.Markers;
3028

29+
import java.util.ArrayList;
3130
import java.util.List;
3231

3332
import static java.util.Objects.requireNonNull;
@@ -97,6 +96,7 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations v
9796
/**
9897
* Makes nested generic types explicit by replacing diamond operators in constructor calls
9998
* with explicit type parameters based on the variable declaration type.
99+
* Also adds explicit type parameters to the method invocation itself when needed.
100100
*/
101101
private J.MethodInvocation makeNestedGenericsExplicit(J.MethodInvocation mi, J.VariableDeclarations vd) {
102102
// Extract type parameters from the variable declaration
@@ -109,6 +109,16 @@ private J.MethodInvocation makeNestedGenericsExplicit(J.MethodInvocation mi, J.V
109109
return mi;
110110
}
111111

112+
// Add explicit type parameters when the method is generic and the return type's type parameter matches a type parameter from the declaring class
113+
if (mi.getTypeParameters() == null && mi.getMethodType() != null && containsGenericTypeVariable(mi.getMethodType().getReturnType())) {
114+
// Create JRightPadded list from leftTypeParams
115+
List<JRightPadded<Expression>> typeParamsList = new ArrayList<>();
116+
for (Expression typeParam : leftTypeParams) {
117+
typeParamsList.add(JRightPadded.build(typeParam));
118+
}
119+
mi = mi.withTypeParameters(JContainer.build(Space.EMPTY, typeParamsList, Markers.EMPTY));
120+
}
121+
112122
// Visit arguments and replace diamond operators with explicit type parameters
113123
return mi.withArguments(ListUtils.map(mi.getArguments(), arg -> {
114124
if (arg instanceof J.NewClass) {
@@ -124,6 +134,22 @@ private J.MethodInvocation makeNestedGenericsExplicit(J.MethodInvocation mi, J.V
124134
}));
125135
}
126136

137+
private boolean containsGenericTypeVariable(JavaType type) {
138+
if (type instanceof JavaType.GenericTypeVariable) {
139+
return true;
140+
}
141+
142+
if (type instanceof JavaType.Parameterized) {
143+
for (JavaType typeParam : ((JavaType.Parameterized) type).getTypeParameters()) {
144+
if (containsGenericTypeVariable(typeParam)) {
145+
return true;
146+
}
147+
}
148+
}
149+
150+
return false;
151+
}
152+
127153
private static boolean hasTypeParams(@Nullable TypeTree clazz) {
128154
if (clazz instanceof J.ParameterizedType) {
129155
List<Expression> typeParameters = ((J.ParameterizedType) clazz).getTypeParameters();

src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocationsTest.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,5 +295,79 @@ void dostuff() {
295295
)
296296
);
297297
}
298+
299+
@Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/868")
300+
@Test
301+
void applyVarAndAddExplicitTypeArgumentForNestedGenericFactoryMethod() {
302+
//language=java
303+
rewriteRun(
304+
version(
305+
java(
306+
"""
307+
class A<T> {
308+
void getX(final Root<T> root) {
309+
Path<T> x = root.get("x");
310+
}
311+
}
312+
interface Root<X>{
313+
<Y> Path<Y> get(String var1);
314+
}
315+
interface Path<X> { }
316+
""",
317+
"""
318+
class A<T> {
319+
void getX(final Root<T> root) {
320+
var x = root.<T>get("x");
321+
}
322+
}
323+
interface Root<X>{
324+
<Y> Path<Y> get(String var1);
325+
}
326+
interface Path<X> { }
327+
"""
328+
),
329+
10
330+
)
331+
);
332+
}
333+
334+
@Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/868")
335+
@Test
336+
void genericsCollectorsRegression() {
337+
//language=java
338+
rewriteRun(
339+
version(
340+
java(
341+
"""
342+
import java.time.LocalDate;
343+
import java.util.ArrayList;
344+
import java.util.Set;
345+
import java.util.stream.Collectors;
346+
347+
public class A {
348+
void getX() {
349+
Set<String> strDates = new ArrayList<LocalDate>().stream()
350+
.map(date -> date.toString()).collect(Collectors.toSet());
351+
}
352+
}
353+
""",
354+
"""
355+
import java.time.LocalDate;
356+
import java.util.ArrayList;
357+
import java.util.Set;
358+
import java.util.stream.Collectors;
359+
360+
public class A {
361+
void getX() {
362+
var strDates = new ArrayList<LocalDate>().stream()
363+
.map(date -> date.toString()).collect(Collectors.toSet());
364+
}
365+
}
366+
"""
367+
),
368+
10
369+
)
370+
);
371+
}
298372
}
299373
}

0 commit comments

Comments
 (0)