void (PsiForeachStatement statement, boolean array, String iteratedValueText, String indexText, StringBuilder newStatement) { newStatement.append("for(int "); newStatement.append(indexText); newStatement.append("=0;"); newStatement.append(indexText); newStatement.append('<'); newStatement.append(iteratedValueText); newStatement.append(array ? ".length;" : ".size();"); newStatement.append(indexText); newStatement.append("++){"); } @Nullable private static String getVariableName(PsiExpression expression) { if (expression instanceof PsiMethodCallExpression methodCallExpression) { final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final String name = methodExpression.getReferenceName(); if (name == null) { return null; } if (name.startsWith("to") && name.length() > 2) { return StringUtil.decapitalize(name.substring(2)); } else if (name.startsWith("get") && name.length() > 3) { return StringUtil.decapitalize(name.substring(3)); } else { return name; } } else if (expression instanceof PsiTypeCastExpression castExpression) { final PsiExpression operand = castExpression.getOperand(); return getVariableName(operand); } else if (expression instanceof PsiArrayAccessExpression arrayAccessExpression) { final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression(); final String name = getVariableName(arrayExpression); return (name == null) ? null : StringUtil.unpluralize(name); } else if (expression instanceof PsiParenthesizedExpression parenthesizedExpression) { final PsiExpression innerExpression = parenthesizedExpression.getExpression(); return getVariableName(innerExpression); } else if (expression instanceof PsiJavaCodeReferenceElement referenceElement) { final String referenceName = referenceElement.getReferenceName(); if (referenceName == null) { return expression.getText(); } return referenceName; } return null; } private static PsiElement getReferenceToIterate(PsiExpression expression, PsiElement context) { if (expression instanceof PsiMethodCallExpression || expression instanceof PsiTypeCastExpression || expression instanceof PsiArrayAccessExpression || expression instanceof PsiNewExpression) { final String variableName = getVariableName(expression); return createVariable(variableName, expression, context); } else if (expression instanceof PsiParenthesizedExpression parenthesizedExpression) { final PsiExpression innerExpression = parenthesizedExpression.getExpression(); return getReferenceToIterate(innerExpression, context); } else if (expression instanceof PsiJavaCodeReferenceElement referenceElement) { final String variableName = getVariableName(expression); if (referenceElement.isQualified()) { return createVariable(variableName, expression, context); } final PsiElement target = referenceElement.resolve(); if (target instanceof PsiVariable) { // maybe should not do this for local variables outside of // anonymous classes return referenceElement; } return createVariable(variableName, expression, context); } return expression; } private static PsiVariable createVariable(String variableNameRoot, PsiExpression iteratedValue, PsiElement context) { final String variableName = createVariableName(variableNameRoot, iteratedValue); final Project project = context.getProject(); final PsiType iteratedValueType = iteratedValue.getType(); assert iteratedValueType != null; final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); final PsiDeclarationStatement declarationStatement = elementFactory.createVariableDeclarationStatement(variableName, iteratedValueType, iteratedValue); return (PsiVariable)declarationStatement.getDeclaredElements()[0]; } public static String createVariableName(@Nullable String baseName, @NotNull PsiExpression assignedExpression) { return new VariableNameGenerator(assignedExpression, VariableKind.LOCAL_VARIABLE).byName(baseName).byExpression(assignedExpression) .byType(assignedExpression.getType()).generate(true); } public static String createVariableName(@Nullable String baseName, @NotNull PsiType type, @NotNull PsiElement context) { return new VariableNameGenerator(context, VariableKind.LOCAL_VARIABLE).byName(baseName).byType(type).generate(true); } }