1 11 package org.eclipse.jdt.internal.corext.fix; 12 13 import java.util.ArrayList ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.List ; 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 fNodes; 48 49 private MissingParenthesisVisitor(ArrayList nodes) { 50 fNodes= nodes; 51 } 52 53 public void postVisit(ASTNode node) { 54 if (!(node.getParent() instanceof InfixExpression)) 56 return; 57 58 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 fNodes; 92 93 private UnnecessaryParenthesisVisitor(ArrayList 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 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 (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 if ((expressionPrecedence == parentPrecedence) && (parentExpression instanceof InfixExpression)) { 124 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 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 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 258 public void rewriteAST(CompilationUnitRewrite cuRewrite, List 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 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 fExpressions; 279 280 public RemoveParenthesisOperation(HashSet expressions) { 281 fExpressions= expressions; 282 } 283 284 287 public void rewriteAST(CompilationUnitRewrite cuRewrite, List 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 final ArrayList changedNodes = new ArrayList (); 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 final ArrayList changedNodes= new ArrayList (); 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 expressions= new HashSet (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 changedNodes = new ArrayList (); 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 changedNodes = new ArrayList (); 367 compilationUnit.accept(new UnnecessaryParenthesisVisitor(changedNodes)); 368 369 if (changedNodes.isEmpty()) 370 return null; 371 372 HashSet expressions= new HashSet (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"); } 383 384 protected ExpressionsFix(String name, CompilationUnit compilationUnit, IFixRewriteOperation[] fixRewriteOperations) { 385 super(name, compilationUnit, fixRewriteOperations); 386 } 387 388 } 389 | Popular Tags |