1 11 package org.eclipse.jdt.internal.corext.fix; 12 13 import java.util.ArrayList ; 14 import java.util.List ; 15 16 import org.eclipse.text.edits.TextEditGroup; 17 18 import org.eclipse.core.runtime.CoreException; 19 20 import org.eclipse.jdt.core.dom.ASTNode; 21 import org.eclipse.jdt.core.dom.Block; 22 import org.eclipse.jdt.core.dom.ChildPropertyDescriptor; 23 import org.eclipse.jdt.core.dom.CompilationUnit; 24 import org.eclipse.jdt.core.dom.DoStatement; 25 import org.eclipse.jdt.core.dom.EnhancedForStatement; 26 import org.eclipse.jdt.core.dom.ForStatement; 27 import org.eclipse.jdt.core.dom.IfStatement; 28 import org.eclipse.jdt.core.dom.ReturnStatement; 29 import org.eclipse.jdt.core.dom.Statement; 30 import org.eclipse.jdt.core.dom.ThrowStatement; 31 import org.eclipse.jdt.core.dom.WhileStatement; 32 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 33 34 import org.eclipse.jdt.internal.corext.dom.GenericVisitor; 35 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; 36 37 import org.eclipse.jdt.internal.ui.text.correction.ASTResolving; 38 39 public class ControlStatementsFix extends AbstractFix { 40 41 private final static class ControlStatementFinder extends GenericVisitor { 42 43 private final List fResult; 44 private final boolean fFindControlStatementsWithoutBlock; 45 private final boolean fRemoveUnnecessaryBlocks; 46 private final boolean fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow; 47 48 public ControlStatementFinder(boolean findControlStatementsWithoutBlock, 49 boolean removeUnnecessaryBlocks, 50 boolean removeUnnecessaryBlocksOnlyWhenReturnOrThrow, 51 List resultingCollection) { 52 53 fFindControlStatementsWithoutBlock= findControlStatementsWithoutBlock; 54 fRemoveUnnecessaryBlocks= removeUnnecessaryBlocks; 55 fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow= removeUnnecessaryBlocksOnlyWhenReturnOrThrow; 56 fResult= resultingCollection; 57 } 58 59 62 public boolean visit(DoStatement node) { 63 if (fFindControlStatementsWithoutBlock) { 64 Statement doBody= node.getBody(); 65 if (!(doBody instanceof Block)) { 66 fResult.add(new AddBlockOperation(DoStatement.BODY_PROPERTY, doBody, node)); 67 } 68 } else if (fRemoveUnnecessaryBlocks || fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow) { 69 if (RemoveBlockOperation.satisfiesCleanUpPrecondition(node, DoStatement.BODY_PROPERTY, fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow)) { 70 fResult.add(new RemoveBlockOperation(node, DoStatement.BODY_PROPERTY)); 71 } 72 } 73 return super.visit(node); 74 } 75 76 79 public boolean visit(ForStatement node) { 80 if (fFindControlStatementsWithoutBlock) { 81 Statement forBody= node.getBody(); 82 if (!(forBody instanceof Block)) { 83 fResult.add(new AddBlockOperation(ForStatement.BODY_PROPERTY, forBody, node)); 84 } 85 } else if (fRemoveUnnecessaryBlocks || fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow) { 86 if (RemoveBlockOperation.satisfiesCleanUpPrecondition(node, ForStatement.BODY_PROPERTY, fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow)) { 87 fResult.add(new RemoveBlockOperation(node, ForStatement.BODY_PROPERTY)); 88 } 89 } 90 return super.visit(node); 91 } 92 93 96 public boolean visit(EnhancedForStatement node) { 97 if (fFindControlStatementsWithoutBlock) { 98 Statement forBody= node.getBody(); 99 if (!(forBody instanceof Block)) { 100 fResult.add(new AddBlockOperation(EnhancedForStatement.BODY_PROPERTY, forBody, node)); 101 } 102 } else if (fRemoveUnnecessaryBlocks || fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow) { 103 if (RemoveBlockOperation.satisfiesCleanUpPrecondition(node, EnhancedForStatement.BODY_PROPERTY, fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow)) { 104 fResult.add(new RemoveBlockOperation(node, EnhancedForStatement.BODY_PROPERTY)); 105 } 106 } 107 return super.visit(node); 108 } 109 110 113 public boolean visit(IfStatement statement) { 114 if (fFindControlStatementsWithoutBlock) { 115 Statement then= statement.getThenStatement(); 116 if (!(then instanceof Block)) { 117 fResult.add(new AddBlockOperation(IfStatement.THEN_STATEMENT_PROPERTY, then, statement)); 118 } 119 Statement elseStatement= statement.getElseStatement(); 120 if (elseStatement != null && !(elseStatement instanceof Block) && !(elseStatement instanceof IfStatement)) { 121 fResult.add(new AddBlockOperation(IfStatement.ELSE_STATEMENT_PROPERTY, elseStatement, statement)); 122 } 123 } else if (fRemoveUnnecessaryBlocks || fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow) { 124 if (RemoveBlockOperation.satisfiesCleanUpPrecondition(statement, IfStatement.THEN_STATEMENT_PROPERTY, fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow)) { 125 fResult.add(new RemoveBlockOperation(statement, IfStatement.THEN_STATEMENT_PROPERTY)); 126 } 127 if (!(statement.getElseStatement() instanceof IfStatement)) { 128 if (RemoveBlockOperation.satisfiesCleanUpPrecondition(statement, IfStatement.ELSE_STATEMENT_PROPERTY, fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow)) { 129 fResult.add(new RemoveBlockOperation(statement, IfStatement.ELSE_STATEMENT_PROPERTY)); 130 } 131 } 132 } 133 return super.visit(statement); 134 } 135 136 139 public boolean visit(WhileStatement node) { 140 if (fFindControlStatementsWithoutBlock) { 141 Statement whileBody= node.getBody(); 142 if (!(whileBody instanceof Block)) { 143 fResult.add(new AddBlockOperation(WhileStatement.BODY_PROPERTY, whileBody, node)); 144 } 145 } else if (fRemoveUnnecessaryBlocks || fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow) { 146 if (RemoveBlockOperation.satisfiesCleanUpPrecondition(node, WhileStatement.BODY_PROPERTY, fRemoveUnnecessaryBlocksOnlyWhenReturnOrThrow)) 147 fResult.add(new RemoveBlockOperation(node, WhileStatement.BODY_PROPERTY)); 148 } 149 return super.visit(node); 150 } 151 152 } 153 154 private static class IfElseIterator { 155 156 private IfStatement fCursor; 157 158 public IfElseIterator(IfStatement item) { 159 fCursor= findStart(item); 160 } 161 162 public IfStatement next() { 163 if (!hasNext()) 164 return null; 165 166 IfStatement result= fCursor; 167 168 if (fCursor.getElseStatement() instanceof IfStatement) { 169 fCursor= (IfStatement)fCursor.getElseStatement(); 170 } else { 171 fCursor= null; 172 } 173 174 return result; 175 } 176 177 public boolean hasNext() { 178 return fCursor != null; 179 } 180 181 private IfStatement findStart(IfStatement item) { 182 while (item.getLocationInParent() == IfStatement.ELSE_STATEMENT_PROPERTY) { 183 item= (IfStatement)item.getParent(); 184 } 185 return item; 186 } 187 } 188 189 private static final class AddBlockOperation extends AbstractFixRewriteOperation { 190 191 private final ChildPropertyDescriptor fBodyProperty; 192 private final Statement fBody; 193 private final Statement fControlStatement; 194 195 public AddBlockOperation(ChildPropertyDescriptor bodyProperty, Statement body, Statement controlStatement) { 196 fBodyProperty= bodyProperty; 197 fBody= body; 198 fControlStatement= controlStatement; 199 } 200 201 204 public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { 205 ASTRewrite rewrite= cuRewrite.getASTRewrite(); 206 String label; 207 if (fBodyProperty == IfStatement.THEN_STATEMENT_PROPERTY) { 208 label = FixMessages.CodeStyleFix_ChangeIfToBlock_desription; 209 } else if (fBodyProperty == IfStatement.ELSE_STATEMENT_PROPERTY) { 210 label = FixMessages.CodeStyleFix_ChangeElseToBlock_description; 211 } else { 212 label = FixMessages.CodeStyleFix_ChangeControlToBlock_description; 213 } 214 215 TextEditGroup group= createTextEditGroup(label); 216 textEditGroups.add(group); 217 218 ASTNode moveTarget= rewrite.createMoveTarget(fBody); 219 Block replacingBody= cuRewrite.getRoot().getAST().newBlock(); 220 replacingBody.statements().add(moveTarget); 221 rewrite.set(fControlStatement, fBodyProperty, replacingBody, group); 222 } 223 224 } 225 226 static class RemoveBlockOperation extends AbstractFixRewriteOperation { 227 228 private final Statement fStatement; 229 private final ChildPropertyDescriptor fChild; 230 231 public RemoveBlockOperation(Statement controlStatement, ChildPropertyDescriptor child) { 232 fStatement= controlStatement; 233 fChild= child; 234 } 235 236 239 public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { 240 ASTRewrite rewrite= cuRewrite.getASTRewrite(); 241 242 Block block= (Block)fStatement.getStructuralProperty(fChild); 243 Statement statement= (Statement)block.statements().get(0); 244 Statement moveTarget= (Statement)rewrite.createMoveTarget(statement); 245 246 TextEditGroup group= createTextEditGroup(FixMessages.ControlStatementsFix_removeBrackets_proposalDescription); 247 textEditGroups.add(group); 248 rewrite.set(fStatement, fChild, moveTarget, group); 249 } 250 251 public static boolean satisfiesCleanUpPrecondition(Statement controlStatement, ChildPropertyDescriptor childDescriptor, boolean onlyReturnAndThrows) { 252 return satisfiesPrecondition(controlStatement, childDescriptor, onlyReturnAndThrows, true); 253 } 254 255 public static boolean satisfiesQuickAssistPrecondition(Statement controlStatement, ChildPropertyDescriptor childDescriptor) { 256 return satisfiesPrecondition(controlStatement, childDescriptor, false, false); 257 } 258 259 private static boolean satisfiesPrecondition(Statement controlStatement, ChildPropertyDescriptor childDescriptor, boolean onlyReturnAndThrows, boolean cleanUpCheck) { 261 Object child= controlStatement.getStructuralProperty(childDescriptor); 262 263 if (!(child instanceof Block)) 264 return false; 265 266 Block block= (Block)child; 267 List list= block.statements(); 268 if (list.size() != 1) 269 return false; 270 271 ASTNode singleStatement= (ASTNode)list.get(0); 272 273 if (onlyReturnAndThrows) 274 if (!(singleStatement instanceof ReturnStatement) && !(singleStatement instanceof ThrowStatement)) 275 return false; 276 277 if (controlStatement instanceof IfStatement) { 278 285 if (((IfStatement)controlStatement).getThenStatement() != child) 286 return true; 288 IfStatement ifStatement= (IfStatement)controlStatement; 289 if (ifStatement.getElseStatement() == null) 290 return true; 292 return !hasUnblockedIf((Statement)singleStatement, onlyReturnAndThrows, cleanUpCheck); 293 } else { 294 if (!hasUnblockedIf((Statement)singleStatement, onlyReturnAndThrows, cleanUpCheck)) 302 return true; 303 304 ASTNode currentChild= controlStatement; 305 ASTNode parent= currentChild.getParent(); 306 while (true) { 307 Statement body= null; 308 if (parent instanceof IfStatement) { 309 body= ((IfStatement)parent).getThenStatement(); 310 if (body == currentChild && ((IfStatement)parent).getElseStatement() != null) return false; 312 } else if (parent instanceof WhileStatement) { 313 body= ((WhileStatement)parent).getBody(); 314 } else if (parent instanceof DoStatement) { 315 body= ((DoStatement)parent).getBody(); 316 } else if (parent instanceof ForStatement) { 317 body= ((ForStatement)parent).getBody(); 318 } else if (parent instanceof EnhancedForStatement) { 319 body= ((EnhancedForStatement)parent).getBody(); 320 } else { 321 return true; 322 } 323 if (body != currentChild) return true; 325 326 currentChild= parent; 327 parent= currentChild.getParent(); 328 } 329 } 330 } 331 332 private static boolean hasUnblockedIf(Statement p, boolean onlyReturnAndThrows, boolean cleanUpCheck) { 333 while (true) { 334 if (p instanceof IfStatement) { 335 return true; 336 } else { 337 338 ChildPropertyDescriptor childD= null; 339 if (p instanceof WhileStatement) { 340 childD= WhileStatement.BODY_PROPERTY; 341 } else if (p instanceof ForStatement) { 342 childD= ForStatement.BODY_PROPERTY; 343 } else if (p instanceof EnhancedForStatement) { 344 childD= EnhancedForStatement.BODY_PROPERTY; 345 } else if (p instanceof DoStatement) { 346 childD= DoStatement.BODY_PROPERTY; 347 } else { 348 return false; 349 } 350 Statement body= (Statement)p.getStructuralProperty(childD); 351 if (body instanceof Block) { 352 if (!cleanUpCheck) { 353 return false; 354 } else { 355 if (!satisfiesPrecondition(p, childD, onlyReturnAndThrows, cleanUpCheck)) 356 return false; 357 358 p= (Statement)((Block)body).statements().get(0); 359 } 360 } else { 361 p= body; 362 } 363 } 364 } 365 } 366 367 } 368 369 public static IFix[] createRemoveBlockFix(CompilationUnit compilationUnit, ASTNode node) { 370 Statement statement= ASTResolving.findParentStatement(node); 371 if (statement == null) { 372 return null; 373 } 374 375 if (statement instanceof Block) { 376 Block block= (Block)statement; 377 if (block.statements().size() != 1) 378 return null; 379 380 ASTNode parent= block.getParent(); 381 if (!(parent instanceof Statement)) 382 return null; 383 384 statement= (Statement)parent; 385 } 386 387 if (statement instanceof IfStatement) { 388 List result= new ArrayList (); 389 390 List removeAllList= new ArrayList (); 391 392 IfElseIterator iter= new IfElseIterator((IfStatement)statement); 393 IfStatement item= null; 394 while (iter.hasNext()) { 395 item= iter.next(); 396 if (RemoveBlockOperation.satisfiesQuickAssistPrecondition(item, IfStatement.THEN_STATEMENT_PROPERTY)) { 397 RemoveBlockOperation op= new RemoveBlockOperation(item, IfStatement.THEN_STATEMENT_PROPERTY); 398 removeAllList.add(op); 399 if (item == statement) 400 result.add(new ControlStatementsFix(FixMessages.ControlStatementsFix_removeIfBlock_proposalDescription, compilationUnit, new IFixRewriteOperation[] {op})); 401 } 402 } 403 404 if (RemoveBlockOperation.satisfiesQuickAssistPrecondition(item, IfStatement.ELSE_STATEMENT_PROPERTY)) { 405 RemoveBlockOperation op= new RemoveBlockOperation(item, IfStatement.ELSE_STATEMENT_PROPERTY); 406 removeAllList.add(op); 407 if (item == statement) 408 result.add(new ControlStatementsFix(FixMessages.ControlStatementsFix_removeElseBlock_proposalDescription, compilationUnit, new IFixRewriteOperation[] {op})); 409 } 410 411 if (removeAllList.size() > 1) { 412 IFixRewriteOperation[] allConvert= (IFixRewriteOperation[])removeAllList.toArray(new IFixRewriteOperation[removeAllList.size()]); 413 result.add(new ControlStatementsFix(FixMessages.ControlStatementsFix_removeIfElseBlock_proposalDescription, compilationUnit, allConvert)); 414 } 415 416 return (IFix[])result.toArray(new IFix[result.size()]); 417 } else if (statement instanceof WhileStatement) { 418 if (RemoveBlockOperation.satisfiesQuickAssistPrecondition(statement, WhileStatement.BODY_PROPERTY)) { 419 RemoveBlockOperation op= new RemoveBlockOperation(statement, WhileStatement.BODY_PROPERTY); 420 return new IFix[] {new ControlStatementsFix(FixMessages.ControlStatementsFix_removeBrackets_proposalDescription, compilationUnit, new IFixRewriteOperation[] {op})}; 421 } 422 } else if (statement instanceof ForStatement) { 423 if (RemoveBlockOperation.satisfiesQuickAssistPrecondition(statement, ForStatement.BODY_PROPERTY)) { 424 RemoveBlockOperation op= new RemoveBlockOperation(statement, ForStatement.BODY_PROPERTY); 425 return new IFix[] {new ControlStatementsFix(FixMessages.ControlStatementsFix_removeBrackets_proposalDescription, compilationUnit, new IFixRewriteOperation[] {op})}; 426 } 427 } else if (statement instanceof EnhancedForStatement) { 428 if (RemoveBlockOperation.satisfiesQuickAssistPrecondition(statement, EnhancedForStatement.BODY_PROPERTY)) { 429 RemoveBlockOperation op= new RemoveBlockOperation(statement, EnhancedForStatement.BODY_PROPERTY); 430 return new IFix[] {new ControlStatementsFix(FixMessages.ControlStatementsFix_removeBrackets_proposalDescription, compilationUnit, new IFixRewriteOperation[] {op})}; 431 } 432 } else if (statement instanceof DoStatement) { 433 if (RemoveBlockOperation.satisfiesQuickAssistPrecondition(statement, DoStatement.BODY_PROPERTY)) { 434 RemoveBlockOperation op= new RemoveBlockOperation(statement, DoStatement.BODY_PROPERTY); 435 return new IFix[] {new ControlStatementsFix(FixMessages.ControlStatementsFix_removeBrackets_proposalDescription, compilationUnit, new IFixRewriteOperation[] {op})}; 436 } 437 } 438 439 return null; 440 } 441 442 public static IFix createCleanUp(CompilationUnit compilationUnit, 443 boolean convertSingleStatementToBlock, 444 boolean removeUnnecessaryBlock, 445 boolean removeUnnecessaryBlockContainingReturnOrThrow) throws CoreException { 446 447 if (!convertSingleStatementToBlock && !removeUnnecessaryBlock && !removeUnnecessaryBlockContainingReturnOrThrow) 448 return null; 449 450 List operations= new ArrayList (); 451 ControlStatementFinder finder= new ControlStatementFinder(convertSingleStatementToBlock, removeUnnecessaryBlock, removeUnnecessaryBlockContainingReturnOrThrow, operations); 452 compilationUnit.accept(finder); 453 454 if (operations.isEmpty()) 455 return null; 456 457 IFixRewriteOperation[] ops= (IFixRewriteOperation[])operations.toArray(new IFixRewriteOperation[operations.size()]); 458 return new ControlStatementsFix(FixMessages.ControlStatementsFix_change_name, compilationUnit, ops); 459 } 460 461 protected ControlStatementsFix(String name, CompilationUnit compilationUnit, IFixRewriteOperation[] fixRewriteOperations) { 462 super(name, compilationUnit, fixRewriteOperations); 463 } 464 465 } 466 | Popular Tags |