IDEADEV-35007 (x -= y + z is converted incorrectly)
[fedora-idea.git] / plugins / IntentionPowerPak / src / com / siyeh / ipp / opassign / ReplaceOperatorAssignmentWithAssignmentIntention.java
blob872ce7470d837f11a33b836b33e8aa8e224cefaa
1 /*
2 * Copyright 2007-2009 Bas Leijdekkers
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.siyeh.ipp.opassign;
18 import com.intellij.psi.*;
19 import com.intellij.psi.tree.IElementType;
20 import com.intellij.util.IncorrectOperationException;
21 import com.siyeh.IntentionPowerPackBundle;
22 import com.siyeh.ipp.base.MutablyNamedIntention;
23 import com.siyeh.ipp.base.PsiElementPredicate;
24 import com.siyeh.ipp.psiutils.ParenthesesUtils;
25 import org.jetbrains.annotations.NotNull;
27 import java.util.Map;
28 import java.util.HashMap;
30 public class ReplaceOperatorAssignmentWithAssignmentIntention
31 extends MutablyNamedIntention {
33 private static final Map<IElementType, IElementType> tokenMap = new HashMap();
34 static {
35 tokenMap.put(JavaTokenType.PLUSEQ, JavaTokenType.PLUS);
36 tokenMap.put(JavaTokenType.MINUSEQ, JavaTokenType.MINUS);
37 tokenMap.put(JavaTokenType.ASTERISKEQ, JavaTokenType.ASTERISK);
38 tokenMap.put(JavaTokenType.DIVEQ, JavaTokenType.DIV);
39 tokenMap.put(JavaTokenType.ANDEQ, JavaTokenType.AND);
40 tokenMap.put(JavaTokenType.OREQ, JavaTokenType.OR);
41 tokenMap.put(JavaTokenType.XOREQ, JavaTokenType.XOR);
42 tokenMap.put(JavaTokenType.PERCEQ, JavaTokenType.PERC);
43 tokenMap.put(JavaTokenType.LTLTEQ, JavaTokenType.LTLT);
44 tokenMap.put(JavaTokenType.GTGTEQ, JavaTokenType.GTGT);
45 tokenMap.put(JavaTokenType.GTGTGTEQ, JavaTokenType.GTGTGT);
48 @Override
49 @NotNull
50 protected PsiElementPredicate getElementPredicate() {
51 return new OperatorAssignmentPredicate();
54 @Override
55 protected String getTextForElement(PsiElement element) {
56 final PsiAssignmentExpression assignmentExpression =
57 (PsiAssignmentExpression)element;
58 final PsiJavaToken sign = assignmentExpression.getOperationSign();
59 final String operator = sign.getText();
60 return IntentionPowerPackBundle.message(
61 "replace.operator.assignment.with.assignment.intention.name",
62 operator);
65 @Override
66 protected void processIntention(@NotNull PsiElement element)
67 throws IncorrectOperationException {
68 final PsiAssignmentExpression assignmentExpression =
69 (PsiAssignmentExpression)element;
70 final PsiJavaToken sign = assignmentExpression.getOperationSign();
71 final PsiExpression lhs = assignmentExpression.getLExpression();
72 final PsiExpression rhs = assignmentExpression.getRExpression();
73 final String operator = sign.getText();
74 final String newOperator = operator.substring(0, operator.length() - 1);
75 final String lhsText = lhs.getText();
76 final String rhsText;
77 if (rhs == null) {
78 rhsText = "";
79 } else {
80 rhsText = rhs.getText();
82 if (rhs instanceof PsiBinaryExpression) {
83 final PsiBinaryExpression binaryExpression =
84 (PsiBinaryExpression)rhs;
85 final PsiJavaToken javaToken = binaryExpression.getOperationSign();
86 final int precedence1 =
87 ParenthesesUtils.getPrecedenceForBinaryOperator(javaToken);
88 final IElementType signTokenType = sign.getTokenType();
89 final IElementType newOperatorToken = tokenMap.get(signTokenType);
90 final int precedence2 =
91 ParenthesesUtils.getPrecedenceForBinaryOperator(
92 newOperatorToken);
93 if (precedence1 > precedence2 ||
94 !ParenthesesUtils.isCommutativeBinaryOperator(
95 newOperatorToken)) {
96 final String expString;
97 if (needsCast(rhs)) {
98 expString = lhsText + "=(int)" + lhsText + newOperator
99 + '(' + rhsText + "))";
100 } else {
101 expString = lhsText + '=' + lhsText + newOperator
102 + '(' + rhsText + ')';
104 replaceExpression(expString, assignmentExpression);
105 return;
108 final String expString;
109 if (needsCast(rhs)) {
110 expString = lhsText + "=(int)(" + lhsText + newOperator + rhsText
111 + ')';
112 } else {
113 expString = lhsText + '=' + lhsText + newOperator + rhsText;
115 replaceExpression(expString, assignmentExpression);
118 private static boolean needsCast(PsiExpression expression) {
119 final PsiType type = expression.getType();
120 return PsiType.LONG.equals(type) || PsiType.DOUBLE.equals(type) ||
121 PsiType.FLOAT.equals(type);