1 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 44 public class DoubleCheckedLocking extends net.sourceforge.pmd.AbstractRule { 45 46 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { 47 if (node.isInterface()) { 48 return data; 49 } 50 return super.visit(node, data); 51 } 52 53 public Object visit(ASTMethodDeclaration node, Object data) { 54 if (node.getResultType().isVoid()) { 55 return super.visit(node, data); 56 } 57 58 ASTType typeNode = (ASTType) node.getResultType().jjtGetChild(0); 59 if (typeNode.jjtGetNumChildren() == 0 || !(typeNode.jjtGetChild(0) instanceof ASTReferenceType)) { 60 return super.visit(node, data); 61 } 62 63 List finder = new ArrayList (); 64 node.findChildrenOfType(ASTReturnStatement.class, finder, true); 65 if (finder.size() != 1) { 66 return super.visit(node, data); 67 } 68 ASTReturnStatement rs = (ASTReturnStatement) finder.get(0); 69 70 finder.clear(); 71 rs.findChildrenOfType(ASTPrimaryExpression.class, finder, true); 72 ASTPrimaryExpression ape = (ASTPrimaryExpression) finder.get(0); 73 Node lastChild = ape.jjtGetChild(ape.jjtGetNumChildren() - 1); 74 String returnVariableName = null; 75 if (lastChild instanceof ASTPrimaryPrefix) { 76 returnVariableName = getNameFromPrimaryPrefix((ASTPrimaryPrefix) lastChild); 77 } 78 if (returnVariableName == null) { 79 return super.visit(node, data); 80 } 81 finder.clear(); 82 node.findChildrenOfType(ASTIfStatement.class, finder, true); 83 if (finder.size() == 2) { 84 ASTIfStatement is = (ASTIfStatement) finder.get(0); 85 if (ifVerify(is, returnVariableName)) { 86 finder.clear(); 88 is.findChildrenOfType(ASTSynchronizedStatement.class, finder, true); 89 if (finder.size() == 1) { 90 ASTSynchronizedStatement ss = (ASTSynchronizedStatement) finder.get(0); 91 finder.clear(); 92 ss.findChildrenOfType(ASTIfStatement.class, finder, true); 93 if (finder.size() == 1) { 94 ASTIfStatement is2 = (ASTIfStatement) finder.get(0); 95 if (ifVerify(is2, returnVariableName)) { 96 finder.clear(); 97 is2.findChildrenOfType(ASTStatementExpression.class, finder, true); 98 if (finder.size() == 1) { 99 ASTStatementExpression se = (ASTStatementExpression) finder.get(0); 100 if (se.jjtGetNumChildren() == 3) { if (se.jjtGetChild(0) instanceof ASTPrimaryExpression) { 102 ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0); 103 if (matchName(pe, returnVariableName)) { 104 if (se.jjtGetChild(1) instanceof ASTAssignmentOperator) { 105 addViolation(data, node); 106 } 107 } 108 } 109 } 110 } 111 } 112 } 113 } 114 } 115 } 116 return super.visit(node, data); 117 } 118 119 private boolean ifVerify(ASTIfStatement is, String varname) { 120 List finder = new ArrayList (); 121 is.findChildrenOfType(ASTPrimaryExpression.class, finder, true); 122 if (finder.size() > 1) { 123 ASTPrimaryExpression apeLeft = (ASTPrimaryExpression) finder.get(0); 124 if (matchName(apeLeft, varname)) { 125 ASTPrimaryExpression apeRight = (ASTPrimaryExpression) finder.get(1); 126 if ((apeRight.jjtGetNumChildren() == 1) && (apeRight.jjtGetChild(0) instanceof ASTPrimaryPrefix)) { 127 ASTPrimaryPrefix pp2 = (ASTPrimaryPrefix) apeRight.jjtGetChild(0); 128 if ((pp2.jjtGetNumChildren() == 1) && (pp2.jjtGetChild(0) instanceof ASTLiteral)) { 129 ASTLiteral lit = (ASTLiteral) pp2.jjtGetChild(0); 130 if ((lit.jjtGetNumChildren() == 1) && (lit.jjtGetChild(0) instanceof ASTNullLiteral)) { 131 return true; 132 } 133 } 134 } 135 } 136 } 137 return false; 138 } 139 140 private boolean matchName(ASTPrimaryExpression ape, String name) { 141 if ((ape.jjtGetNumChildren() == 1) && (ape.jjtGetChild(0) instanceof ASTPrimaryPrefix)) { 142 ASTPrimaryPrefix pp = (ASTPrimaryPrefix) ape.jjtGetChild(0); 143 String name2 = getNameFromPrimaryPrefix(pp); 144 if (name2 != null && name2.equals(name)) { 145 return true; 146 } 147 } 148 return false; 149 } 150 151 private String getNameFromPrimaryPrefix(ASTPrimaryPrefix pp) { 152 if ((pp.jjtGetNumChildren() == 1) && (pp.jjtGetChild(0) instanceof ASTName)) { 153 return ((ASTName) pp.jjtGetChild(0)).getImage(); 154 } 155 return null; 156 } 157 } 158 | Popular Tags |