001: package net.sourceforge.pmd.rules.junit;
002:
003: import java.util.List;
004:
005: import net.sourceforge.pmd.AbstractJavaRule;
006: import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
007: import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
008: import net.sourceforge.pmd.ast.ASTCompilationUnit;
009: import net.sourceforge.pmd.ast.ASTExtendsList;
010: import net.sourceforge.pmd.ast.ASTMarkerAnnotation;
011: import net.sourceforge.pmd.ast.ASTMethodDeclaration;
012: import net.sourceforge.pmd.ast.ASTName;
013: import net.sourceforge.pmd.ast.ASTResultType;
014: import net.sourceforge.pmd.ast.ASTTypeParameters;
015: import net.sourceforge.pmd.ast.Node;
016: import net.sourceforge.pmd.ast.SimpleNode;
017: import net.sourceforge.pmd.typeresolution.TypeHelper;
018:
019: @SuppressWarnings("PMD.AvoidCatchingThrowable")
020: // Don't think we can otherwise here...
021: public abstract class AbstractJUnitRule extends AbstractJavaRule {
022:
023: public static Class junit4Class = null;
024:
025: public static Class junit3Class = null;
026:
027: private boolean isJUnit3Class;
028: private boolean isJUnit4Class;
029:
030: static {
031: try {
032: junit4Class = Class.forName("org.junit.Test");
033: } catch (Throwable t) {
034: junit4Class = null;
035: }
036:
037: try {
038: junit3Class = Class.forName("junit.framework.TestCase");
039: } catch (Throwable t) {
040: junit3Class = null;
041: }
042: }
043:
044: public Object visit(ASTCompilationUnit node, Object data) {
045:
046: isJUnit3Class = isJUnit4Class = false;
047:
048: isJUnit3Class = isJUnit3Class(node);
049: if (!isJUnit3Class) {
050: isJUnit4Class = isJUnit4Class(node);
051: }
052:
053: if (isJUnit3Class || isJUnit4Class) {
054: return super .visit(node, data);
055: }
056: return data;
057: }
058:
059: public boolean isJUnitMethod(ASTMethodDeclaration method,
060: Object data) {
061:
062: if (!method.isPublic() || method.isAbstract()
063: || method.isNative() || method.isStatic()) {
064: return false; // skip various inapplicable method variations
065: }
066:
067: if (isJUnit3Class) {
068: return isJUnit3Method(method);
069: } else {
070: return isJUnit4Method(method);
071: }
072: }
073:
074: private boolean isJUnit4Method(ASTMethodDeclaration method) {
075: return doesNodeContainJUnitAnnotation((SimpleNode) method
076: .jjtGetParent());
077: }
078:
079: private boolean isJUnit3Method(ASTMethodDeclaration method) {
080: Node node = method.jjtGetChild(0);
081: if (node instanceof ASTTypeParameters) {
082: node = method.jjtGetChild(1);
083: }
084: return ((ASTResultType) node).isVoid()
085: && method.getMethodName().startsWith("test");
086: }
087:
088: private boolean isJUnit3Class(ASTCompilationUnit node) {
089: if (node.getType() != null && TypeHelper.isA(node, junit3Class)) {
090: return true;
091:
092: } else if (node.getType() == null) {
093: ASTClassOrInterfaceDeclaration cid = node
094: .getFirstChildOfType(ASTClassOrInterfaceDeclaration.class);
095: if (cid == null) {
096: return false;
097: }
098: ASTExtendsList extendsList = cid
099: .getFirstChildOfType(ASTExtendsList.class);
100: if (extendsList == null) {
101: return false;
102: }
103: if (((ASTClassOrInterfaceType) extendsList.jjtGetChild(0))
104: .getImage().endsWith("TestCase")) {
105: return true;
106: }
107: String className = cid.getImage();
108: return className.endsWith("Test");
109: }
110: return false;
111: }
112:
113: private boolean isJUnit4Class(ASTCompilationUnit node) {
114: return doesNodeContainJUnitAnnotation(node);
115: }
116:
117: private boolean doesNodeContainJUnitAnnotation(SimpleNode node) {
118: List<ASTMarkerAnnotation> lstAnnotations = node
119: .findChildrenOfType(ASTMarkerAnnotation.class);
120: for (ASTMarkerAnnotation annotation : lstAnnotations) {
121: if (annotation.getType() == null) {
122: ASTName name = (ASTName) annotation.jjtGetChild(0);
123: if ("Test".equals(name.getImage())) {
124: return true;
125: }
126: } else if (annotation.getType().equals(junit4Class)) {
127: return true;
128: }
129: }
130: return false;
131: }
132:
133: }
|