/**
* 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;
}
}