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 }