View Javadoc

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") // Don't think we can otherwise here...
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; // skip various inapplicable method variations
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 }