mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
abandon isFullyInferred from LambdaUtil
This commit is contained in:
-29
@@ -112,37 +112,8 @@ public class LambdaHighlightingUtil {
|
||||
if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
MethodSignature functionalMethod = LambdaUtil.getFunction(aClass);
|
||||
if (functionalMethod != null && functionalMethod.getTypeParameters().length > 0) return "Target method is generic";
|
||||
if (checkReturnTypeApplicable(resolveResult, aClass)) {
|
||||
return "No instance of type " + functionalInterfaceType.getPresentableText() + " exists so that lambda expression can be type-checked";
|
||||
}
|
||||
return checkInterfaceFunctional(aClass);
|
||||
}
|
||||
return functionalInterfaceType.getPresentableText() + " is not a functional interface";
|
||||
}
|
||||
|
||||
private static boolean checkReturnTypeApplicable(PsiClassType.ClassResolveResult resolveResult, final PsiClass aClass) {
|
||||
final MethodSignature methodSignature = LambdaUtil.getFunction(aClass);
|
||||
if (methodSignature == null) return false;
|
||||
|
||||
for (PsiTypeParameter parameter : aClass.getTypeParameters()) {
|
||||
if (parameter.getExtendsListTypes().length == 0) continue;
|
||||
final PsiType substitution = resolveResult.getSubstitutor().substitute(parameter);
|
||||
if (substitution instanceof PsiWildcardType && !((PsiWildcardType)substitution).isBounded()) {
|
||||
boolean depends = false;
|
||||
for (PsiType paramType : methodSignature.getParameterTypes()) {
|
||||
if (LambdaUtil.depends(paramType, new LambdaUtil.TypeParamsChecker((PsiMethod)null, aClass) {
|
||||
@Override
|
||||
public boolean startedInference() {
|
||||
return true;
|
||||
}
|
||||
}, parameter)) {
|
||||
depends = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!depends) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-37
@@ -23,9 +23,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -55,7 +52,7 @@ public class RedundantLambdaParameterTypeInspection extends BaseJavaBatchLocalIn
|
||||
if (parameter.getTypeElement() == null) return false;
|
||||
}
|
||||
if (parameters.length == 0) return false;
|
||||
final PsiType functionalInterfaceType = LambdaUtil.getFunctionalInterfaceType(expression, true);
|
||||
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null) {
|
||||
final PsiElement lambdaParent = expression.getParent();
|
||||
if (lambdaParent instanceof PsiExpressionList) {
|
||||
@@ -67,36 +64,15 @@ public class RedundantLambdaParameterTypeInspection extends BaseJavaBatchLocalIn
|
||||
final int idx = LambdaUtil.getLambdaIdx((PsiExpressionList)lambdaParent, expression);
|
||||
if (idx < 0) return false;
|
||||
|
||||
final PsiTypeParameter[] typeParameters = method.getTypeParameters();
|
||||
final PsiExpression[] arguments = ((PsiExpressionList)lambdaParent).getExpressions();
|
||||
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(parameterList.getProject());
|
||||
arguments[idx] = javaPsiFacade.getElementFactory().createExpressionFromText(
|
||||
"(" + StringUtil.join(expression.getParameterList().getParameters(), PsiParameter::getName, ", ") + ") -> {}", expression);
|
||||
final PsiParameter[] methodParams = method.getParameterList().getParameters();
|
||||
final PsiSubstitutor substitutor = javaPsiFacade.getResolveHelper()
|
||||
.inferTypeArguments(typeParameters, methodParams, arguments, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(),
|
||||
gParent, DefaultParameterTypeInferencePolicy.INSTANCE);
|
||||
|
||||
for (PsiTypeParameter parameter : typeParameters) {
|
||||
final PsiType psiType = substitutor.substitute(parameter);
|
||||
if (psiType == null || dependsOnTypeParams(psiType, expression, parameter)) return false;
|
||||
PsiCallExpression copy = (PsiCallExpression)gParent.copy();
|
||||
PsiLambdaExpression lambdaToStripTypeParameters = (PsiLambdaExpression)copy.getArgumentList().getExpressions()[idx];
|
||||
for (PsiParameter parameter : lambdaToStripTypeParameters.getParameterList().getParameters()) {
|
||||
parameter.getTypeElement().delete();
|
||||
}
|
||||
|
||||
final PsiType paramType;
|
||||
if (idx < methodParams.length) {
|
||||
paramType = methodParams[idx].getType();
|
||||
}
|
||||
else {
|
||||
final PsiParameter lastParam = methodParams[methodParams.length - 1];
|
||||
if (!lastParam.isVarArgs()) return false;
|
||||
paramType = ((PsiEllipsisType)lastParam.getType()).getComponentType();
|
||||
}
|
||||
return functionalInterfaceType.isAssignableFrom(substitutor.substitute(paramType));
|
||||
return functionalInterfaceType.equals(lambdaToStripTypeParameters.getFunctionalInterfaceType());
|
||||
}
|
||||
}
|
||||
if (!LambdaUtil.isLambdaFullyInferred(expression, functionalInterfaceType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -118,13 +94,6 @@ public class RedundantLambdaParameterTypeInspection extends BaseJavaBatchLocalIn
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean dependsOnTypeParams(PsiType type,
|
||||
PsiLambdaExpression expr,
|
||||
PsiTypeParameter param2Check) {
|
||||
return LambdaUtil.depends(type, new LambdaUtil.TypeParamsChecker(expr, PsiUtil
|
||||
.resolveGenericsClassInType(LambdaUtil.getFunctionalInterfaceType(expr, false)).getElement()), param2Check);
|
||||
}
|
||||
|
||||
private static class LambdaParametersFix implements LocalQuickFix {
|
||||
@Nls
|
||||
@NotNull
|
||||
|
||||
@@ -154,15 +154,6 @@ public class LambdaUtil {
|
||||
context instanceof PsiArrayInitializerExpression;
|
||||
}
|
||||
|
||||
public static boolean isLambdaFullyInferred(PsiLambdaExpression expression, PsiType functionalInterfaceType) {
|
||||
final boolean hasParams = expression.getParameterList().getParametersCount() > 0;
|
||||
if (hasParams || !PsiType.VOID.equals(getFunctionalInterfaceReturnType(functionalInterfaceType))) { //todo check that void lambdas without params check
|
||||
|
||||
return !dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
@Nullable
|
||||
public static MethodSignature getFunction(final PsiClass psiClass) {
|
||||
@@ -348,23 +339,6 @@ public class LambdaUtil {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static boolean dependsOnTypeParams(PsiType type,
|
||||
PsiType functionalInterfaceType,
|
||||
PsiElement lambdaExpression,
|
||||
PsiTypeParameter... param2Check) {
|
||||
return depends(type, new TypeParamsChecker(lambdaExpression,
|
||||
PsiUtil.resolveClassInType(functionalInterfaceType)), param2Check);
|
||||
}
|
||||
|
||||
public static boolean depends(PsiType type, TypeParamsChecker visitor, PsiTypeParameter... param2Check) {
|
||||
if (!visitor.startedInference()) return false;
|
||||
final Boolean accept = type.accept(visitor);
|
||||
if (param2Check.length > 0) {
|
||||
return visitor.used(param2Check);
|
||||
}
|
||||
return accept != null && accept.booleanValue();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getFunctionalInterfaceType(PsiElement expression, final boolean tryToSubstitute) {
|
||||
PsiElement parent = expression.getParent();
|
||||
@@ -887,99 +861,4 @@ public class LambdaUtil {
|
||||
return expression instanceof PsiReferenceExpression &&
|
||||
((PsiReferenceExpression)expression).isReferenceTo(parameters.getParameters()[0]);
|
||||
}
|
||||
|
||||
public static class TypeParamsChecker extends PsiTypeVisitor<Boolean> {
|
||||
private PsiMethod myMethod;
|
||||
private final PsiClass myClass;
|
||||
public final Set<PsiTypeParameter> myUsedTypeParams = new HashSet<>();
|
||||
|
||||
public TypeParamsChecker(PsiElement expression, PsiClass aClass) {
|
||||
myClass = aClass;
|
||||
PsiElement parent = expression != null ? expression.getParent() : null;
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiCall) {
|
||||
final MethodCandidateInfo.CurrentCandidateProperties pair = MethodCandidateInfo.getCurrentMethod(parent);
|
||||
myMethod = pair != null ? pair.getMethod() : null;
|
||||
if (myMethod == null) {
|
||||
myMethod = ((PsiCall)gParent).resolveMethod();
|
||||
}
|
||||
if (myMethod != null && PsiTreeUtil.isAncestor(myMethod, expression, false)) {
|
||||
myMethod = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startedInference() {
|
||||
return myMethod != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitClassType(PsiClassType classType) {
|
||||
boolean used = false;
|
||||
for (PsiType paramType : classType.getParameters()) {
|
||||
final Boolean paramAccepted = paramType.accept(this);
|
||||
used |= paramAccepted != null && paramAccepted.booleanValue();
|
||||
}
|
||||
final PsiClass resolve = classType.resolve();
|
||||
if (resolve instanceof PsiTypeParameter) {
|
||||
final PsiTypeParameter typeParameter = (PsiTypeParameter)resolve;
|
||||
if (check(typeParameter)) {
|
||||
myUsedTypeParams.add(typeParameter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitWildcardType(PsiWildcardType wildcardType) {
|
||||
final PsiType bound = wildcardType.getBound();
|
||||
if (bound != null) return bound.accept(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitLambdaExpressionType(PsiLambdaExpressionType lambdaExpressionType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitArrayType(PsiArrayType arrayType) {
|
||||
return arrayType.getComponentType().accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitType(PsiType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean check(PsiTypeParameter check) {
|
||||
final PsiTypeParameterListOwner owner = check.getOwner();
|
||||
if (owner == myMethod || owner == myClass) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean used(PsiTypeParameter... parameters) {
|
||||
for (PsiTypeParameter parameter : parameters) {
|
||||
if (myUsedTypeParams.contains(parameter)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -216,7 +216,6 @@ public class LambdaCanBeReplacedWithAnonymousInspection extends BaseInspection {
|
||||
}
|
||||
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null &&
|
||||
LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType) &&
|
||||
LambdaUtil.isFunctionalType(functionalInterfaceType)) {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
|
||||
if (interfaceMethod != null) {
|
||||
|
||||
+1
-2
@@ -67,8 +67,7 @@ public class LambdaParameterTypeCanBeSpecifiedInspection extends BaseInspection
|
||||
}
|
||||
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null &&
|
||||
LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null &&
|
||||
LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType)) {
|
||||
LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null) {
|
||||
final String inferredTypesText = LambdaRefactoringUtil.createLambdaParameterListWithFormalTypes(functionalInterfaceType, lambdaExpression,
|
||||
true);
|
||||
if (inferredTypesText != null) {
|
||||
|
||||
+1
-2
@@ -69,8 +69,7 @@ public class ExtractToMethodReferenceIntention extends BaseElementAtCaretIntenti
|
||||
//is a valid lambda
|
||||
PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType == null ||
|
||||
LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType) == null ||
|
||||
!LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType)) {
|
||||
LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType) == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user