View Javadoc

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