View Javadoc

1   package net.sourceforge.pmd.lang.java.rule.strictexception;
2   
3   import java.util.Collections;
4   import java.util.List;
5   
6   import net.sourceforge.pmd.lang.ast.Node;
7   import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
8   import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
9   import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
10  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
11  import net.sourceforge.pmd.lang.java.ast.ASTName;
12  import net.sourceforge.pmd.lang.java.ast.ASTNameList;
13  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
14  
15  /**
16   * <p/>
17   *
18   * @author <a mailto:trondandersen@c2i.net>Trond Andersen</a>
19   * @version 1.0
20   * @since 1.2
21   */
22  
23  public class SignatureDeclareThrowsExceptionRule extends AbstractJavaRule {
24  
25      private boolean junitImported;
26  
27      @Override
28      public Object visit(ASTCompilationUnit node, Object o) {
29          junitImported = false;
30          return super.visit(node, o);
31      }
32  
33      @Override
34      public Object visit(ASTImportDeclaration node, Object o) {
35          if (node.getImportedName().indexOf("junit") != -1) {
36              junitImported = true;
37          }
38          return super.visit(node, o);
39      }
40  
41      @Override
42      public Object visit(ASTMethodDeclaration methodDeclaration, Object o) {
43          if ((methodDeclaration.getMethodName().equals("setUp") || methodDeclaration.getMethodName().equals("tearDown")) && junitImported) {
44              return super.visit(methodDeclaration, o);
45          }
46  
47          if (methodDeclaration.getMethodName().startsWith("test")) {
48              return super.visit(methodDeclaration, o);
49          }
50  
51          List<ASTName> exceptionList = Collections.emptyList();
52          ASTNameList nameList = methodDeclaration.getFirstChildOfType(ASTNameList.class);
53          if (nameList != null) {
54              exceptionList = nameList.findDescendantsOfType(ASTName.class);
55          }
56          if (!exceptionList.isEmpty()) {
57              evaluateExceptions(exceptionList, o);
58          }
59          return super.visit(methodDeclaration, o);
60      }
61  
62  
63      @Override
64      public Object visit(ASTConstructorDeclaration constructorDeclaration, Object o) {
65          List<ASTName> exceptionList = constructorDeclaration.findDescendantsOfType(ASTName.class);
66          if (!exceptionList.isEmpty()) {
67              evaluateExceptions(exceptionList, o);
68          }
69          return super.visit(constructorDeclaration, o);
70      }
71  
72      /**
73       * Checks all exceptions for possible violation on the exception declaration.
74       *
75       * @param exceptionList containing all exception for declaration
76       * @param context
77       */
78      private void evaluateExceptions(List<ASTName> exceptionList, Object context) {
79          for (ASTName exception: exceptionList) {
80              if (hasDeclaredExceptionInSignature(exception)) {
81                  addViolation(context, exception);
82              }
83          }
84      }
85  
86      /**
87       * Checks if the given value is defined as <code>Exception</code> and the parent is either
88       * a method or constructor declaration.
89       *
90       * @param exception to evaluate
91       * @return true if <code>Exception</code> is declared and has proper parents
92       */
93      private boolean hasDeclaredExceptionInSignature(ASTName exception) {
94          return exception.hasImageEqualTo("Exception") && isParentSignatureDeclaration(exception);
95      }
96  
97      /**
98       * @param exception to evaluate
99       * @return true if parent node is either a method or constructor declaration
100      */
101     private boolean isParentSignatureDeclaration(ASTName exception) {
102         Node parent = exception.jjtGetParent().jjtGetParent();
103         return parent instanceof ASTMethodDeclaration || parent instanceof ASTConstructorDeclaration;
104     }
105 
106 }