View Javadoc

    1   package net.sourceforge.pmd.lang.java.rule.junit;
    2
    3   import java.util.List;
    4
    5   import net.sourceforge.pmd.lang.ast.Node;
    6   import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
    7   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
    8   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
    9   import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
    10  import net.sourceforge.pmd.lang.java.ast.ASTExtendsList;
    11  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
    12  import net.sourceforge.pmd.lang.java.ast.ASTName;
    13  import net.sourceforge.pmd.lang.java.ast.ASTResultType;
    14  import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters;
    15  import net.sourceforge.pmd.lang.java.ast.TypeNode;
    16  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
    17  import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
    18
    19  public abstract class AbstractJUnitRule extends AbstractJavaRule {
    20
    21      public static final Class<?> JUNIT4_CLASS;
    22
    23      public static final Class<?> JUNIT3_CLASS;
    24
    25      private boolean isJUnit3Class;
    26      private boolean isJUnit4Class;
    27
    28      static {
    29  	Class<?> c;
    30  	try {
    31  	    c = Class.forName("org.junit.Test");
    32  	} catch (ClassNotFoundException t) {
    33  	    c = null;
    34  	}
    35  	JUNIT4_CLASS = c;
    36
    37  	try {
    38  	    c = Class.forName("junit.framework.TestCase");
    39  	} catch (ClassNotFoundException t) {
    40  	    c = null;
    41  	}
    42  	JUNIT3_CLASS = c;
    43      }
    44
    45      @Override
    46      public Object visit(ASTCompilationUnit node, Object data) {
    47
    48  	isJUnit3Class = isJUnit4Class = false;
    49
    50  	isJUnit3Class = isJUnit3Class(node);
    51  	if (!isJUnit3Class) {
    52  	    isJUnit4Class = isJUnit4Class(node);
    53  	}
    54
    55  	if (isJUnit3Class || isJUnit4Class) {
    56  	    return super.visit(node, data);
    57  	}
    58  	return data;
    59      }
    60
    61      public boolean isJUnitMethod(ASTMethodDeclaration method, Object data) {
    62
    63  	if (!method.isPublic() || method.isAbstract() || method.isNative() || method.isStatic()) {
    64  	    return false; // skip various inapplicable method variations
    65  	}
    66
    67  	if (isJUnit3Class) {
    68  	    return isJUnit3Method(method);
    69  	} else {
    70  	    return isJUnit4Method(method);
    71  	}
    72      }
    73
    74      private boolean isJUnit4Method(ASTMethodDeclaration method) {
    75  	return doesNodeContainJUnitAnnotation(method.jjtGetParent());
    76      }
    77
    78      private boolean isJUnit3Method(ASTMethodDeclaration method) {
    79  	Node node = method.jjtGetChild(0);
    80  	if (node instanceof ASTTypeParameters) {
    81  	    node = method.jjtGetChild(1);
    82  	}
    83  	return ((ASTResultType) node).isVoid() && method.getMethodName().startsWith("test");
    84      }
    85
    86      private boolean isJUnit3Class(ASTCompilationUnit node) {
    87  	if (node.getType() != null && TypeHelper.isA(node, JUNIT3_CLASS)) {
    88  	    return true;
    89
    90  	} else if (node.getType() == null) {
    91  	    ASTClassOrInterfaceDeclaration cid = node.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class);
    92  	    if (cid == null) {
    93  		return false;
    94  	    }
    95  	    ASTExtendsList extendsList = cid.getFirstChildOfType(ASTExtendsList.class);
    96  	    if (extendsList == null) {
    97  		return false;
    98  	    }
    99  	    if (((ASTClassOrInterfaceType) extendsList.jjtGetChild(0)).getImage().endsWith("TestCase")) {
    100 		return true;
    101 	    }
    102 	    String className = cid.getImage();
    103 	    return className.endsWith("Test");
    104 	}
    105 	return false;
    106     }
    107
    108     private boolean isJUnit4Class(ASTCompilationUnit node) {
    109 	return doesNodeContainJUnitAnnotation(node);
    110     }
    111
    112     private boolean doesNodeContainJUnitAnnotation(Node node) {
    113         List<ASTAnnotation> annotations = node.findDescendantsOfType(ASTAnnotation.class);
    114         for (ASTAnnotation annotation : annotations) {
    115             Node annotationTypeNode = annotation.jjtGetChild(0);
    116             TypeNode annotationType = (TypeNode) annotationTypeNode;
    117             if (annotationType.getType() == null) {
    118                 ASTName name = annotationTypeNode.getFirstChildOfType(ASTName.class);
    119                 if (name != null && "Test".equals(name.getImage())) {
    120                     return true;
    121                 }
    122             } else if (annotationType.getType().equals(JUNIT4_CLASS)) {
    123                 return true;
    124             }
    125         }
    126         return false;
    127     }
    128 }