boolean (@NotNull PsiLambdaExpression lambda, @NotNull Function<? super PsiLambdaExpression, ? extends PsiExpression> replacer) { PsiElement body = lambda.getBody(); if (body == null) return false; final PsiCall call = treeWalkUp(body); if (call != null) { JavaResolveResult result = call.resolveMethodGenerics(); PsiElement oldTarget = result.getElement(); if (oldTarget != null) { String origErrorMessage = result instanceof MethodCandidateInfo ? ((MethodCandidateInfo)result).getInferenceErrorMessage() : null; Object marker = new Object(); PsiTreeUtil.mark(lambda, marker); PsiType origType = call instanceof PsiExpression ? ((PsiExpression)call).getType() : null; PsiCall copyCall = copyTopLevelCall(call); if (copyCall == null) return false; PsiLambdaExpression lambdaCopy = ObjectUtils.tryCast(PsiTreeUtil.releaseMark(copyCall, marker), PsiLambdaExpression.class); if (lambdaCopy == null) return false; PsiExpression function = replacer.apply(lambdaCopy); if (function == null) return false; JavaResolveResult resultCopy = copyCall.resolveMethodGenerics(); if (!oldTarget.getManager().areElementsEquivalent(resultCopy.getElement(), oldTarget)) return false; String copyMessage = resultCopy instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resultCopy).getInferenceErrorMessage() : null; if (!Objects.equals(origErrorMessage, copyMessage)) return false; if (function instanceof PsiFunctionalExpression) { PsiType functionalType = ((PsiFunctionalExpression)function).getFunctionalInterfaceType(); if (functionalType == null) return false; PsiType lambdaFunctionalType = lambda.getFunctionalInterfaceType(); if (lambdaFunctionalType != null && !functionalType.getCanonicalText().equals(lambdaFunctionalType.getCanonicalText())) { return false; } } if (origType instanceof PsiClassType && !((PsiClassType)origType).isRaw() && //when lambda has no formal parameter types, it's ignored during applicability check //so unchecked warnings inside lambda's body won't lead to erasure of the type of the containing call //but after replacement of lambda with the equivalent method call, unchecked warning won't be ignored anymore //and the type of the call would be erased => red code may appear !lambda.hasFormalParameterTypes()) { PsiExpression expressionFromBody = extractSingleExpressionFromBody(body); if (expressionFromBody instanceof PsiMethodCallExpression && PsiTypesUtil.isUncheckedCall(((PsiMethodCallExpression)expressionFromBody).resolveMethodGenerics())) { return false; } } } } else if (PsiPolyExpressionUtil.isInAssignmentOrInvocationContext(lambda)) { PsiType origType = lambda.getFunctionalInterfaceType(); if (origType != null) { PsiLambdaExpression lambdaCopy = (PsiLambdaExpression)copyWithExpectedType(lambda, origType); PsiExpression replacement = replacer.apply(lambdaCopy); PsiType type = replacement.getType(); return type != null && origType.isAssignableFrom(type); } } return true; }