private static boolean isCollectCall(PsiStatement body, final PsiParameter parameter) { PsiIfStatement ifStatement = extractIfStatement(body); final PsiMethodCallExpression methodCallExpression = extractAddCall(body, ifStatement); if (methodCallExpression != null) { final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); PsiClass qualifierClass = null; if (qualifierExpression instanceof PsiReferenceExpression) { if (ReferencesSearch.search(parameter, new LocalSearchScope(qualifierExpression)) .findFirst() != null) { return false; } final PsiElement resolve = ((PsiReferenceExpression) qualifierExpression).resolve(); if (resolve instanceof PsiVariable) { if (ReferencesSearch.search( resolve, new LocalSearchScope(methodCallExpression.getArgumentList())) .findFirst() != null) { return false; } } qualifierClass = PsiUtil.resolveClassInType(qualifierExpression.getType()); } else if (qualifierExpression == null) { final PsiClass enclosingClass = PsiTreeUtil.getParentOfType(body, PsiClass.class); if (PsiUtil.getEnclosingStaticElement(body, enclosingClass) == null) { qualifierClass = enclosingClass; } } if (qualifierClass != null && InheritanceUtil.isInheritor( qualifierClass, false, CommonClassNames.JAVA_UTIL_COLLECTION)) { while (ifStatement != null && PsiTreeUtil.isAncestor(body, ifStatement, false)) { final PsiExpression condition = ifStatement.getCondition(); if (condition != null && isConditionDependsOnUpdatedCollections(condition, qualifierExpression)) return false; ifStatement = PsiTreeUtil.getParentOfType(ifStatement, PsiIfStatement.class); } final PsiElement resolve = methodExpression.resolve(); if (resolve instanceof PsiMethod && "add".equals(((PsiMethod) resolve).getName()) && ((PsiMethod) resolve).getParameterList().getParametersCount() == 1) { final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions(); if (args.length == 1) { if (args[0] instanceof PsiCallExpression) { final PsiMethod method = ((PsiCallExpression) args[0]).resolveMethod(); return method != null && !method.hasTypeParameters() && !isThrowsCompatible(method); } return true; } } } } return false; }
private static PsiIfStatement extractIfStatement(PsiStatement body) { PsiIfStatement ifStmt = null; if (body instanceof PsiIfStatement) { ifStmt = (PsiIfStatement) body; } else if (body instanceof PsiBlockStatement) { final PsiStatement[] statements = ((PsiBlockStatement) body).getCodeBlock().getStatements(); if (statements.length == 1 && statements[0] instanceof PsiIfStatement) { ifStmt = (PsiIfStatement) statements[0]; } } if (ifStmt != null && ifStmt.getElseBranch() == null && ifStmt.getCondition() != null) { final PsiStatement thenBranch = ifStmt.getThenBranch(); if (thenBranch != null) { final PsiIfStatement deeperThen = extractIfStatement(thenBranch); return deeperThen != null ? deeperThen : ifStmt; } } return null; }
private static String createFiltersChainText( PsiStatement body, PsiParameter parameter, PsiIfStatement ifStatement) { final List<String> filters = new ArrayList<String>(); while (ifStatement != null && PsiTreeUtil.isAncestor(body, ifStatement, false)) { final PsiExpression condition = ifStatement.getCondition(); if (condition != null) { filters.add( ".filter(" + compoundLambdaOrMethodReference( parameter, condition, "java.util.function.Predicate", new PsiType[] {parameter.getType()}) + ")"); } ifStatement = PsiTreeUtil.getParentOfType(ifStatement, PsiIfStatement.class); } Collections.reverse(filters); return StringUtil.join(filters, ""); }
private static PsiMethodCallExpression extractAddCall( PsiStatement body, PsiIfStatement ifStatement) { if (ifStatement != null) { final PsiStatement thenBranch = ifStatement.getThenBranch(); return extractAddCall(thenBranch, null); } PsiExpressionStatement stmt = null; if (body instanceof PsiBlockStatement) { final PsiStatement[] statements = ((PsiBlockStatement) body).getCodeBlock().getStatements(); if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) { stmt = (PsiExpressionStatement) statements[0]; } } else if (body instanceof PsiExpressionStatement) { stmt = (PsiExpressionStatement) body; } if (stmt != null) { final PsiExpression expression = stmt.getExpression(); if (expression instanceof PsiMethodCallExpression) { return (PsiMethodCallExpression) expression; } } return null; }
@Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiForeachStatement foreachStatement = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiForeachStatement.class); if (foreachStatement != null) { if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement)) return; PsiStatement body = foreachStatement.getBody(); final PsiExpression iteratedValue = foreachStatement.getIteratedValue(); if (body != null && iteratedValue != null) { restoreComments(foreachStatement, body); final PsiParameter parameter = foreachStatement.getIterationParameter(); final PsiIfStatement ifStmt = extractIfStatement(body); StringBuilder buffer = new StringBuilder(getIteratedValueText(iteratedValue)); if (ifStmt != null) { final PsiStatement thenBranch = ifStmt.getThenBranch(); LOG.assertTrue(thenBranch != null); buffer.append(".stream()"); buffer.append(createFiltersChainText(body, parameter, ifStmt)); body = thenBranch; } buffer.append(".").append(getForEachMethodName()).append("("); final String functionalExpressionText = createForEachFunctionalExpressionText(project, body, parameter); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); PsiExpressionStatement callStatement = (PsiExpressionStatement) elementFactory.createStatementFromText( buffer.toString() + functionalExpressionText + ");", foreachStatement); callStatement = (PsiExpressionStatement) foreachStatement.replace(callStatement); final PsiExpressionList argumentList = ((PsiCallExpression) callStatement.getExpression()).getArgumentList(); LOG.assertTrue(argumentList != null, callStatement.getText()); final PsiExpression[] expressions = argumentList.getExpressions(); LOG.assertTrue(expressions.length == 1); if (expressions[0] instanceof PsiFunctionalExpression && ((PsiFunctionalExpression) expressions[0]).getFunctionalInterfaceType() == null) { callStatement = (PsiExpressionStatement) callStatement.replace( elementFactory.createStatementFromText( buffer.toString() + "(" + parameter.getText() + ") -> " + wrapInBlock(body) + ");", callStatement)); } simplifyRedundantCast(callStatement); CodeStyleManager.getInstance(project) .reformat( JavaCodeStyleManager.getInstance(project).shortenClassReferences(callStatement)); } } }