anonymous -> lambda: do not reject cases when return type can't be correctly inferred without target type constraints (IDEA-137390)

This commit is contained in:
Anna Kozlova
2015-03-24 21:00:48 +01:00
parent 4b3cebcf53
commit 6ae3daeef1
3 changed files with 61 additions and 10 deletions

View File

@@ -36,10 +36,7 @@ import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -459,14 +456,15 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
private final PsiMethod myMethod;
private final PsiAnonymousClass myAnonymClass;
private final boolean myEqualInference;
private final PsiType myInferredType;
public ForbiddenRefsChecker(PsiMethod method,
PsiAnonymousClass aClass) {
myMethod = method;
myAnonymClass = aClass;
final PsiType inferredType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(getInferredType(aClass));
myEqualInference = !aClass.getBaseClassType().equals(inferredType);
final PsiClassType baseClassType = aClass.getBaseClassType();
myInferredType = !baseClassType.equals(inferredType) ? inferredType : null;
}
@Override
@@ -557,14 +555,24 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
}
}
if (myEqualInference) {
if (myInferredType != null) {
final PsiElement resolved = expression.resolve();
if (resolved instanceof PsiParameter && ((PsiParameter)resolved).getDeclarationScope() == myMethod) {
if (!(myInferredType instanceof PsiClassType)) {
myBodyContainsForbiddenRefs = true;
return;
}
final int parameterIndex = myMethod.getParameterList().getParameterIndex((PsiParameter)resolved);
for (PsiMethod superMethod : myMethod.findDeepestSuperMethods()) {
if (PsiUtil.resolveClassInType(superMethod.getParameterList().getParameters()[parameterIndex].getType()) instanceof PsiTypeParameter) {
myBodyContainsForbiddenRefs = true;
return;
final PsiType paramType = superMethod.getParameterList().getParameters()[parameterIndex].getType();
final PsiClass superClass = superMethod.getContainingClass();
if (superClass != null) {
final PsiSubstitutor inferredSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, (PsiClassType)myInferredType);
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, myAnonymClass.getBaseClassType());
if (!Comparing.equal(inferredSubstitutor.substitute(paramType), substitutor.substitute(paramType))) {
myBodyContainsForbiddenRefs = true;
return;
}
}
}
}

View File

@@ -0,0 +1,19 @@
// "Replace with lambda" "true"
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Test {
private static final Map<String, Mood> WORD_TO_MOOD = null;
public static void analyseMood(String[] wordsInMessage) {
Stream.of(wordsInMessage)
.map(s -> WORD_TO_MOOD.get(s))
.filter(mood -> mood != null)
.collect(Collectors.toSet());
}
enum Mood {}
}

View File

@@ -0,0 +1,24 @@
// "Replace with lambda" "true"
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Test {
private static final Map<String, Mood> WORD_TO_MOOD = null;
public static void analyseMood(String[] wordsInMessage) {
Stream.of(wordsInMessage)
.map(new Func<caret>tion<String, Mood>() {
@Override
public Mood apply(String s) {
return WORD_TO_MOOD.get(s);
}
})
.filter(mood -> mood != null)
.collect(Collectors.toSet());
}
enum Mood {}
}