private static boolean binaryExpressionsAreEquivalent( @NotNull PsiBinaryExpression binaryExp1, @NotNull PsiBinaryExpression binaryExp2) { final IElementType tokenType1 = binaryExp1.getOperationTokenType(); if (!tokenType1.equals(binaryExp2.getOperationTokenType())) { return false; } final PsiExpression lhs1 = binaryExp1.getLOperand(); final PsiExpression lhs2 = binaryExp2.getLOperand(); final PsiExpression rhs1 = binaryExp1.getROperand(); final PsiExpression rhs2 = binaryExp2.getROperand(); return expressionsAreEquivalent(lhs1, lhs2) && expressionsAreEquivalent(rhs1, rhs2); }
protected static void replaceExpressionWithNegatedExpression( @NotNull PsiExpression newExpression, @NotNull PsiExpression expression) { final Project project = expression.getProject(); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); PsiExpression expressionToReplace = expression; final String newExpressionText = newExpression.getText(); final String expString; if (BoolUtils.isNegated(expression)) { expressionToReplace = BoolUtils.findNegation(expression); expString = newExpressionText; } else if (ComparisonUtils.isComparison(newExpression)) { final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) newExpression; final String negatedComparison = ComparisonUtils.getNegatedComparison(binaryExpression.getOperationTokenType()); final PsiExpression lhs = binaryExpression.getLOperand(); final PsiExpression rhs = binaryExpression.getROperand(); assert rhs != null; expString = lhs.getText() + negatedComparison + rhs.getText(); } else { if (ParenthesesUtils.getPrecedence(newExpression) > ParenthesesUtils.PREFIX_PRECEDENCE) { expString = "!(" + newExpressionText + ')'; } else { expString = '!' + newExpressionText; } } final PsiExpression newCall = factory.createExpressionFromText(expString, expression); assert expressionToReplace != null; final PsiElement insertedElement = expressionToReplace.replace(newCall); final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); codeStyleManager.reformat(insertedElement); }
private boolean checkCondition(@Nullable PsiExpression condition, @Nullable PsiStatement body) { if (body == null) { return false; } if (!(condition instanceof PsiBinaryExpression)) { return false; } final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) condition; final IElementType tokenType = binaryExpression.getOperationTokenType(); final PsiExpression lhs = binaryExpression.getLOperand(); final PsiExpression rhs = binaryExpression.getROperand(); if (JavaTokenType.ANDAND == tokenType) { return checkCondition(lhs, body) || checkCondition(rhs, body); } if (JavaTokenType.EQEQ != tokenType) { return false; } if (rhs == null) { return false; } if (PsiUtil.isConstantExpression(lhs)) { return checkConstantValueVariableUse(rhs, lhs, body); } else if (PsiUtil.isConstantExpression(rhs)) { return checkConstantValueVariableUse(lhs, rhs, body); } return false; }
private static String buildToOffsetText(PsiExpression expression, boolean plusOne) { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return null; } if (!plusOne) { return expression.getText(); } if (expression instanceof PsiBinaryExpression) { final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) expression; final IElementType tokenType = binaryExpression.getOperationTokenType(); if (tokenType == JavaTokenType.MINUS) { final PsiExpression rhs = binaryExpression.getROperand(); if (ExpressionUtils.isOne(rhs)) { return binaryExpression.getLOperand().getText(); } } } final int precedence = ParenthesesUtils.getPrecedence(expression); if (precedence > ParenthesesUtils.ADDITIVE_PRECEDENCE) { return '(' + expression.getText() + ")+1"; } else { return expression.getText() + "+1"; } }
@Override public void visitBinaryExpression(PsiBinaryExpression expression) { final IElementType tokenType = expression.getOperationTokenType(); if (JavaTokenType.OROR != tokenType) { return; } final PsiExpression lhs = expression.getLOperand(); final PsiExpression rhs = expression.getROperand(); final Pair<PsiReferenceExpression, PsiExpression> pair1 = getReferenceExpressionPair(lhs); final Pair<PsiReferenceExpression, PsiExpression> pair2 = getReferenceExpressionPair(rhs); if (pair1 == null || pair2 == null) { return; } final PsiExpression expression1 = pair1.getSecond(); final PsiExpression expression2 = pair2.getSecond(); if (expression1 == null || expression2 == null) { return; } final Project project = expression1.getProject(); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiConstantEvaluationHelper constantEvaluationHelper = psiFacade.getConstantEvaluationHelper(); final Object constant1 = constantEvaluationHelper.computeConstantExpression(expression1); final Object constant2 = constantEvaluationHelper.computeConstantExpression(expression2); if (constant1 == null || constant2 == null || constant1 == constant2) { return; } final PsiReferenceExpression referenceExpression1 = pair1.getFirst(); final PsiReferenceExpression referenceExpression2 = pair2.getFirst(); if (referenceExpression1.resolve() == referenceExpression2.resolve()) { registerError(expression); } }
@NotNull private static PsiExpression psiToClsExpression( final PsiExpression expr, @Nullable final ClsElementImpl parent) { if (expr instanceof PsiLiteralExpression) { return new ClsLiteralExpressionImpl( parent, expr.getText(), expr.getType(), ((PsiLiteralExpression) expr).getValue()); } else if (expr instanceof PsiPrefixExpression) { final PsiPrefixExpression prefixExpr = (PsiPrefixExpression) expr; final ClsJavaTokenImpl operation = new ClsJavaTokenImpl( null, prefixExpr.getOperationTokenType(), prefixExpr.getOperationSign().getText()); final ClsLiteralExpressionImpl literal = (ClsLiteralExpressionImpl) psiToClsExpression(prefixExpr.getOperand(), null); return new ClsPrefixExpressionImpl(parent, operation, literal); } else if (expr instanceof PsiClassObjectAccessExpression) { final String canonicalClassText = ((PsiClassObjectAccessExpression) expr).getOperand().getType().getCanonicalText(); return new ClsClassObjectAccessExpressionImpl(parent, canonicalClassText); } else if (expr instanceof PsiReferenceExpression) { return new ClsReferenceExpressionImpl(parent, (PsiReferenceExpression) expr); } else if (expr instanceof PsiBinaryExpression) { final PsiBinaryExpression binaryExpr = (PsiBinaryExpression) expr; final PsiExpression lOperand = psiToClsExpression(binaryExpr.getLOperand(), null); final ClsJavaTokenImpl operation = new ClsJavaTokenImpl( null, binaryExpr.getOperationTokenType(), binaryExpr.getOperationSign().getText()); final PsiExpression rOperand = psiToClsExpression(binaryExpr.getROperand(), null); if (lOperand instanceof ClsLiteralExpressionImpl) { return new ClsBinaryExpressionImpl( parent, (ClsLiteralExpressionImpl) lOperand, operation, (ClsLiteralExpressionImpl) rOperand); } else if (lOperand instanceof ClsPrefixExpressionImpl) { return new ClsBinaryExpressionImpl( parent, (ClsPrefixExpressionImpl) lOperand, operation, (ClsLiteralExpressionImpl) rOperand); } } else { final PsiConstantEvaluationHelper evaluator = JavaPsiFacade.getInstance(expr.getProject()).getConstantEvaluationHelper(); final Object value = evaluator.computeConstantExpression(expr); if (value != null) { return new ClsLiteralExpressionImpl(parent, expr.getText(), expr.getType(), value); } } LOG.error("Unable to compute expression value: " + expr); return null; }
@Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiBinaryExpression expression = (PsiBinaryExpression) descriptor.getPsiElement(); final PsiExpression rhs = expression.getROperand(); if (rhs == null) { return; } final String flippedComparison = ComparisonUtils.getFlippedComparison(expression.getOperationTokenType()); if (flippedComparison == null) { return; } final PsiExpression lhs = expression.getLOperand(); final String rhsText = rhs.getText(); final String lhsText = lhs.getText(); replaceExpression(expression, rhsText + ' ' + flippedComparison + ' ' + lhsText); }
@Nullable private static Pair<PsiReferenceExpression, PsiExpression> getReferenceExpressionPair( PsiExpression expression) { if (!(expression instanceof PsiBinaryExpression)) { return null; } final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) expression; final IElementType tokenType = binaryExpression.getOperationTokenType(); if (JavaTokenType.NE != tokenType) { return null; } final PsiExpression lhs = binaryExpression.getLOperand(); final PsiExpression rhs = binaryExpression.getROperand(); if (lhs instanceof PsiReferenceExpression) { final PsiReferenceExpression lref = (PsiReferenceExpression) lhs; return new Pair(lref, rhs); } else if (rhs instanceof PsiReferenceExpression) { final PsiReferenceExpression rref = (PsiReferenceExpression) rhs; return new Pair(rref, lhs); } return null; }
@Nullable private String createListIterationText(@NotNull PsiForStatement forStatement) { final PsiBinaryExpression condition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(forStatement.getCondition()); if (condition == null) { return null; } final PsiExpression lhs = ParenthesesUtils.stripParentheses(condition.getLOperand()); if (lhs == null) { return null; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(condition.getROperand()); if (rhs == null) { return null; } final IElementType tokenType = condition.getOperationTokenType(); final String indexName; PsiExpression collectionSize; if (JavaTokenType.LT.equals(tokenType)) { indexName = lhs.getText(); collectionSize = rhs; } else if (JavaTokenType.GT.equals(tokenType)) { indexName = rhs.getText(); collectionSize = lhs; } else { return null; } if (collectionSize instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) collectionSize; final PsiElement target = referenceExpression.resolve(); if (target instanceof PsiVariable) { final PsiVariable variable = (PsiVariable) target; collectionSize = ParenthesesUtils.stripParentheses(variable.getInitializer()); } } if (!(collectionSize instanceof PsiMethodCallExpression)) { return null; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) ParenthesesUtils.stripParentheses(collectionSize); if (methodCallExpression == null) { return null; } final PsiReferenceExpression listLengthExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = ParenthesesUtils.stripParentheses(listLengthExpression.getQualifierExpression()); final PsiReferenceExpression listReference; if (qualifier instanceof PsiReferenceExpression) { listReference = (PsiReferenceExpression) qualifier; } else { listReference = null; } PsiType parameterType; if (listReference == null) { parameterType = extractListTypeFromContainingClass(forStatement); } else { final PsiType type = listReference.getType(); if (type == null) { return null; } parameterType = extractContentTypeFromType(type); } if (parameterType == null) { parameterType = TypeUtils.getObjectType(forStatement); } final String typeString = parameterType.getCanonicalText(); final PsiVariable listVariable; if (listReference == null) { listVariable = null; } else { final PsiElement target = listReference.resolve(); if (!(target instanceof PsiVariable)) { return null; } listVariable = (PsiVariable) target; } final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final boolean isDeclaration = isListElementDeclaration(firstStatement, listVariable, indexName, parameterType); final String contentVariableName; @NonNls final String finalString; final PsiStatement statementToSkip; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } else { final String collectionName; if (listReference == null) { collectionName = null; } else { collectionName = listReference.getReferenceName(); } contentVariableName = createNewVariableName(forStatement, parameterType, collectionName); finalString = ""; statementToSkip = null; } @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(typeString); out.append(' '); out.append(contentVariableName); out.append(": "); @NonNls final String listName; if (listReference == null) { listName = "this"; } else { listName = listReference.getText(); } out.append(listName); out.append(')'); if (body != null) { replaceCollectionGetAccess( body, contentVariableName, listVariable, indexName, statementToSkip, out); } return out.toString(); }
@Nullable private String createArrayIterationText(@NotNull PsiForStatement forStatement) { final PsiExpression condition = forStatement.getCondition(); final PsiBinaryExpression strippedCondition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(condition); if (strippedCondition == null) { return null; } final PsiExpression lhs = ParenthesesUtils.stripParentheses(strippedCondition.getLOperand()); if (lhs == null) { return null; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(strippedCondition.getROperand()); if (rhs == null) { return null; } final IElementType tokenType = strippedCondition.getOperationTokenType(); final PsiReferenceExpression arrayLengthExpression; final String indexName; if (tokenType.equals(JavaTokenType.LT)) { arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(rhs); indexName = lhs.getText(); } else if (tokenType.equals(JavaTokenType.GT)) { arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(lhs); indexName = rhs.getText(); } else { return null; } if (arrayLengthExpression == null) { return null; } PsiReferenceExpression arrayReference = (PsiReferenceExpression) arrayLengthExpression.getQualifierExpression(); if (arrayReference == null) { final PsiElement target = arrayLengthExpression.resolve(); if (!(target instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) target; final PsiExpression initializer = variable.getInitializer(); if (!(initializer instanceof PsiReferenceExpression)) { return null; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) initializer; arrayReference = (PsiReferenceExpression) referenceExpression.getQualifierExpression(); if (arrayReference == null) { return null; } } final PsiType type = arrayReference.getType(); if (!(type instanceof PsiArrayType)) { return null; } final PsiArrayType arrayType = (PsiArrayType) type; final PsiType componentType = arrayType.getComponentType(); final String typeText = componentType.getCanonicalText(); final PsiElement target = arrayReference.resolve(); if (!(target instanceof PsiVariable)) { return null; } final PsiVariable arrayVariable = (PsiVariable) target; final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final boolean isDeclaration = isArrayElementDeclaration(firstStatement, arrayVariable, indexName); final String contentVariableName; @NonNls final String finalString; final PsiStatement statementToSkip; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; if (VariableAccessUtils.variableIsAssigned(variable, forStatement)) { final String collectionName = arrayReference.getReferenceName(); contentVariableName = createNewVariableName(forStatement, componentType, collectionName); final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } else { contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } } else { final String collectionName = arrayReference.getReferenceName(); contentVariableName = createNewVariableName(forStatement, componentType, collectionName); final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(typeText); out.append(' '); out.append(contentVariableName); out.append(": "); final String arrayName = arrayReference.getText(); out.append(arrayName); out.append(')'); if (body != null) { replaceArrayAccess( body, contentVariableName, arrayVariable, indexName, statementToSkip, out); } return out.toString(); }
@Nullable private static String getCollectionsAddAllText(PsiForStatement forStatement) throws IncorrectOperationException { final PsiExpression expression = forStatement.getCondition(); final PsiBinaryExpression condition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(expression); if (condition == null) { return null; } final PsiStatement initialization = forStatement.getInitialization(); if (initialization == null) { return null; } if (!(initialization instanceof PsiDeclarationStatement)) { return null; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return null; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiLocalVariable)) { return null; } final PsiLocalVariable variable = (PsiLocalVariable) declaredElement; final String collectionText = buildCollectionText(forStatement); final PsiArrayAccessExpression arrayAccessExpression = getArrayAccessExpression(forStatement); if (arrayAccessExpression == null) { return null; } final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression(); final String arrayText = arrayExpression.getText(); final PsiExpression indexExpression = arrayAccessExpression.getIndexExpression(); final String fromOffsetText = buildFromOffsetText(indexExpression, variable); if (fromOffsetText == null) { return null; } final PsiExpression limit; final IElementType tokenType = condition.getOperationTokenType(); if (tokenType == JavaTokenType.LT || tokenType == JavaTokenType.LE) { limit = condition.getROperand(); } else { limit = condition.getLOperand(); } @NonNls final String toOffsetText = buildToOffsetText(limit, tokenType == JavaTokenType.LE || tokenType == JavaTokenType.GE); if (toOffsetText == null) { return null; } if (fromOffsetText.equals("0") && toOffsetText.equals(arrayText + ".length") && PsiUtil.isLanguageLevel5OrHigher(forStatement)) { return "java.util.Collections.addAll(" + collectionText + ',' + arrayText + ");"; } else { @NonNls final StringBuilder buffer = new StringBuilder(); buffer.append(collectionText); buffer.append('.'); buffer.append("addAll(java.util.Arrays.asList("); buffer.append(arrayText); buffer.append(')'); if (!fromOffsetText.equals("0") || !toOffsetText.equals(arrayText + ".length")) { buffer.append(".subList("); buffer.append(fromOffsetText); buffer.append(", "); buffer.append(toOffsetText); buffer.append(')'); } buffer.append(");"); return buffer.toString(); } }
@Override public void visitBinaryExpression(PsiBinaryExpression expression) { super.visitBinaryExpression(expression); final IElementType operationTokenType = expression.getOperationTokenType(); final PsiExpression lhs = ParenthesesUtils.stripParentheses(expression.getLOperand()); final PsiExpression rhs = ParenthesesUtils.stripParentheses(expression.getROperand()); final PsiBinaryExpression binaryExpression; final PsiExpression possibleInstanceofExpression; if (operationTokenType.equals(JavaTokenType.ANDAND)) { if (lhs instanceof PsiBinaryExpression) { binaryExpression = (PsiBinaryExpression) lhs; possibleInstanceofExpression = rhs; } else if (rhs instanceof PsiBinaryExpression) { binaryExpression = (PsiBinaryExpression) rhs; possibleInstanceofExpression = lhs; } else { return; } final IElementType tokenType = binaryExpression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.NE)) { return; } } else if (operationTokenType.equals(JavaTokenType.OROR)) { if (lhs instanceof PsiBinaryExpression && rhs instanceof PsiPrefixExpression) { final PsiPrefixExpression prefixExpression = (PsiPrefixExpression) rhs; final IElementType prefixTokenType = prefixExpression.getOperationTokenType(); if (!JavaTokenType.EXCL.equals(prefixTokenType)) { return; } binaryExpression = (PsiBinaryExpression) lhs; possibleInstanceofExpression = ParenthesesUtils.stripParentheses(prefixExpression.getOperand()); } else if (rhs instanceof PsiBinaryExpression && lhs instanceof PsiPrefixExpression) { final PsiPrefixExpression prefixExpression = (PsiPrefixExpression) lhs; final IElementType prefixTokenType = prefixExpression.getOperationTokenType(); if (!JavaTokenType.EXCL.equals(prefixTokenType)) { return; } binaryExpression = (PsiBinaryExpression) rhs; possibleInstanceofExpression = ParenthesesUtils.stripParentheses(prefixExpression.getOperand()); } else { return; } final IElementType tokenType = binaryExpression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.EQEQ)) { return; } } else { return; } final PsiReferenceExpression referenceExpression1 = getReferenceFromNullCheck(binaryExpression); if (referenceExpression1 == null) { return; } final PsiReferenceExpression referenceExpression2 = getReferenceFromInstanceofExpression(possibleInstanceofExpression); if (!referencesEqual(referenceExpression1, referenceExpression2)) { return; } registerError(binaryExpression); }