public static boolean isReceiverType(
     PsiType functionalInterfaceType,
     PsiClass containingClass,
     @Nullable PsiMethod referencedMethod) {
   final PsiClassType.ClassResolveResult resolveResult =
       PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
   final MethodSignature function = LambdaUtil.getFunction(resolveResult.getElement());
   if (function != null) {
     final int interfaceMethodParamsLength = function.getParameterTypes().length;
     if (interfaceMethodParamsLength > 0) {
       final PsiType firstParamType =
           resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]);
       boolean isReceiver =
           isReceiverType(
               firstParamType,
               containingClass,
               PsiUtil.resolveGenericsClassInType(firstParamType).getSubstitutor());
       if (isReceiver) {
         if (referencedMethod == null) {
           if (interfaceMethodParamsLength == 1) return true;
           return false;
         }
         if (referencedMethod.getParameterList().getParametersCount()
             != interfaceMethodParamsLength - 1) {
           return false;
         }
         return true;
       }
     }
   }
   return false;
 }
 private static boolean hasReceiver(
     @NotNull PsiMethodReferenceExpression methodRef,
     @NotNull PsiMethod method,
     PsiType functionalInterfaceType) {
   final PsiClassType.ClassResolveResult resolveResult =
       PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
   final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
   final MethodSignature signature =
       interfaceMethod != null
           ? interfaceMethod.getSignature(
               LambdaUtil.getSubstitutor(interfaceMethod, resolveResult))
           : null;
   if (signature == null) {
     return false;
   }
   final PsiType[] parameterTypes = signature.getParameterTypes();
   final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(methodRef);
   return (method.getParameterList().getParametersCount() + 1 == parameterTypes.length
           || method.isVarArgs()
               && parameterTypes.length > 0
               && !method.hasModifierProperty(PsiModifier.STATIC))
       && hasReceiver(parameterTypes, qualifierResolveResult, methodRef);
 }
예제 #3
0
  public static boolean isAcceptable(
      PsiLambdaExpression lambdaExpression, final PsiType leftType, boolean checkReturnType) {
    if (leftType instanceof PsiIntersectionType) {
      for (PsiType conjunctType : ((PsiIntersectionType) leftType).getConjuncts()) {
        if (isAcceptable(lambdaExpression, conjunctType, checkReturnType)) return true;
      }
      return false;
    }
    final PsiClassType.ClassResolveResult resolveResult =
        PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(leftType));
    final PsiClass psiClass = resolveResult.getElement();
    if (psiClass instanceof PsiAnonymousClass) {
      return isAcceptable(
          lambdaExpression, ((PsiAnonymousClass) psiClass).getBaseClassType(), checkReturnType);
    }
    final MethodSignature methodSignature = getFunction(psiClass);
    if (methodSignature == null) return false;
    final PsiParameter[] lambdaParameters = lambdaExpression.getParameterList().getParameters();
    final PsiType[] parameterTypes = methodSignature.getParameterTypes();
    if (lambdaParameters.length != parameterTypes.length) return false;
    for (int lambdaParamIdx = 0, length = lambdaParameters.length;
        lambdaParamIdx < length;
        lambdaParamIdx++) {
      PsiParameter parameter = lambdaParameters[lambdaParamIdx];
      final PsiTypeElement typeElement = parameter.getTypeElement();
      if (typeElement != null) {
        final PsiType lambdaFormalType = typeElement.getType();
        final PsiType methodParameterType = parameterTypes[lambdaParamIdx];
        if (lambdaFormalType instanceof PsiPrimitiveType) {
          if (methodParameterType instanceof PsiPrimitiveType)
            return methodParameterType.equals(lambdaFormalType);
          return false;
        }

        if (!TypeConversionUtil.erasure(lambdaFormalType)
            .isAssignableFrom(
                TypeConversionUtil.erasure(
                    GenericsUtil.eliminateWildcards(
                        resolveResult
                            .getSubstitutor()
                            .substitute(
                                methodSignature
                                    .getSubstitutor()
                                    .substitute(methodParameterType)))))) {
          return false;
        }
      }
    }
    if (checkReturnType) {
      final String uniqueVarName =
          JavaCodeStyleManager.getInstance(lambdaExpression.getProject())
              .suggestUniqueVariableName("l", lambdaExpression, true);
      String canonicalText = leftType.getCanonicalText();
      if (leftType instanceof PsiEllipsisType) {
        canonicalText = ((PsiEllipsisType) leftType).toArrayType().getCanonicalText();
      }
      final PsiStatement assignmentFromText =
          JavaPsiFacade.getElementFactory(lambdaExpression.getProject())
              .createStatementFromText(
                  canonicalText + " " + uniqueVarName + " = " + lambdaExpression.getText(),
                  lambdaExpression);
      final PsiLocalVariable localVariable =
          (PsiLocalVariable)
              ((PsiDeclarationStatement) assignmentFromText).getDeclaredElements()[0];
      LOG.assertTrue(psiClass != null);
      PsiType methodReturnType = getReturnType(psiClass, methodSignature);
      if (methodReturnType != null) {
        methodReturnType =
            resolveResult
                .getSubstitutor()
                .substitute(methodSignature.getSubstitutor().substitute(methodReturnType));
        return LambdaHighlightingUtil.checkReturnTypeCompatible(
                (PsiLambdaExpression) localVariable.getInitializer(), methodReturnType)
            == null;
      }
    }
    return true;
  }