Esempio n. 1
0
 private static PsiType getFunctionalInterfaceTypeByContainingLambda(
     @NotNull PsiLambdaExpression parentLambda) {
   final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType();
   return parentInterfaceType != null
       ? getFunctionalInterfaceReturnType(parentInterfaceType)
       : null;
 }
Esempio n. 2
0
 private static boolean checkRawAcceptable(
     PsiLambdaExpression expression, PsiType functionalInterfaceType) {
   PsiElement parent = expression.getParent();
   while (parent instanceof PsiParenthesizedExpression) {
     parent = parent.getParent();
   }
   if (parent instanceof PsiExpressionList) {
     final PsiElement gParent = parent.getParent();
     if (gParent instanceof PsiMethodCallExpression) {
       final PsiExpression qualifierExpression =
           ((PsiMethodCallExpression) gParent).getMethodExpression().getQualifierExpression();
       final PsiType type = qualifierExpression != null ? qualifierExpression.getType() : null;
       if (type instanceof PsiClassType && ((PsiClassType) type).isRaw()) {
         return true;
       }
       final PsiMethod method = ((PsiMethodCallExpression) gParent).resolveMethod();
       if (method != null) {
         int lambdaIdx = getLambdaIdx((PsiExpressionList) parent, expression);
         final PsiParameter[] parameters = method.getParameterList().getParameters();
         final PsiType normalizedType =
             getNormalizedType(parameters[adjustLambdaIdx(lambdaIdx, method, parameters)]);
         if (normalizedType instanceof PsiClassType && ((PsiClassType) normalizedType).isRaw())
           return true;
       }
     }
     if (functionalInterfaceType instanceof PsiClassType
         && ((PsiClassType) functionalInterfaceType).isRaw()) {
       return false;
     }
   }
   return true;
 }
Esempio n. 3
0
  public static boolean isLambdaFullyInferred(
      PsiLambdaExpression expression, PsiType functionalInterfaceType) {
    final boolean hasParams = expression.getParameterList().getParametersCount() > 0;
    if (hasParams
        || getFunctionalInterfaceReturnType(functionalInterfaceType)
            != PsiType.VOID) { // todo check that void lambdas without params check

      return !dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression);
    }
    return true;
  }
Esempio n. 4
0
 public static List<PsiExpression> getReturnExpressions(PsiLambdaExpression lambdaExpression) {
   final PsiElement body = lambdaExpression.getBody();
   if (body instanceof PsiExpression) {
     // if (((PsiExpression)body).getType() != PsiType.VOID) return Collections.emptyList();
     return Collections.singletonList((PsiExpression) body);
   }
   final List<PsiExpression> result = new ArrayList<PsiExpression>();
   for (PsiReturnStatement returnStatement : getReturnStatements(lambdaExpression)) {
     final PsiExpression returnValue = returnStatement.getReturnValue();
     if (returnValue != null) {
       result.add(returnValue);
     }
   }
   return result;
 }
Esempio n. 5
0
  public static List<PsiReturnStatement> getReturnStatements(PsiLambdaExpression lambdaExpression) {
    final PsiElement body = lambdaExpression.getBody();
    final List<PsiReturnStatement> result = new ArrayList<PsiReturnStatement>();
    if (body != null) {
      body.accept(
          new JavaRecursiveElementVisitor() {
            @Override
            public void visitReturnStatement(PsiReturnStatement statement) {
              result.add(statement);
            }

            @Override
            public void visitClass(PsiClass aClass) {}

            @Override
            public void visitLambdaExpression(PsiLambdaExpression expression) {}
          });
    }
    return result;
  }
Esempio n. 6
0
 @Nullable
 public static PsiType getFunctionalInterfaceReturnType(PsiLambdaExpression expr) {
   return getFunctionalInterfaceReturnType(expr.getFunctionalInterfaceType());
 }
Esempio n. 7
0
  public static boolean isFreeFromTypeInferenceArgs(
      final PsiParameter[] methodParameters,
      final PsiLambdaExpression lambdaExpression,
      final PsiExpression expression,
      final PsiSubstitutor subst,
      final PsiType functionalInterfaceType,
      final PsiTypeParameter typeParam) {
    if (expression instanceof PsiCallExpression
        && ((PsiCallExpression) expression).getTypeArguments().length > 0) return true;
    if (expression instanceof PsiNewExpression) {
      final PsiJavaCodeReferenceElement classReference =
          ((PsiNewExpression) expression).getClassOrAnonymousClassReference();
      if (classReference != null) {
        final PsiReferenceParameterList parameterList = classReference.getParameterList();
        if (parameterList != null) {
          final PsiTypeElement[] typeParameterElements = parameterList.getTypeParameterElements();
          if (typeParameterElements.length > 0) {
            if (!(typeParameterElements[0].getType() instanceof PsiDiamondType)) {
              return true;
            }
          }
        }
      }
    }
    final PsiParameter[] lambdaParams = lambdaExpression.getParameterList().getParameters();
    if (lambdaParams.length != methodParameters.length) return false;
    final boolean[] independent = {true};
    final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(functionalInterfaceType);
    if (interfaceMethod == null) return false;
    final TypeParamsChecker paramsChecker = new TypeParamsChecker(lambdaExpression);
    for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) {
      subst.substitute(parameter.getType()).accept(paramsChecker);
    }
    paramsChecker.myUsedTypeParams.add(typeParam);

    expression.accept(
        new JavaRecursiveElementWalkingVisitor() {
          @Override
          public void visitConditionalExpression(PsiConditionalExpression expression) {
            final PsiExpression thenExpression = expression.getThenExpression();
            if (thenExpression != null) {
              thenExpression.accept(this);
            }
            final PsiExpression elseExpression = expression.getElseExpression();
            if (elseExpression != null) {
              elseExpression.accept(this);
            }
          }

          @Override
          public void visitReferenceExpression(PsiReferenceExpression expression) {
            super.visitReferenceExpression(expression);
            int usedParamIdx = -1;
            for (int i = 0; i < lambdaParams.length; i++) {
              PsiParameter param = lambdaParams[i];
              if (expression.isReferenceTo(param)) {
                usedParamIdx = i;
                break;
              }
            }

            if (usedParamIdx > -1
                && dependsOnTypeParams(
                    subst.substitute(methodParameters[usedParamIdx].getType()),
                    functionalInterfaceType,
                    lambdaExpression,
                    paramsChecker.myUsedTypeParams.toArray(
                        new PsiTypeParameter[paramsChecker.myUsedTypeParams.size()]))) {
              independent[0] = false;
            }
          }
        });
    return independent[0];
  }
Esempio n. 8
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;
  }