Skip to content

Commit

Permalink
Add additional logic to cast lambda for wildcard argument (#1674)
Browse files Browse the repository at this point in the history
- modify LambdaExressionsFixCore to add a cast if the lambda will
  end up as an argument that is supposed to be a wildcard type and
  the bound is not compatible with the initial class instance
  creation type argument
- add new tests to CleanUpTest1d8
- fixes #1535
  • Loading branch information
jjohnstn authored Sep 26, 2024
1 parent 6be9114 commit 486989e
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ public boolean visit(final ThisExpression node) {
}

ITypeBinding targetTypeBinding= ASTNodes.getTargetType(classInstanceCreation);
if (ASTNodes.isTargetAmbiguous(classInstanceCreation, ASTNodes.isExplicitlyTypedLambda(cicReplacement)) || targetTypeBinding.getFunctionalInterfaceMethod() == null) {
if (needCastForWildcardArgument(classInstanceCreation) || ASTNodes.isTargetAmbiguous(classInstanceCreation, ASTNodes.isExplicitlyTypedLambda(cicReplacement)) || targetTypeBinding.getFunctionalInterfaceMethod() == null) {
CastExpression cast= ast.newCastExpression();
cast.setExpression(cicReplacement);
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
Expand All @@ -962,6 +962,49 @@ public boolean visit(final ThisExpression node) {
}
}

private boolean needCastForWildcardArgument(ClassInstanceCreation classInstanceCreation) {
if (classInstanceCreation.getLocationInParent() == MethodInvocation.ARGUMENTS_PROPERTY) {
MethodInvocation parent= (MethodInvocation)classInstanceCreation.getParent();
List<Expression> arguments= parent.arguments();
IMethodBinding methodBinding= parent.resolveMethodBinding();
if (methodBinding != null) {
ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
int index= -1;
for (int i= 0; i < arguments.size(); ++i) {
if (arguments.get(i) == classInstanceCreation) {
index= i;
break;
}
}
if (index >= 0) {
ITypeBinding parameterTypeBinding= null;
if (index < parameterTypes.length) {
parameterTypeBinding= parameterTypes[index];
} else {
parameterTypeBinding= parameterTypes[parameterTypes.length - 1].getComponentType();
}
ITypeBinding classInstanceParameterizedType= classInstanceCreation.getType().resolveBinding();
ITypeBinding[] classInstanceTypeArguments= classInstanceParameterizedType.getTypeArguments();
ITypeBinding[] typeArguments= parameterTypeBinding.getTypeArguments();
for (int i= 0; i < typeArguments.length; ++i) {
ITypeBinding typeArgument= typeArguments[i];
if (typeArgument.isWildcardType()) {
ITypeBinding bound= typeArgument.getBound();
if (bound == null) {
bound= typeArgument.getErasure();
}
ITypeBinding classInstanceTypeArgument= classInstanceTypeArguments[i];
if (!bound.isSubTypeCompatible(classInstanceTypeArgument)) {
return true;
}
}
}
}
}
}
return false;
}

private Expression castMethodRefIfNeeded(final CompilationUnitRewrite cuRewrite, AST ast, Expression methodRef, Expression visited) {
boolean needCast= false;
Expression replacementNode= methodRef;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6925,4 +6925,132 @@ public String get() {
assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 }, null);
}

@Test
public void testConvertToLambdaIssue1535_1() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
String original= """
package test1;
import java.util.Iterator;
import java.util.List;
public class E {
private void func(Iterable<?> a, Iterable<?> b) {}
private void assertIteratorProducesExpectedList(
List<String> expectedList,
Iterator<String> rankedListIterator) {
func(expectedList, new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return rankedListIterator;
}
});
}
}
""";
ICompilationUnit cu1= pack1.createCompilationUnit("E.java", original, false, null);

enable(CleanUpConstants.CONVERT_FUNCTIONAL_INTERFACES);
enable(CleanUpConstants.USE_LAMBDA);

String expected= """
package test1;
import java.util.Iterator;
import java.util.List;
public class E {
private void func(Iterable<?> a, Iterable<?> b) {}
private void assertIteratorProducesExpectedList(
List<String> expectedList,
Iterator<String> rankedListIterator) {
func(expectedList, (Iterable<String>) () -> rankedListIterator);
}
}
""";

assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected }, null);

}

@Test
public void testConvertToLambdaIssue1535_2() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
String original= """
package test1;
import java.util.Iterator;
import java.util.List;
public class E {
private void func(Iterable<?> a, Iterable<?> b) {}
private Iterator<String> myfunc() {
class K implements Iterator<String> {
@Override
public boolean hasNext() {
return false;
}
@Override
public String next() {
return null;
}
}
return new K();
}
private void assertIteratorProducesExpectedList(
List<String> expectedList,
Iterator<String> rankedListIterator) {
func(expectedList, new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return myfunc();
}
});
}
}
""";
ICompilationUnit cu1= pack1.createCompilationUnit("E.java", original, false, null);

enable(CleanUpConstants.CONVERT_FUNCTIONAL_INTERFACES);
enable(CleanUpConstants.USE_LAMBDA);
enable(CleanUpConstants.ALSO_SIMPLIFY_LAMBDA);

String expected= """
package test1;
import java.util.Iterator;
import java.util.List;
public class E {
private void func(Iterable<?> a, Iterable<?> b) {}
private Iterator<String> myfunc() {
class K implements Iterator<String> {
@Override
public boolean hasNext() {
return false;
}
@Override
public String next() {
return null;
}
}
return new K();
}
private void assertIteratorProducesExpectedList(
List<String> expectedList,
Iterator<String> rankedListIterator) {
func(expectedList, (Iterable<String>) this::myfunc);
}
}
""";

assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected }, null);

}
}

0 comments on commit 486989e

Please sign in to comment.