View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule.optimizations;
5   
6   import net.sourceforge.pmd.lang.ast.Node;
7   import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
8   import net.sourceforge.pmd.lang.java.ast.ASTDoStatement;
9   import net.sourceforge.pmd.lang.java.ast.ASTForInit;
10  import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
11  import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
12  import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement;
13  import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
14  
15  public class AvoidInstantiatingObjectsInLoopsRule extends AbstractOptimizationRule {
16  
17      @Override
18      public Object visit(ASTAllocationExpression node, Object data) {
19          if (insideLoop(node) && fourthParentNotThrow(node) && fourthParentNotReturn(node)) {
20              addViolation(data, node);
21          }
22          return data;
23      }
24  
25      private boolean fourthParentNotThrow(ASTAllocationExpression node) {
26          return !(node.jjtGetParent().jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTThrowStatement);
27      }
28  
29      private boolean fourthParentNotReturn(ASTAllocationExpression node) {
30          return !(node.jjtGetParent().jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTReturnStatement);
31      }
32  
33      private boolean insideLoop(ASTAllocationExpression node) {
34          Node n = node.jjtGetParent();
35          while (n != null) {
36              if (n instanceof ASTDoStatement || n instanceof ASTWhileStatement || n instanceof ASTForStatement) {
37                  return true;
38              } else if (n instanceof ASTForInit) {
39                  /*
40                   * init part is not technically inside the loop.
41                   * Skip parent ASTForStatement but continue higher
42                   * up to detect nested loops
43                   */
44                  n = n.jjtGetParent();
45              } else if (n.jjtGetParent() instanceof ASTForStatement
46                  && n.jjtGetParent().jjtGetNumChildren() > 1
47                  && n == n.jjtGetParent().jjtGetChild(1)) {
48                  // it is the second child of a ForStatement - which means
49                  // we are dealing with a for-each construct
50                  // In that case, we can ignore this allocation expression, as the second child
51                  // is the expression, over which to iterate.
52                  // Skip this parent but continue higher up
53                  // to detect nested loops
54                  n = n.jjtGetParent();
55              }
56              n = n.jjtGetParent();
57          }
58          return false;
59      }
60  }