static boolean isComplexArrayExpression(PsiExpression expression) { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return false; } if (expression instanceof PsiNewExpression) { final PsiNewExpression newExpression = (PsiNewExpression) expression; final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer(); return isComplexArrayExpression(arrayInitializer); } else if (expression instanceof PsiArrayInitializerExpression) { final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression) expression; for (PsiExpression initializer : arrayInitializerExpression.getInitializers()) { if (isComplexArrayExpression(initializer)) { return true; } } return false; } else if (expression instanceof PsiReferenceExpression) { return expression.getType() instanceof PsiArrayType; } else if (expression instanceof PsiArrayAccessExpression) { return true; } else if (expression instanceof PsiTypeCastExpression) { final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression) expression; return isComplexArrayExpression(typeCastExpression.getOperand()); } else if (expression instanceof PsiConditionalExpression) { final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression) expression; return isComplexArrayExpression(conditionalExpression.getThenExpression()) || isComplexArrayExpression(conditionalExpression.getElseExpression()); } else if (expression instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; final PsiMethod method = methodCallExpression.resolveMethod(); if (method == null) { return true; } if (CloneUtils.isClone(method)) { return false; } @NonNls final String name = method.getName(); if ("copyOf".equals(name) || "copyOfRange".equals(name)) { final PsiClass aClass = method.getContainingClass(); if (aClass != null && CommonClassNames.JAVA_UTIL_ARRAYS.equals(aClass.getQualifiedName())) { return false; } } else if ("toArray".equals(name) && InheritanceUtil.isInheritor(method.getContainingClass(), "java.util.Collection")) { return false; } return true; } return true; }
private static void removeParensFromConditionalExpression( @NotNull PsiConditionalExpression conditionalExpression, boolean ignoreClarifyingParentheses) { final PsiExpression condition = conditionalExpression.getCondition(); removeParentheses(condition, ignoreClarifyingParentheses); final PsiExpression thenBranch = conditionalExpression.getThenExpression(); if (thenBranch != null) { removeParentheses(thenBranch, ignoreClarifyingParentheses); } final PsiExpression elseBranch = conditionalExpression.getElseExpression(); if (elseBranch != null) { removeParentheses(elseBranch, ignoreClarifyingParentheses); } }
static PsiExpression createCastExpression( PsiExpression originalExpression, Project project, PsiType type) throws IncorrectOperationException { // remove nested casts PsiElement element = PsiUtil.deparenthesizeExpression(originalExpression); PsiElementFactory factory = JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory(); PsiTypeCastExpression typeCast = (PsiTypeCastExpression) factory.createExpressionFromText("(Type)value", null); typeCast = (PsiTypeCastExpression) CodeStyleManager.getInstance(project).reformat(typeCast); typeCast.getCastType().replace(factory.createTypeElement(type)); if (element instanceof PsiConditionalExpression) { // we'd better cast one branch of ternary expression if we could PsiConditionalExpression expression = (PsiConditionalExpression) element.copy(); PsiExpression thenE = expression.getThenExpression(); PsiExpression elseE = expression.getElseExpression(); PsiType thenType = thenE == null ? null : thenE.getType(); PsiType elseType = elseE == null ? null : elseE.getType(); if (elseType != null && thenType != null) { boolean replaceThen = !TypeConversionUtil.isAssignable(type, thenType); boolean replaceElse = !TypeConversionUtil.isAssignable(type, elseType); if (replaceThen != replaceElse) { if (replaceThen) { typeCast.getOperand().replace(thenE); thenE.replace(typeCast); } else { typeCast.getOperand().replace(elseE); elseE.replace(typeCast); } return expression; } } } typeCast.getOperand().replace(element); return typeCast; }
private static boolean conditionalExpressionsAreEquivalent( @NotNull PsiConditionalExpression condExp1, @NotNull PsiConditionalExpression condExp2) { final PsiExpression condition1 = condExp1.getCondition(); final PsiExpression condition2 = condExp2.getCondition(); final PsiExpression thenExpression1 = condExp1.getThenExpression(); final PsiExpression thenExpression2 = condExp2.getThenExpression(); final PsiExpression elseExpression1 = condExp1.getElseExpression(); final PsiExpression elseExpression2 = condExp2.getElseExpression(); return expressionsAreEquivalent(condition1, condition2) && expressionsAreEquivalent(thenExpression1, thenExpression2) && expressionsAreEquivalent(elseExpression1, elseExpression2); }
private boolean checkCondition( @Nullable PsiExpression condition, @NotNull PsiStatement context, List<PsiExpression> notUpdated) { if (condition == null) { return false; } if (PsiUtil.isConstantExpression(condition) || PsiKeyword.NULL.equals(condition.getText())) { return true; } if (condition instanceof PsiInstanceOfExpression) { final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression) condition; final PsiExpression operand = instanceOfExpression.getOperand(); return checkCondition(operand, context, notUpdated); } else if (condition instanceof PsiParenthesizedExpression) { // catch stuff like "while ((x)) { ... }" final PsiExpression expression = ((PsiParenthesizedExpression) condition).getExpression(); return checkCondition(expression, context, notUpdated); } else if (condition instanceof PsiPolyadicExpression) { // while (value != x) { ... } // while (value != (x + y)) { ... } // while (b1 && b2) { ... } final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression) condition; for (PsiExpression operand : polyadicExpression.getOperands()) { if (!checkCondition(operand, context, notUpdated)) { return false; } } return true; } else if (condition instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) condition; final PsiElement element = referenceExpression.resolve(); if (element instanceof PsiField) { final PsiField field = (PsiField) element; final PsiType type = field.getType(); if (field.hasModifierProperty(PsiModifier.FINAL) && type.getArrayDimensions() == 0) { if (field.hasModifierProperty(PsiModifier.STATIC)) { return true; } final PsiExpression qualifier = referenceExpression.getQualifierExpression(); if (qualifier == null) { return true; } else if (checkCondition(qualifier, context, notUpdated)) { return true; } } } else if (element instanceof PsiVariable) { final PsiVariable variable = (PsiVariable) element; if (variable.hasModifierProperty(PsiModifier.FINAL)) { // final variables cannot be updated, don't bother to // flag them return true; } else if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { if (!VariableAccessUtils.variableIsAssigned(variable, context)) { notUpdated.add(referenceExpression); return true; } } } } else if (condition instanceof PsiPrefixExpression) { final PsiPrefixExpression prefixExpression = (PsiPrefixExpression) condition; final IElementType tokenType = prefixExpression.getOperationTokenType(); if (JavaTokenType.EXCL.equals(tokenType) || JavaTokenType.PLUS.equals(tokenType) || JavaTokenType.MINUS.equals(tokenType)) { final PsiExpression operand = prefixExpression.getOperand(); return checkCondition(operand, context, notUpdated); } } else if (condition instanceof PsiArrayAccessExpression) { // Actually the contents of the array could change nevertheless // if it is accessed through a different reference like this: // int[] local_ints = new int[]{1, 2}; // int[] other_ints = local_ints; // while (local_ints[0] > 0) { other_ints[0]--; } // // Keep this check? final PsiArrayAccessExpression accessExpression = (PsiArrayAccessExpression) condition; final PsiExpression indexExpression = accessExpression.getIndexExpression(); return checkCondition(indexExpression, context, notUpdated) && checkCondition(accessExpression.getArrayExpression(), context, notUpdated); } else if (condition instanceof PsiConditionalExpression) { final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression) condition; final PsiExpression thenExpression = conditionalExpression.getThenExpression(); final PsiExpression elseExpression = conditionalExpression.getElseExpression(); if (thenExpression == null || elseExpression == null) { return false; } return checkCondition(conditionalExpression.getCondition(), context, notUpdated) && checkCondition(thenExpression, context, notUpdated) && checkCondition(elseExpression, context, notUpdated); } else if (condition instanceof PsiThisExpression) { return true; } else if (condition instanceof PsiMethodCallExpression && !ignoreIterators) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) condition; if (!IteratorUtils.isCallToHasNext(methodCallExpression)) { return false; } final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); if (qualifierExpression instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) qualifierExpression; final PsiElement element = referenceExpression.resolve(); if (!(element instanceof PsiVariable)) { return false; } final PsiVariable variable = (PsiVariable) element; if (!IteratorUtils.containsCallToScannerNext(context, variable, true)) { notUpdated.add(qualifierExpression); return true; } } else { if (!IteratorUtils.containsCallToScannerNext(context, null, true)) { notUpdated.add(methodCallExpression); return true; } } } return false; }
public static boolean areParenthesesNeeded( PsiExpression expression, PsiExpression parentExpression, boolean ignoreClarifyingParentheses) { if (parentExpression instanceof PsiParenthesizedExpression || parentExpression instanceof PsiArrayInitializerExpression) { return false; } final int parentPrecedence = getPrecedence(parentExpression); final int childPrecedence = getPrecedence(expression); if (parentPrecedence > childPrecedence) { if (ignoreClarifyingParentheses) { if (expression instanceof PsiPolyadicExpression) { if (parentExpression instanceof PsiPolyadicExpression || parentExpression instanceof PsiConditionalExpression || parentExpression instanceof PsiInstanceOfExpression) { return true; } } else if (expression instanceof PsiInstanceOfExpression) { return true; } } return false; } if (parentExpression instanceof PsiPolyadicExpression && expression instanceof PsiPolyadicExpression) { final PsiPolyadicExpression parentPolyadicExpression = (PsiPolyadicExpression) parentExpression; final PsiType parentType = parentPolyadicExpression.getType(); if (parentType == null) { return true; } final PsiPolyadicExpression childPolyadicExpression = (PsiPolyadicExpression) expression; final PsiType childType = childPolyadicExpression.getType(); if (!parentType.equals(childType)) { return true; } if (childType.equalsToText(CommonClassNames.JAVA_LANG_STRING) && !PsiTreeUtil.isAncestor( parentPolyadicExpression.getOperands()[0], childPolyadicExpression, true)) { final PsiExpression[] operands = childPolyadicExpression.getOperands(); for (PsiExpression operand : operands) { if (!childType.equals(operand.getType())) { return true; } } } else if (childType.equals(PsiType.BOOLEAN)) { final PsiExpression[] operands = childPolyadicExpression.getOperands(); for (PsiExpression operand : operands) { if (!PsiType.BOOLEAN.equals(operand.getType())) { return true; } } } final IElementType parentOperator = parentPolyadicExpression.getOperationTokenType(); final IElementType childOperator = childPolyadicExpression.getOperationTokenType(); if (ignoreClarifyingParentheses) { if (!childOperator.equals(parentOperator)) { return true; } } final PsiExpression[] parentOperands = parentPolyadicExpression.getOperands(); if (!PsiTreeUtil.isAncestor(parentOperands[0], expression, false)) { if (!isAssociativeOperation(parentPolyadicExpression) || JavaTokenType.DIV == childOperator || JavaTokenType.PERC == childOperator) { return true; } } } else if (parentExpression instanceof PsiConditionalExpression && expression instanceof PsiConditionalExpression) { final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression) parentExpression; final PsiExpression condition = conditionalExpression.getCondition(); return PsiTreeUtil.isAncestor(condition, expression, true); } return parentPrecedence < childPrecedence; }
private static void replaceConditionalWithIf(PsiConditionalExpression expression) throws IncorrectOperationException { final PsiStatement statement = PsiTreeUtil.getParentOfType(expression, PsiStatement.class); if (statement == null) { return; } final PsiVariable variable; if (statement instanceof PsiDeclarationStatement) { variable = PsiTreeUtil.getParentOfType(expression, PsiVariable.class); } else { variable = null; } final PsiExpression thenExpression = expression.getThenExpression(); final PsiExpression elseExpression = expression.getElseExpression(); final PsiExpression condition = expression.getCondition(); final PsiExpression strippedCondition = ParenthesesUtils.stripParentheses(condition); final StringBuilder newStatement = new StringBuilder(); newStatement.append("if("); if (strippedCondition != null) { newStatement.append(strippedCondition.getText()); } newStatement.append(')'); if (variable != null) { final String name = variable.getName(); newStatement.append(name); newStatement.append('='); final PsiExpression initializer = variable.getInitializer(); if (initializer == null) { return; } appendElementTextWithoutParentheses(initializer, expression, thenExpression, newStatement); newStatement.append("; else "); newStatement.append(name); newStatement.append('='); appendElementTextWithoutParentheses(initializer, expression, elseExpression, newStatement); newStatement.append(';'); initializer.delete(); final PsiManager manager = statement.getManager(); final Project project = manager.getProject(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final PsiElementFactory factory = facade.getElementFactory(); final PsiStatement ifStatement = factory.createStatementFromText(newStatement.toString(), statement); final PsiElement parent = statement.getParent(); final PsiElement addedElement = parent.addAfter(ifStatement, statement); final CodeStyleManager styleManager = CodeStyleManager.getInstance(manager.getProject()); styleManager.reformat(addedElement); } else { final boolean addBraces = PsiTreeUtil.getParentOfType(expression, PsiIfStatement.class, true, PsiStatement.class) != null; if (addBraces || thenExpression == null) { newStatement.append('{'); } appendElementTextWithoutParentheses(statement, expression, thenExpression, newStatement); if (addBraces) { newStatement.append("} else {"); } else { if (thenExpression == null) { newStatement.append('}'); } newStatement.append(" else "); if (elseExpression == null) { newStatement.append('{'); } } appendElementTextWithoutParentheses(statement, expression, elseExpression, newStatement); if (addBraces || elseExpression == null) { newStatement.append('}'); } replaceStatement(newStatement.toString(), statement); } }