private static boolean forEachStatementsAreEquivalent( @NotNull PsiForeachStatement statement1, @NotNull PsiForeachStatement statement2) { final PsiExpression value1 = statement1.getIteratedValue(); final PsiExpression value2 = statement2.getIteratedValue(); if (!expressionsAreEquivalent(value1, value2)) { return false; } final PsiParameter parameter1 = statement1.getIterationParameter(); final PsiParameter parameter2 = statement1.getIterationParameter(); final String name1 = parameter1.getName(); final String name2 = parameter2.getName(); if (!name1.equals(name2)) { return false; } final PsiType type1 = parameter1.getType(); if (!type1.equals(parameter2.getType())) { return false; } final PsiStatement body1 = statement1.getBody(); final PsiStatement body2 = statement2.getBody(); return statementsAreEquivalent(body1, body2); }
@NotNull static ElementFilter getReferenceFilter(PsiElement element, boolean allowRecursion) { // throw foo if (psiElement() .withParent(psiElement(PsiReferenceExpression.class).withParent(PsiThrowStatement.class)) .accepts(element)) { return TrueFilter.INSTANCE; } if (psiElement() .inside( StandardPatterns.or( psiElement(PsiAnnotationParameterList.class), psiElement(PsiSwitchLabelStatement.class))) .accepts(element)) { return new ElementExtractorFilter( new AndFilter( new ClassFilter(PsiField.class), new ModifierFilter(PsiKeyword.STATIC, PsiKeyword.FINAL))); } final PsiForeachStatement foreach = PsiTreeUtil.getParentOfType(element, PsiForeachStatement.class); if (foreach != null && !PsiTreeUtil.isAncestor(foreach.getBody(), element, false)) { return new ElementExtractorFilter( new ElementFilter() { @Override public boolean isAcceptable(Object element, @Nullable PsiElement context) { return element != foreach.getIterationParameter(); } @Override public boolean isClassAcceptable(Class hintClass) { return true; } }); } if (!allowRecursion) { final ElementFilter filter = RecursionWeigher.recursionFilter(element); if (filter != null) { return new ElementExtractorFilter(filter); } } return TrueFilter.INSTANCE; }
@Override public void visitForeachStatement(PsiForeachStatement statement) { super.visitForeachStatement(statement); final PsiExpression iteratedValue = statement.getIteratedValue(); if (iteratedValue == null) { return; } final PsiType type = iteratedValue.getType(); if (!(type instanceof PsiArrayType)) { return; } final PsiArrayType arrayType = (PsiArrayType) type; final PsiType componentType = arrayType.getComponentType(); if (componentType instanceof PsiPrimitiveType) { return; } final PsiParameter parameter = statement.getIterationParameter(); final PsiStatement body = statement.getBody(); if (!bodyIsArrayToCollectionCopy(body, parameter, false)) { return; } registerStatementError(statement); }
@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; final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); PsiStatement body = foreachStatement.getBody(); final PsiExpression iteratedValue = foreachStatement.getIteratedValue(); if (body != null && iteratedValue != null) { final PsiParameter parameter = foreachStatement.getIterationParameter(); final PsiIfStatement ifStatement = extractIfStatement(body); final PsiMethodCallExpression methodCallExpression = extractAddCall(body, ifStatement); if (methodCallExpression == null) return; if (isAddAllCall(foreachStatement, body)) { restoreComments(foreachStatement, body); final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression(); final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() : ""; final String callText = StringUtil.getQualifiedName( qualifierText, "addAll(" + getIteratedValueText(iteratedValue) + ");"); PsiElement result = foreachStatement.replace( elementFactory.createStatementFromText(callText, foreachStatement)); reformatWhenNeeded(project, result); return; } final StringBuilder builder = new StringBuilder(getIteratedValueText(iteratedValue) + ".stream()"); builder.append(createFiltersChainText(body, parameter, ifStatement)); builder.append( createMapperFunctionalExpressionText( parameter, methodCallExpression.getArgumentList().getExpressions()[0])); builder.append(".collect(java.util.stream.Collectors."); PsiElement result = null; try { final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression(); if (qualifierExpression instanceof PsiReferenceExpression) { final PsiElement resolve = ((PsiReferenceExpression) qualifierExpression).resolve(); if (resolve instanceof PsiVariable) { if (resolve instanceof PsiLocalVariable && foreachStatement.equals( PsiTreeUtil.skipSiblingsForward( resolve.getParent(), PsiWhiteSpace.class))) { final PsiExpression initializer = ((PsiVariable) resolve).getInitializer(); if (initializer instanceof PsiNewExpression) { final PsiExpressionList argumentList = ((PsiNewExpression) initializer).getArgumentList(); if (argumentList != null && argumentList.getExpressions().length == 0) { restoreComments(foreachStatement, body); final String callText = builder.toString() + createInitializerReplacementText( ((PsiVariable) resolve).getType(), initializer) + ")"; result = initializer.replace( elementFactory.createExpressionFromText(callText, null)); simplifyRedundantCast(result); foreachStatement.delete(); return; } } } } } restoreComments(foreachStatement, body); final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() : ""; final String callText = StringUtil.getQualifiedName( qualifierText, "addAll(" + builder.toString() + "toList()));"); result = foreachStatement.replace( elementFactory.createStatementFromText(callText, foreachStatement)); simplifyRedundantCast(result); } finally { reformatWhenNeeded(project, result); } } } }
@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)); } } }