View Javadoc

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