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