private static void simplifyRedundantCast(PsiElement result) {
   final PsiMethodReferenceExpression methodReferenceExpression =
       PsiTreeUtil.findChildOfType(result, PsiMethodReferenceExpression.class);
   if (methodReferenceExpression != null) {
     final PsiElement parent = methodReferenceExpression.getParent();
     if (parent instanceof PsiTypeCastExpression) {
       if (RedundantCastUtil.isCastRedundant((PsiTypeCastExpression) parent)) {
         final PsiExpression operand = ((PsiTypeCastExpression) parent).getOperand();
         LOG.assertTrue(operand != null);
         parent.replace(operand);
       }
     }
   }
 }
 public static boolean isValidQualifier(PsiMethodReferenceExpression expression) {
   final PsiElement referenceNameElement = expression.getReferenceNameElement();
   if (referenceNameElement instanceof PsiKeyword) {
     final PsiElement qualifier = expression.getQualifier();
     if (qualifier instanceof PsiTypeElement) {
       return true;
     }
     if (qualifier instanceof PsiReferenceExpression
         && ((PsiReferenceExpression) qualifier).resolve() instanceof PsiClass) {
       return true;
     }
   }
   return false;
 }
 public static boolean isStaticallyReferenced(
     @NotNull PsiMethodReferenceExpression methodReferenceExpression) {
   final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
   if (qualifierExpression != null) {
     return qualifierExpression instanceof PsiReferenceExpression
         && ((PsiReferenceExpression) qualifierExpression).resolve() instanceof PsiClass;
   }
   return true;
 }
 @Nullable
 public static PsiType getQualifierType(PsiMethodReferenceExpression expression) {
   PsiType qualifierType = null;
   final PsiTypeElement typeElement = expression.getQualifierType();
   if (typeElement != null) {
     qualifierType = typeElement.getType();
   } else {
     final PsiElement qualifier = expression.getQualifier();
     if (qualifier instanceof PsiExpression) {
       qualifierType = ((PsiExpression) qualifier).getType();
     }
   }
   if (qualifierType == null) {
     final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(expression);
     final PsiClass containingClass = qualifierResolveResult.getContainingClass();
     if (containingClass == null) {
       return null;
     }
     qualifierType =
         JavaPsiFacade.getElementFactory(expression.getProject()).createType(containingClass);
   }
   return qualifierType;
 }
 public static boolean hasReceiver(
     PsiType[] parameterTypes,
     QualifierResolveResult qualifierResolveResult,
     PsiMethodReferenceExpression methodRef) {
   if (parameterTypes.length > 0
       && !methodRef.isConstructor()
       && isReceiverType(
           parameterTypes[0],
           qualifierResolveResult.getContainingClass(),
           qualifierResolveResult.getSubstitutor())
       && isStaticallyReferenced(methodRef)) {
     return true;
   }
   return false;
 }
 @NotNull
 public static QualifierResolveResult getQualifierResolveResult(
     @NotNull PsiMethodReferenceExpression methodReferenceExpression) {
   PsiClass containingClass = null;
   PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
   final PsiExpression expression = methodReferenceExpression.getQualifierExpression();
   if (expression != null) {
     final PsiType expressionType = getExpandedType(expression.getType(), expression);
     PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(expressionType);
     containingClass = result.getElement();
     if (containingClass != null) {
       substitutor = result.getSubstitutor();
     }
     if (containingClass == null && expression instanceof PsiReferenceExpression) {
       final JavaResolveResult resolveResult =
           ((PsiReferenceExpression) expression).advancedResolve(false);
       final PsiElement resolve = resolveResult.getElement();
       if (resolve instanceof PsiClass) {
         containingClass = (PsiClass) resolve;
         substitutor = resolveResult.getSubstitutor();
         return new QualifierResolveResult(containingClass, substitutor, true);
       }
     }
   } else {
     final PsiTypeElement typeElement = methodReferenceExpression.getQualifierType();
     if (typeElement != null) {
       PsiType type = getExpandedType(typeElement.getType(), typeElement);
       PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type);
       containingClass = result.getElement();
       if (containingClass != null) {
         return new QualifierResolveResult(containingClass, result.getSubstitutor(), true);
       }
     }
   }
   return new QualifierResolveResult(containingClass, substitutor, false);
 }
  public static String checkReturnType(
      PsiMethodReferenceExpression expression,
      JavaResolveResult result,
      PsiType functionalInterfaceType) {
    final PsiElement resolve = result.getElement();
    if (resolve instanceof PsiMethod) {
      final PsiClass containingClass = ((PsiMethod) resolve).getContainingClass();
      LOG.assertTrue(containingClass != null);
      PsiSubstitutor subst = result.getSubstitutor();
      PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass();
      if (qContainingClass != null
          && isReceiverType(functionalInterfaceType, containingClass, (PsiMethod) resolve)) {
        subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst);
        LOG.assertTrue(subst != null);
      }

      final PsiType interfaceReturnType =
          LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);

      PsiType returnType =
          PsiTypesUtil.patchMethodGetClassReturnType(
              expression,
              expression,
              (PsiMethod) resolve,
              null,
              PsiUtil.getLanguageLevel(expression));
      if (returnType == null) {
        returnType = ((PsiMethod) resolve).getReturnType();
      }
      PsiType methodReturnType = subst.substitute(returnType);
      if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) {
        if (methodReturnType == null) {
          methodReturnType =
              JavaPsiFacade.getElementFactory(expression.getProject())
                  .createType(containingClass, subst);
        }
        if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) {
          return "Bad return type in method reference: cannot convert "
              + methodReturnType.getCanonicalText()
              + " to "
              + interfaceReturnType.getCanonicalText();
        }
      }
    }
    return null;
  }
 public static boolean hasReceiver(
     @NotNull PsiMethodReferenceExpression methodRef, @NotNull PsiMethod method) {
   return hasReceiver(methodRef, method, methodRef.getFunctionalInterfaceType());
 }
  public static String checkMethodReferenceContext(
      PsiMethodReferenceExpression methodRef, PsiElement resolve, PsiType functionalInterfaceType) {
    final PsiClass containingClass =
        resolve instanceof PsiMethod
            ? ((PsiMethod) resolve).getContainingClass()
            : (PsiClass) resolve;
    final boolean isStaticSelector = isStaticallyReferenced(methodRef);
    final PsiElement qualifier = methodRef.getQualifier();

    boolean isMethodStatic = false;
    boolean receiverReferenced = false;
    boolean isConstructor = true;

    if (resolve instanceof PsiMethod) {
      final PsiMethod method = (PsiMethod) resolve;

      isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
      isConstructor = method.isConstructor();
      receiverReferenced = hasReceiver(methodRef, method, functionalInterfaceType);

      if (method.hasModifierProperty(PsiModifier.ABSTRACT)
          && qualifier instanceof PsiSuperExpression) {
        return "Abstract method '" + method.getName() + "' cannot be accessed directly";
      }
    }

    if (!receiverReferenced && isStaticSelector && !isMethodStatic && !isConstructor) {
      return "Non-static method cannot be referenced from a static context";
    }

    if (!receiverReferenced && !isStaticSelector && isMethodStatic) {
      return "Static method referenced through non-static qualifier";
    }

    if (receiverReferenced && isStaticSelector && isMethodStatic && !isConstructor) {
      return "Static method referenced through receiver";
    }

    if (isMethodStatic && isStaticSelector && qualifier instanceof PsiTypeElement) {
      final PsiJavaCodeReferenceElement referenceElement =
          PsiTreeUtil.getChildOfType(qualifier, PsiJavaCodeReferenceElement.class);
      if (referenceElement != null) {
        final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
        if (parameterList != null && parameterList.getTypeArguments().length > 0) {
          return "Parameterized qualifier on static method reference";
        }
      }
    }

    if (isConstructor) {
      if (containingClass != null
          && PsiUtil.isInnerClass(containingClass)
          && containingClass.isPhysical()) {
        PsiClass outerClass = containingClass.getContainingClass();
        if (outerClass != null
            && !InheritanceUtil.hasEnclosingInstanceInScope(outerClass, methodRef, true, false)) {
          return "An enclosing instance of type "
              + PsiFormatUtil.formatClass(outerClass, PsiFormatUtilBase.SHOW_NAME)
              + " is not in scope";
        }
      }
    }
    return null;
  }
  public static String checkMethodReferenceContext(PsiMethodReferenceExpression methodRef) {
    final PsiElement resolve = methodRef.resolve();

    if (resolve == null) return null;
    return checkMethodReferenceContext(methodRef, resolve, methodRef.getFunctionalInterfaceType());
  }