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