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
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 }