speedup lambda search: don't check assignability in light applicability check

because we already search for all possible SAM inheritors of the main searched class, so we can check exact name match
This commit is contained in:
peter
2018-10-22 20:48:52 +02:00
parent dce504b013
commit 2042b1cc28
@@ -24,6 +24,7 @@ import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.JBIterable;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NotNull;
@@ -31,6 +32,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -122,28 +124,38 @@ public class FunExprOccurrence {
return member instanceof PsiMethod && hasCompatibleParameter((PsiMethod)member, argIndex, samClasses);
}
if (member instanceof PsiClass) {
return ContainerUtil.exists(samClasses, c -> InheritanceUtil.isInheritorOrSelf((PsiClass)member, c, true));
return samClasses.contains(member);
}
return member instanceof PsiField &&
ContainerUtil.exists(samClasses, c -> canPassFunctionalExpression(c, ((PsiField)member).getType()));
ContainerUtil.exists(samClasses, c -> canPassFunctionalExpression(c, ((PsiField)member).getType(), member));
}
public static boolean hasCompatibleParameter(PsiMethod method, int argIndex, List<? extends PsiClass> samClasses) {
PsiParameter[] parameters = method.getParameterList().getParameters();
int paramIndex = method.isVarArgs() ? Math.min(argIndex, parameters.length - 1) : argIndex;
return paramIndex < parameters.length &&
ContainerUtil.exists(samClasses, c -> canPassFunctionalExpression(c, parameters[paramIndex].getType()));
ContainerUtil.exists(samClasses, c -> canPassFunctionalExpression(c, parameters[paramIndex].getType(), method));
}
private static boolean canPassFunctionalExpression(PsiClass sam, PsiType paramType) {
private static boolean canPassFunctionalExpression(PsiClass sam, PsiType paramType, PsiElement place) {
if (paramType instanceof PsiEllipsisType) {
paramType = ((PsiEllipsisType)paramType).getComponentType();
}
PsiClass functionalCandidate = PsiUtil.resolveClassInClassTypeOnly(paramType);
if (functionalCandidate instanceof PsiTypeParameter) {
return InheritanceUtil.isInheritorOrSelf(sam, PsiUtil.resolveClassInClassTypeOnly(TypeConversionUtil.erasure(paramType)), true);
}
String paramClassName = paramType instanceof PsiClassType ? ((PsiClassType)paramType).getClassName() : null;
if (paramClassName == null) return false;
return InheritanceUtil.isInheritorOrSelf(functionalCandidate, sam, true);
if (paramClassName.equals(sam.getName())) return true;
JBIterable<String> typeParameters = JBIterable.generate(place, PsiElement::getContext)
.takeWhile(c -> !(c instanceof PsiFile))
.filter(PsiTypeParameterListOwner.class)
.flatMap(o -> Arrays.asList(o.getTypeParameters()))
.map(PsiNamedElement::getName);
if (typeParameters.contains(paramClassName)) {
PsiClass functionalCandidate = ((PsiClassType)paramType).resolve();
return functionalCandidate instanceof PsiTypeParameter &&
InheritanceUtil.isInheritorOrSelf(sam, PsiUtil.resolveClassInClassTypeOnly(TypeConversionUtil.erasure(paramType)), true);
}
return false;
}
}