KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > fix > ExpressionsFix


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.fix;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.text.edits.TextEditGroup;
19
20 import org.eclipse.core.runtime.CoreException;
21
22 import org.eclipse.jdt.core.dom.AST;
23 import org.eclipse.jdt.core.dom.ASTNode;
24 import org.eclipse.jdt.core.dom.ASTVisitor;
25 import org.eclipse.jdt.core.dom.Assignment;
26 import org.eclipse.jdt.core.dom.CastExpression;
27 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
28 import org.eclipse.jdt.core.dom.CompilationUnit;
29 import org.eclipse.jdt.core.dom.ConditionalExpression;
30 import org.eclipse.jdt.core.dom.Expression;
31 import org.eclipse.jdt.core.dom.ITypeBinding;
32 import org.eclipse.jdt.core.dom.InfixExpression;
33 import org.eclipse.jdt.core.dom.InstanceofExpression;
34 import org.eclipse.jdt.core.dom.MethodInvocation;
35 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
36 import org.eclipse.jdt.core.dom.PostfixExpression;
37 import org.eclipse.jdt.core.dom.PrefixExpression;
38 import org.eclipse.jdt.core.dom.InfixExpression.Operator;
39 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
40
41 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
42
43 public class ExpressionsFix extends AbstractFix {
44
45     private static final class MissingParenthesisVisitor extends ASTVisitor {
46         
47         private final ArrayList JavaDoc fNodes;
48
49         private MissingParenthesisVisitor(ArrayList JavaDoc nodes) {
50             fNodes= nodes;
51         }
52
53         public void postVisit(ASTNode node) {
54             // check that parent is && or ||
55
if (!(node.getParent() instanceof InfixExpression))
56                 return;
57             
58             // we want to add parenthesis around arithmetic operators and instanceof
59
boolean needParenthesis = false;
60             if (node instanceof InfixExpression) {
61                 InfixExpression expression = (InfixExpression) node;
62                 InfixExpression.Operator operator = expression.getOperator();
63
64                 InfixExpression parentExpression = (InfixExpression) node.getParent();
65                 InfixExpression.Operator parentOperator = parentExpression.getOperator();
66                 
67                 if (parentOperator == operator)
68                     return;
69                 
70                 needParenthesis= (operator == InfixExpression.Operator.LESS)
71                         || (operator == InfixExpression.Operator.GREATER)
72                         || (operator == InfixExpression.Operator.LESS_EQUALS)
73                         || (operator == InfixExpression.Operator.GREATER_EQUALS)
74                         || (operator == InfixExpression.Operator.EQUALS)
75                         || (operator == InfixExpression.Operator.NOT_EQUALS)
76                         
77                         || (operator == InfixExpression.Operator.CONDITIONAL_AND)
78                         || (operator == InfixExpression.Operator.CONDITIONAL_OR);
79             }
80             if (node instanceof InstanceofExpression) {
81                 needParenthesis = true;
82             }
83             if (!needParenthesis) {
84                 return;
85             }
86             fNodes.add(node);
87         }
88     }
89     
90     private static final class UnnecessaryParenthesisVisitor extends ASTVisitor {
91         private final ArrayList JavaDoc fNodes;
92
93         private UnnecessaryParenthesisVisitor(ArrayList JavaDoc nodes) {
94             fNodes= nodes;
95         }
96
97         public void postVisit(ASTNode node) {
98             if (!(node instanceof ParenthesizedExpression)) {
99                 return;
100             }
101             ParenthesizedExpression parenthesizedExpression= (ParenthesizedExpression) node;
102             Expression expression= parenthesizedExpression.getExpression();
103             while (expression instanceof ParenthesizedExpression) {
104                 expression= ((ParenthesizedExpression) expression).getExpression();
105             }
106             // check case when this expression is cast expression and parent is method invocation with this expression as expression
107
if ((parenthesizedExpression.getExpression() instanceof CastExpression)
108                 && (parenthesizedExpression.getParent() instanceof MethodInvocation)) {
109                 MethodInvocation parentMethodInvocation = (MethodInvocation) parenthesizedExpression.getParent();
110                 if (parentMethodInvocation.getExpression() == parenthesizedExpression)
111                     return;
112             }
113             // if this is part of another expression, check for this and parent precedences
114
if (parenthesizedExpression.getParent() instanceof Expression) {
115                 Expression parentExpression= (Expression) parenthesizedExpression.getParent();
116                 int expressionPrecedence= getExpressionPrecedence(expression);
117                 int parentPrecedence= getExpressionPrecedence(parentExpression);
118                 if ((expressionPrecedence > parentPrecedence)
119                     && !(parenthesizedExpression.getParent() instanceof ParenthesizedExpression)) {
120                     return;
121                 }
122                 // check for case when precedences for expression and parent are same
123
if ((expressionPrecedence == parentPrecedence) && (parentExpression instanceof InfixExpression)) {
124                     //we have expr infix (expr infix expr) removing the parenthesis is equal to (expr infix expr) infix expr
125
InfixExpression parentInfix= (InfixExpression) parentExpression;
126                     Operator parentOperator= parentInfix.getOperator();
127                     if (parentInfix.getLeftOperand() == parenthesizedExpression) {
128                         fNodes.add(node);
129                     } else if (isAssoziative(parentOperator)) {
130                         if (parentOperator == InfixExpression.Operator.PLUS) {
131                             if (isStringExpression(parentInfix.getLeftOperand())
132                                 || isStringExpression(parentInfix.getRightOperand())) {
133                                 return;
134                             }
135                             for (Iterator JavaDoc J= parentInfix.extendedOperands().iterator(); J.hasNext();) {
136                                 Expression operand= (Expression) J.next();
137                                 if (isStringExpression(operand)) {
138                                     return;
139                                 }
140                             }
141                         }
142                         fNodes.add(node);
143                     }
144                     return;
145                 } else if (expressionPrecedence == parentPrecedence && parentExpression instanceof ConditionalExpression) {
146                     if (((ConditionalExpression)parentExpression).getElseExpression() != parenthesizedExpression)
147                         return;
148                 }
149             }
150             fNodes.add(node);
151         }
152
153         //is e1 op (e2 op e3) == (e1 op e2) op e3 == e1 op e2 op e3 for 'operator'?
154
private boolean isAssoziative(Operator operator) {
155             if (operator == InfixExpression.Operator.PLUS)
156                 return true;
157             
158             if (operator == InfixExpression.Operator.CONDITIONAL_AND)
159                 return true;
160             
161             if (operator == InfixExpression.Operator.CONDITIONAL_OR)
162                 return true;
163             
164             if (operator == InfixExpression.Operator.AND)
165                 return true;
166             
167             if (operator == InfixExpression.Operator.OR)
168                 return true;
169             
170             if (operator == InfixExpression.Operator.XOR)
171                 return true;
172             
173             if (operator == InfixExpression.Operator.TIMES)
174                 return true;
175             
176             return false;
177         }
178
179         private static int getExpressionPrecedence(Expression expression) {
180             if (expression instanceof PostfixExpression || expression instanceof MethodInvocation) {
181                 return 0;
182             }
183             if (expression instanceof PrefixExpression) {
184                 return 1;
185             }
186             if ((expression instanceof ClassInstanceCreation) || (expression instanceof CastExpression)) {
187                 return 2;
188             }
189             if (expression instanceof InfixExpression) {
190                 InfixExpression infixExpression = (InfixExpression) expression;
191                 InfixExpression.Operator operator = infixExpression.getOperator();
192                 return getInfixOperatorPrecedence(operator);
193             }
194             if (expression instanceof InstanceofExpression) {
195                 return 6;
196             }
197             if (expression instanceof ConditionalExpression) {
198                 return 13;
199             }
200             if (expression instanceof Assignment) {
201                 return 14;
202             }
203             return -1;
204         }
205         
206         private static int getInfixOperatorPrecedence(InfixExpression.Operator operator) {
207             if ((operator == InfixExpression.Operator.TIMES) || (operator == InfixExpression.Operator.DIVIDE)
208                     || (operator == InfixExpression.Operator.REMAINDER)) {
209                 return 3;
210             }
211             if ((operator == InfixExpression.Operator.PLUS) || (operator == InfixExpression.Operator.MINUS)) {
212                 return 4;
213             }
214             if ((operator == InfixExpression.Operator.LEFT_SHIFT)
215                     || (operator == InfixExpression.Operator.RIGHT_SHIFT_SIGNED)
216                     || (operator == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED)) {
217                 return 5;
218             }
219             if ((operator == InfixExpression.Operator.LESS) || (operator == InfixExpression.Operator.GREATER)
220                     || (operator == InfixExpression.Operator.LESS_EQUALS)
221                     || (operator == InfixExpression.Operator.GREATER_EQUALS)) {
222                 return 6;
223             }
224             if ((operator == InfixExpression.Operator.EQUALS) || (operator == InfixExpression.Operator.NOT_EQUALS)) {
225                 return 7;
226             }
227             if (operator == InfixExpression.Operator.AND) {
228                 return 8;
229             }
230             if (operator == InfixExpression.Operator.XOR) {
231                 return 9;
232             }
233             if (operator == InfixExpression.Operator.OR) {
234                 return 10;
235             }
236             if (operator == InfixExpression.Operator.CONDITIONAL_AND) {
237                 return 11;
238             }
239             if (operator == InfixExpression.Operator.CONDITIONAL_OR) {
240                 return 12;
241             }
242             return -1;
243         }
244         
245     }
246
247     private static class AddParenthesisOperation extends AbstractFixRewriteOperation {
248
249         private final Expression[] fExpressions;
250
251         public AddParenthesisOperation(Expression[] expressions) {
252             fExpressions= expressions;
253         }
254
255         /**
256          * {@inheritDoc}
257          */

258         public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
259             TextEditGroup group= createTextEditGroup(FixMessages.ExpressionsFix_addParanoiacParenthesis_description);
260             textEditGroups.add(group);
261             
262             ASTRewrite rewrite= cuRewrite.getASTRewrite();
263             AST ast= cuRewrite.getRoot().getAST();
264
265             for (int i= 0; i < fExpressions.length; i++) {
266                 // add parenthesis around expression
267
Expression expression= fExpressions[i];
268                 
269                 ParenthesizedExpression parenthesizedExpression= ast.newParenthesizedExpression();
270                 parenthesizedExpression.setExpression((Expression) rewrite.createCopyTarget(expression));
271                 rewrite.replace(expression, parenthesizedExpression, group);
272             }
273         }
274     }
275     
276     private static class RemoveParenthesisOperation extends AbstractFixRewriteOperation {
277
278         private final HashSet JavaDoc/*<ParenthesizedExpression>*/ fExpressions;
279
280         public RemoveParenthesisOperation(HashSet JavaDoc expressions) {
281             fExpressions= expressions;
282         }
283
284         /**
285          * {@inheritDoc}
286          */

287         public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
288             TextEditGroup group= createTextEditGroup(FixMessages.ExpressionsFix_removeUnnecessaryParenthesis_description);
289             textEditGroups.add(group);
290             
291             ASTRewrite rewrite= cuRewrite.getASTRewrite();
292                         
293             while (fExpressions.size() > 0) {
294                 ParenthesizedExpression parenthesizedExpression= (ParenthesizedExpression)fExpressions.iterator().next();
295                 fExpressions.remove(parenthesizedExpression);
296                 ParenthesizedExpression down= parenthesizedExpression;
297                 while (fExpressions.contains(down.getExpression())) {
298                     down= (ParenthesizedExpression)down.getExpression();
299                     fExpressions.remove(down);
300                 }
301                 
302                 ASTNode move= rewrite.createMoveTarget(down.getExpression());
303                 
304                 ParenthesizedExpression top= parenthesizedExpression;
305                 while (fExpressions.contains(top.getParent())) {
306                     top= (ParenthesizedExpression)top.getParent();
307                     fExpressions.remove(top);
308                 }
309                 
310                 rewrite.replace(top, move, group);
311             }
312         }
313     }
314     
315     public static IFix createAddParanoidalParenthesisFix(CompilationUnit compilationUnit, ASTNode[] coveredNodes) throws CoreException {
316         if (coveredNodes == null)
317             return null;
318         
319         if (coveredNodes.length == 0)
320             return null;
321         // check sub-expressions in fully covered nodes
322
final ArrayList JavaDoc changedNodes = new ArrayList JavaDoc();
323         for (int i= 0; i < coveredNodes.length; i++) {
324             ASTNode covered = coveredNodes[i];
325             if (covered instanceof InfixExpression)
326                 covered.accept(new MissingParenthesisVisitor(changedNodes));
327         }
328         if (changedNodes.isEmpty())
329             return null;
330         
331
332         IFixRewriteOperation op= new AddParenthesisOperation((Expression[])changedNodes.toArray(new Expression[changedNodes.size()]));
333         return new ExpressionsFix(FixMessages.ExpressionsFix_addParanoiacParenthesis_description, compilationUnit, new IFixRewriteOperation[] {op});
334     }
335     
336     public static IFix createRemoveUnnecessaryParenthesisFix(CompilationUnit compilationUnit, ASTNode[] nodes) {
337         // check sub-expressions in fully covered nodes
338
final ArrayList JavaDoc changedNodes= new ArrayList JavaDoc();
339         for (int i= 0; i < nodes.length; i++) {
340             ASTNode covered= nodes[i];
341             if (covered instanceof ParenthesizedExpression || covered instanceof InfixExpression)
342                 covered.accept(new UnnecessaryParenthesisVisitor(changedNodes));
343         }
344         if (changedNodes.isEmpty())
345             return null;
346         
347         HashSet JavaDoc expressions= new HashSet JavaDoc(changedNodes);
348         RemoveParenthesisOperation op= new RemoveParenthesisOperation(expressions);
349         return new ExpressionsFix(FixMessages.ExpressionsFix_removeUnnecessaryParenthesis_description, compilationUnit, new IFixRewriteOperation[] {op});
350     }
351     
352     public static IFix createCleanUp(CompilationUnit compilationUnit,
353             boolean addParanoicParentesis,
354             boolean removeUnnecessaryParenthesis) {
355         
356         if (addParanoicParentesis) {
357             final ArrayList JavaDoc changedNodes = new ArrayList JavaDoc();
358             compilationUnit.accept(new MissingParenthesisVisitor(changedNodes));
359
360             if (changedNodes.isEmpty())
361                 return null;
362             
363             IFixRewriteOperation op= new AddParenthesisOperation((Expression[])changedNodes.toArray(new Expression[changedNodes.size()]));
364             return new ExpressionsFix(FixMessages.ExpressionsFix_add_parenthesis_change_name, compilationUnit, new IFixRewriteOperation[] {op});
365         } else if (removeUnnecessaryParenthesis) {
366             final ArrayList JavaDoc changedNodes = new ArrayList JavaDoc();
367             compilationUnit.accept(new UnnecessaryParenthesisVisitor(changedNodes));
368
369             if (changedNodes.isEmpty())
370                 return null;
371             
372             HashSet JavaDoc expressions= new HashSet JavaDoc(changedNodes);
373             IFixRewriteOperation op= new RemoveParenthesisOperation(expressions);
374             return new ExpressionsFix(FixMessages.ExpressionsFix_remove_parenthesis_change_name, compilationUnit, new IFixRewriteOperation[] {op});
375         }
376         return null;
377     }
378     
379     private static boolean isStringExpression(Expression expression) {
380         ITypeBinding binding = expression.resolveTypeBinding();
381         return binding.getQualifiedName().equals("java.lang.String"); //$NON-NLS-1$
382
}
383
384     protected ExpressionsFix(String JavaDoc name, CompilationUnit compilationUnit, IFixRewriteOperation[] fixRewriteOperations) {
385         super(name, compilationUnit, fixRewriteOperations);
386     }
387
388 }
389
Popular Tags