View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.vm.rule.basic;
5   
6   import net.sourceforge.pmd.lang.ast.Node;
7   import net.sourceforge.pmd.lang.vm.ast.ASTBlock;
8   import net.sourceforge.pmd.lang.vm.ast.ASTElseIfStatement;
9   import net.sourceforge.pmd.lang.vm.ast.ASTElseStatement;
10  import net.sourceforge.pmd.lang.vm.ast.ASTIfStatement;
11  import net.sourceforge.pmd.lang.vm.ast.ASTText;
12  import net.sourceforge.pmd.lang.vm.ast.AbstractVmNode;
13  import net.sourceforge.pmd.lang.vm.rule.AbstractVmRule;
14  
15  import org.apache.commons.lang3.StringUtils;
16  
17  public class CollapsibleIfStatementsRule extends AbstractVmRule {
18  
19      @Override
20      public Object visit(final ASTIfStatement node, final Object data) {
21          handleIfElseIf(node, data);
22          return super.visit(node, data);
23      }
24  
25      @Override
26      public Object visit(final ASTElseIfStatement node, final Object data) {
27          // verify that this elseif doesn't have any siblings
28          if (node.jjtGetParent().findChildrenOfType(ASTElseIfStatement.class).size() == 1) {
29              handleIfElseIf(node, data);
30          }
31          return super.visit(node, data);
32      }
33  
34      private void handleIfElseIf(final AbstractVmNode node, final Object data) {
35          if (node.getFirstChildOfType(ASTElseStatement.class) == null
36                  && node.getFirstChildOfType(ASTElseIfStatement.class) == null) {
37              final ASTBlock ifBlock = node.getFirstChildOfType(ASTBlock.class);
38              boolean violationFound = false;
39              int ifCounter = 0;
40              for (int i = 0; i < ifBlock.jjtGetNumChildren(); i++) {
41                  final Node blockChild = ifBlock.jjtGetChild(i);
42                  if (blockChild instanceof ASTText) {
43                      if (StringUtils.isNotBlank(((ASTText) blockChild).getFirstToken().toString())) {
44                          violationFound = false;
45                          break;
46                      }
47                  }
48                  else if (blockChild instanceof ASTIfStatement) {
49                      // check if it has an ELSE of ELSEIF
50                      violationFound = !hasElseOrElseIf(blockChild);
51                      if (!violationFound) {
52                          break;
53                      }
54                      ifCounter++;
55                  }
56                  else if (blockChild instanceof ASTElseIfStatement) {
57                      // check if it has an ELSE of ELSEIF
58                      violationFound = !hasElseOrElseIf(blockChild);
59                      if (!violationFound) {
60                          break;
61                      }
62                      ifCounter++;
63                  }
64                  else {
65                      // any other node - not violation
66                      violationFound = false;
67                      break;
68                  }
69              }
70              if (violationFound && ifCounter == 1) {
71                  addViolation(data, node);
72              }
73          }
74      }
75  
76      private boolean hasElseOrElseIf(final Node parentIfNode) {
77          return parentIfNode.getFirstChildOfType(ASTElseStatement.class) != null
78                  || parentIfNode.getFirstChildOfType(ASTElseIfStatement.class) != null;
79      }
80  
81  }