/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.design;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
public class SingletonClassReturningNewInstanceRule extends AbstractJavaRule {
@Override
public Object visit(ASTMethodDeclaration node, Object data) {
boolean violation = false;
String localVarName = null;
String returnVariableName = null;
if (node.getResultType().isVoid()) {
return super.visit(node, data);
}
if ("getInstance".equals(node.getMethodName())) {
List<ASTReturnStatement> rsl = node.findDescendantsOfType(ASTReturnStatement.class);
if (rsl.isEmpty()) {
return super.visit(node, data);
} else {
for (ASTReturnStatement rs : rsl) {
List<ASTPrimaryExpression> pel = rs.findDescendantsOfType(ASTPrimaryExpression.class);
ASTPrimaryExpression ape = pel.get(0);
if (ape.getFirstDescendantOfType(ASTAllocationExpression.class) != null) {
violation = true;
break;
}
}
}
/*
* public class Singleton {
*
* private static Singleton m_instance=null;
*
* public static Singleton getInstance() {
*
* Singleton m_instance=null;
*
* if ( m_instance == null ) { synchronized(Singleton.class) {
* if(m_instance == null) { m_instance = new Singleton(); } } }
* return m_instance; } }
*/
List<ASTBlockStatement> astBlockStatements = node.findDescendantsOfType(ASTBlockStatement.class);
returnVariableName = getReturnVariableName(node);
if (astBlockStatements.size() != 0) {
for (ASTBlockStatement blockStatement : astBlockStatements) {
if (blockStatement.hasDescendantOfType(ASTLocalVariableDeclaration.class)) {
List<ASTLocalVariableDeclaration> lVarList = blockStatement
.findDescendantsOfType(ASTLocalVariableDeclaration.class);
if (!lVarList.isEmpty()) {
for (ASTLocalVariableDeclaration localVar : lVarList) {
localVarName = localVar.getVariableName();
if (returnVariableName != null && returnVariableName.equals(localVarName)) {
violation = true;
break;
}
}
}
}
}
}
}
if (violation) {
addViolation(data, node);
}
return super.visit(node, data);
}
private String getReturnVariableName(ASTMethodDeclaration node) {
List<ASTReturnStatement> rsl = node.findDescendantsOfType(ASTReturnStatement.class);
ASTReturnStatement rs = rsl.get(0);
List<ASTPrimaryExpression> pel = rs.findDescendantsOfType(ASTPrimaryExpression.class);
ASTPrimaryExpression ape = pel.get(0);
Node lastChild = ape.jjtGetChild(0);
String returnVariableName = null;
if (lastChild instanceof ASTPrimaryPrefix) {
returnVariableName = getNameFromPrimaryPrefix((ASTPrimaryPrefix) lastChild);
}
/*
* if(lastChild instanceof ASTPrimarySuffix){ returnVariableName =
* getNameFromPrimarySuffix((ASTPrimarySuffix) lastChild); }
*/
return returnVariableName;
}
private String getNameFromPrimaryPrefix(ASTPrimaryPrefix pp) {
if ((pp.jjtGetNumChildren() == 1) && (pp.jjtGetChild(0) instanceof ASTName)) {
return ((ASTName) pp.jjtGetChild(0)).getImage();
}
return null;
}
}