/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.junit; import java.util.List; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTExtendsList; import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTResultType; import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; public abstract class AbstractJUnitRule extends AbstractJavaRule { public static final Class<?> JUNIT4_CLASS; public static final Class<?> JUNIT3_CLASS; private boolean isJUnit3Class; private boolean isJUnit4Class; static { Class<?> c; try { c = Class.forName("org.junit.Test"); } catch (ClassNotFoundException t) { c = null; } catch (NoClassDefFoundError t) { c = null; } JUNIT4_CLASS = c; try { c = Class.forName("junit.framework.TestCase"); } catch (ClassNotFoundException t) { c = null; } catch (NoClassDefFoundError t) { c = null; } JUNIT3_CLASS = c; } @Override public Object visit(ASTCompilationUnit node, Object data) { isJUnit3Class = false; isJUnit4Class = false; isJUnit3Class = isJUnit3Class(node); if (!isJUnit3Class) { isJUnit4Class = isJUnit4Class(node); } if (!isTestNgClass(node) && (isJUnit3Class || isJUnit4Class)) { return super.visit(node, data); } return data; } private boolean isTestNgClass(ASTCompilationUnit node) { List<ASTImportDeclaration> imports = node.findDescendantsOfType(ASTImportDeclaration.class); for (ASTImportDeclaration i : imports) { if (i.getImportedName() != null && i.getImportedName().startsWith("org.testng")) { return true; } } return false; } public boolean isJUnitMethod(ASTMethodDeclaration method, Object data) { if (!method.isPublic() || method.isAbstract() || method.isNative() || method.isStatic()) { return false; // skip various inapplicable method variations } boolean result = false; if (isJUnit3Class) { result = isJUnit3Method(method); } result |= isJUnit4Method(method); return result; } private boolean isJUnit4Method(ASTMethodDeclaration method) { return doesNodeContainJUnitAnnotation(method.jjtGetParent()); } private boolean isJUnit3Method(ASTMethodDeclaration method) { Node node = method.jjtGetChild(0); if (node instanceof ASTTypeParameters) { node = method.jjtGetChild(1); } return ((ASTResultType) node).isVoid() && method.getMethodName().startsWith("test"); } private boolean isJUnit3Class(ASTCompilationUnit node) { if (node.getType() != null && TypeHelper.isA(node, JUNIT3_CLASS)) { return true; } else if (node.getType() == null) { ASTClassOrInterfaceDeclaration cid = node.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class); if (cid == null) { return false; } ASTExtendsList extendsList = cid.getFirstChildOfType(ASTExtendsList.class); if (extendsList == null) { return false; } if (((ASTClassOrInterfaceType) extendsList.jjtGetChild(0)).getImage().endsWith("TestCase")) { return true; } String className = cid.getImage(); return className.endsWith("Test"); } return false; } private boolean isJUnit4Class(ASTCompilationUnit node) { return doesNodeContainJUnitAnnotation(node); } private boolean doesNodeContainJUnitAnnotation(Node node) { List<ASTAnnotation> annotations = node.findDescendantsOfType(ASTAnnotation.class); for (ASTAnnotation annotation : annotations) { Node annotationTypeNode = annotation.jjtGetChild(0); TypeNode annotationType = (TypeNode) annotationTypeNode; if (annotationType.getType() == null) { ASTName name = annotationTypeNode.getFirstChildOfType(ASTName.class); if (name != null && "Test".equals(name.getImage())) { return true; } } else if (annotationType.getType().equals(JUNIT4_CLASS)) { return true; } } return false; } }