@Override
  public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element)
      throws IncorrectOperationException {
    try {
      if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;

      final PsiJavaToken token = (PsiJavaToken) element;
      final PsiPolyadicExpression expression =
          SplitConditionUtil.findCondition(element, true, false);

      final PsiLambdaExpression lambdaExpression =
          PsiTreeUtil.getParentOfType(expression, PsiLambdaExpression.class);
      LOG.assertTrue(lambdaExpression != null);
      final String lambdaParameterName =
          lambdaExpression.getParameterList().getParameters()[0].getName();

      final PsiMethodCallExpression methodCallExpression =
          PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class);
      LOG.assertTrue(methodCallExpression != null, expression);

      PsiExpression lOperand = getLOperands(expression, token);
      PsiExpression rOperand = getROperands(expression, token);

      final Collection<PsiComment> comments =
          PsiTreeUtil.findChildrenOfType(expression, PsiComment.class);

      final PsiMethodCallExpression chainedCall =
          (PsiMethodCallExpression)
              JavaPsiFacade.getElementFactory(project)
                  .createExpressionFromText(
                      "a.filter(" + lambdaParameterName + " -> x)", expression);
      final PsiExpression argExpression = chainedCall.getArgumentList().getExpressions()[0];
      final PsiElement rReplaced =
          ((PsiLambdaExpression) argExpression).getBody().replace(rOperand);

      final PsiExpression compoundArg = methodCallExpression.getArgumentList().getExpressions()[0];

      final int separatorOffset = token.getTextOffset();
      for (PsiComment comment : comments) {
        if (comment.getTextOffset() < separatorOffset) {
          compoundArg.getParent().add(comment);
        } else {
          rReplaced.getParent().add(comment);
        }
      }

      ((PsiLambdaExpression) compoundArg).getBody().replace(lOperand);

      chainedCall.getMethodExpression().getQualifierExpression().replace(methodCallExpression);
      methodCallExpression.replace(chainedCall);
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
Exemplo 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;
 }
Exemplo n.º 3
0
 private static PsiType getFunctionalInterfaceTypeByContainingLambda(
     @NotNull PsiLambdaExpression parentLambda) {
   final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType();
   return parentInterfaceType != null
       ? getFunctionalInterfaceReturnType(parentInterfaceType)
       : null;
 }
Exemplo n.º 4
0
 private void registerNestedClosures(
     @NotNull DfaInstructionState instructionState, @NotNull PsiLambdaExpression expr) {
   DfaMemoryState state = instructionState.getMemoryState();
   PsiElement body = expr.getBody();
   if (body != null) {
     myNestedClosures.putValue(body, createClosureState(state));
   }
 }
Exemplo n.º 5
0
 @Override
 public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
   final PsiElement element = descriptor.getPsiElement();
   if (element != null) {
     if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
     final PsiLambdaExpression lambdaExpression =
         PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
     if (lambdaExpression != null) {
       final PsiElement body = lambdaExpression.getBody();
       if (body != null) {
         PsiExpression expression = LambdaUtil.extractSingleExpressionFromBody(body);
         if (expression != null) {
           body.replace(expression);
         }
       }
     }
   }
 }
Exemplo n.º 6
0
 public static boolean processDeclarationsInLambda(
     @NotNull final PsiLambdaExpression lambda,
     @NotNull final PsiScopeProcessor processor,
     @NotNull final ResolveState state,
     final PsiElement lastParent,
     @NotNull final PsiElement place) {
   final boolean fromBody = lastParent != null && lastParent == lambda.getBody();
   return processDeclarationsInMethodLike(lambda, processor, state, place, fromBody, null);
 }
Exemplo n.º 7
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;
  }
Exemplo n.º 8
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;
 }
Exemplo n.º 9
0
 @Nullable
 public static PsiElement getFirstElementOnTheLine(
     PsiLambdaExpression lambda, Document document, int line) {
   ApplicationManager.getApplication().assertReadAccessAllowed();
   TextRange lineRange = DocumentUtil.getLineTextRange(document, line);
   if (!intersects(lineRange, lambda)) return null;
   PsiElement body = lambda.getBody();
   if (body == null || !intersects(lineRange, body)) return null;
   if (body instanceof PsiCodeBlock) {
     for (PsiStatement statement : ((PsiCodeBlock) body).getStatements()) {
       if (intersects(lineRange, statement)) {
         return statement;
       }
     }
     return null;
   }
   return body;
 }
Exemplo n.º 10
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;
  }
Exemplo n.º 11
0
 @Nullable
 public static PsiType getFunctionalInterfaceReturnType(PsiLambdaExpression expr) {
   return getFunctionalInterfaceReturnType(expr.getFunctionalInterfaceType());
 }
Exemplo n.º 12
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];
  }
Exemplo n.º 13
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;
  }