Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 157   Methods: 5
NCLOC: 123   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DoubleCheckedLocking.java 56.2% 92.8% 100% 78.7%
coverage coverage
 1    /**
 2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 3    */
 4    package net.sourceforge.pmd.rules;
 5   
 6    import net.sourceforge.pmd.ast.ASTAssignmentOperator;
 7    import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
 8    import net.sourceforge.pmd.ast.ASTIfStatement;
 9    import net.sourceforge.pmd.ast.ASTLiteral;
 10    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 11    import net.sourceforge.pmd.ast.ASTName;
 12    import net.sourceforge.pmd.ast.ASTNullLiteral;
 13    import net.sourceforge.pmd.ast.ASTPrimaryExpression;
 14    import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
 15    import net.sourceforge.pmd.ast.ASTReferenceType;
 16    import net.sourceforge.pmd.ast.ASTReturnStatement;
 17    import net.sourceforge.pmd.ast.ASTStatementExpression;
 18    import net.sourceforge.pmd.ast.ASTSynchronizedStatement;
 19    import net.sourceforge.pmd.ast.ASTType;
 20    import net.sourceforge.pmd.ast.Node;
 21   
 22    import java.util.ArrayList;
 23    import java.util.List;
 24   
 25    /**
 26    * void method() {
 27    * if(x == null) {
 28    * synchronized(this){
 29    * if(x == null) {
 30    * x = new | method();
 31    * }
 32    * }
 33    * }
 34    * 1. The error is when one uses the value assigned within a synchronized
 35    * section, outside of a synchronized section.
 36    * if(x == null) is outside of synchronized section
 37    * x = new | method();
 38    * <p/>
 39    * <p/>
 40    * Very very specific check for double checked locking.
 41    *
 42    * @author CL Gilbert (dnoyeb@users.sourceforge.net)
 43    */
 44    public class DoubleCheckedLocking extends net.sourceforge.pmd.AbstractRule {
 45   
 46  4 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
 47  4 if (node.isInterface()) {
 48  1 return data;
 49    }
 50  3 return super.visit(node, data);
 51    }
 52   
 53  3 public Object visit(ASTMethodDeclaration node, Object data) {
 54  3 if (node.getResultType().isVoid()) {
 55  1 return super.visit(node, data);
 56    }
 57   
 58  2 ASTType typeNode = (ASTType) node.getResultType().jjtGetChild(0);
 59  2 if (typeNode.jjtGetNumChildren() == 0 || !(typeNode.jjtGetChild(0) instanceof ASTReferenceType)) {
 60  0 return super.visit(node, data);
 61    }
 62   
 63  2 List finder = new ArrayList();
 64  2 node.findChildrenOfType(ASTReturnStatement.class, finder, true);
 65  2 if (finder.size() != 1) {
 66  1 return super.visit(node, data);
 67    }
 68  1 ASTReturnStatement rs = (ASTReturnStatement) finder.get(0);
 69   
 70  1 finder.clear();
 71  1 rs.findChildrenOfType(ASTPrimaryExpression.class, finder, true);
 72  1 ASTPrimaryExpression ape = (ASTPrimaryExpression) finder.get(0);
 73  1 Node lastChild = ape.jjtGetChild(ape.jjtGetNumChildren() - 1);
 74  1 String returnVariableName = null;
 75  1 if (lastChild instanceof ASTPrimaryPrefix) {
 76  1 returnVariableName = getNameFromPrimaryPrefix((ASTPrimaryPrefix) lastChild);
 77    }
 78  1 if (returnVariableName == null) {
 79  0 return super.visit(node, data);
 80    }
 81  1 finder.clear();
 82  1 node.findChildrenOfType(ASTIfStatement.class, finder, true);
 83  1 if (finder.size() == 2) {
 84  1 ASTIfStatement is = (ASTIfStatement) finder.get(0);
 85  1 if (ifVerify(is, returnVariableName)) {
 86    //find synchronized
 87  1 finder.clear();
 88  1 is.findChildrenOfType(ASTSynchronizedStatement.class, finder, true);
 89  1 if (finder.size() == 1) {
 90  1 ASTSynchronizedStatement ss = (ASTSynchronizedStatement) finder.get(0);
 91  1 finder.clear();
 92  1 ss.findChildrenOfType(ASTIfStatement.class, finder, true);
 93  1 if (finder.size() == 1) {
 94  1 ASTIfStatement is2 = (ASTIfStatement) finder.get(0);
 95  1 if (ifVerify(is2, returnVariableName)) {
 96  1 finder.clear();
 97  1 is2.findChildrenOfType(ASTStatementExpression.class, finder, true);
 98  1 if (finder.size() == 1) {
 99  1 ASTStatementExpression se = (ASTStatementExpression) finder.get(0);
 100  1 if (se.jjtGetNumChildren() == 3) { //primaryExpression, AssignmentOperator, Expression
 101  1 if (se.jjtGetChild(0) instanceof ASTPrimaryExpression) {
 102  1 ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
 103  1 if (matchName(pe, returnVariableName)) {
 104  1 if (se.jjtGetChild(1) instanceof ASTAssignmentOperator) {
 105  1 addViolation(data, node);
 106    }
 107    }
 108    }
 109    }
 110    }
 111    }
 112    }
 113    }
 114    }
 115    }
 116  1 return super.visit(node, data);
 117    }
 118   
 119  2 private boolean ifVerify(ASTIfStatement is, String varname) {
 120  2 List finder = new ArrayList();
 121  2 is.findChildrenOfType(ASTPrimaryExpression.class, finder, true);
 122  2 if (finder.size() > 1) {
 123  2 ASTPrimaryExpression apeLeft = (ASTPrimaryExpression) finder.get(0);
 124  2 if (matchName(apeLeft, varname)) {
 125  2 ASTPrimaryExpression apeRight = (ASTPrimaryExpression) finder.get(1);
 126  2 if ((apeRight.jjtGetNumChildren() == 1) && (apeRight.jjtGetChild(0) instanceof ASTPrimaryPrefix)) {
 127  2 ASTPrimaryPrefix pp2 = (ASTPrimaryPrefix) apeRight.jjtGetChild(0);
 128  2 if ((pp2.jjtGetNumChildren() == 1) && (pp2.jjtGetChild(0) instanceof ASTLiteral)) {
 129  2 ASTLiteral lit = (ASTLiteral) pp2.jjtGetChild(0);
 130  2 if ((lit.jjtGetNumChildren() == 1) && (lit.jjtGetChild(0) instanceof ASTNullLiteral)) {
 131  2 return true;
 132    }
 133    }
 134    }
 135    }
 136    }
 137  0 return false;
 138    }
 139   
 140  3 private boolean matchName(ASTPrimaryExpression ape, String name) {
 141  3 if ((ape.jjtGetNumChildren() == 1) && (ape.jjtGetChild(0) instanceof ASTPrimaryPrefix)) {
 142  3 ASTPrimaryPrefix pp = (ASTPrimaryPrefix) ape.jjtGetChild(0);
 143  3 String name2 = getNameFromPrimaryPrefix(pp);
 144  3 if (name2 != null && name2.equals(name)) {
 145  3 return true;
 146    }
 147    }
 148  0 return false;
 149    }
 150   
 151  4 private String getNameFromPrimaryPrefix(ASTPrimaryPrefix pp) {
 152  4 if ((pp.jjtGetNumChildren() == 1) && (pp.jjtGetChild(0) instanceof ASTName)) {
 153  4 return ((ASTName) pp.jjtGetChild(0)).getImage();
 154    }
 155  0 return null;
 156    }
 157    }