Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 120 |  | Methods: | 4
| NCLOC: | 95 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
NonThreadSafeSingleton.java | 83.3% | 87.5% | 75% | 85.3% |

1 |  | /**
2 |  | * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 |  | */
4 |  | package net.sourceforge.pmd.rules.design;
5 |  |
6 |  | import java.util.HashMap;
7 |  | import java.util.Iterator;
8 |  | import java.util.List;
9 |  | import java.util.Map;
10 |  |
11 |  | import net.sourceforge.pmd.AbstractRule;
12 |  | import net.sourceforge.pmd.PropertyDescriptor;
13 |  | import net.sourceforge.pmd.ast.ASTAssignmentOperator;
14 |  | import net.sourceforge.pmd.ast.ASTCompilationUnit;
15 |  | import net.sourceforge.pmd.ast.ASTFieldDeclaration;
16 |  | import net.sourceforge.pmd.ast.ASTIfStatement;
17 |  | import net.sourceforge.pmd.ast.ASTMethodDeclaration;
18 |  | import net.sourceforge.pmd.ast.ASTName;
19 |  | import net.sourceforge.pmd.ast.ASTNullLiteral;
20 |  | import net.sourceforge.pmd.ast.ASTPrimaryExpression;
21 |  | import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
22 |  | import net.sourceforge.pmd.ast.ASTPrimarySuffix;
23 |  | import net.sourceforge.pmd.ast.ASTStatementExpression;
24 |  | import net.sourceforge.pmd.ast.ASTSynchronizedStatement;
25 |  | import net.sourceforge.pmd.properties.BooleanProperty;
26 |  |
27 |  | public class NonThreadSafeSingleton extends AbstractRule {
28 |  |
29 |  | private Map fieldDecls = new HashMap();
30 |  |
31 |  | private boolean checkNonStaticMethods = true;
32 |  | private boolean checkNonStaticFields = true;
33 |  |
34 |  | private static final PropertyDescriptor checkNonStaticMethodsDescriptor = new BooleanProperty(
35 |  | "checkNonStaticMethods", "Check for non-static methods.", true, 1.0f
36 |  | );
37 |  | private static final PropertyDescriptor checkNonStaticFieldsDescriptor = new BooleanProperty(
38 |  | "checkNonStaticFields", "Check for non-static fields.", true, 2.0f
39 |  | );
40 |  |
41 |  | private static final Map propertyDescriptorsByName = asFixedMap(new PropertyDescriptor[] {
42 |  | checkNonStaticMethodsDescriptor, checkNonStaticFieldsDescriptor
43 |  | });
44 |  |
45 |  | // public NonThreadSafeSingleton() {
46 |  | // checkNonStaticMethods = super.getBooleanProperty("checkNonStaticMethods");
47 |  | // checkNonStaticFields = super.getBooleanProperty("checkNonStaticFields");
48 |  | // }
49 |  |
50 | 8 | public Object visit(ASTCompilationUnit node, Object data) {
51 | 8 | fieldDecls.clear();
52 | 8 | checkNonStaticMethods = getBooleanProperty(checkNonStaticMethodsDescriptor);
53 | 8 | checkNonStaticFields = getBooleanProperty(checkNonStaticFieldsDescriptor);
54 | 8 | return super.visit(node, data);
55 |  | }
56 |  |
57 | 10 | public Object visit(ASTFieldDeclaration node, Object data) {
58 | 10 | if (checkNonStaticFields || node.isStatic()) {
59 | 9 | fieldDecls.put(node.getVariableName(), node);
60 |  | }
61 | 10 | return super.visit(node, data);
62 |  | }
63 |  |
64 | 8 | public Object visit(ASTMethodDeclaration node, Object data) {
65 |  |
66 | 8 | if ((checkNonStaticMethods && !node.isStatic()) || node.isSynchronized()) {
67 | 2 | return super.visit(node, data);
68 |  | }
69 |  |
70 | 6 | List ifStatements = node.findChildrenOfType(ASTIfStatement.class);
71 | 6 | for (Iterator iter = ifStatements.iterator(); iter.hasNext();) {
72 | 7 | ASTIfStatement ifStatement = (ASTIfStatement) iter.next();
73 | 7 | if (ifStatement.getFirstParentOfType(ASTSynchronizedStatement.class) == null) {
74 | 6 | ASTNullLiteral NullLiteral = (ASTNullLiteral) ifStatement.getFirstChildOfType(ASTNullLiteral.class);
75 |  |
76 | 6 | if (NullLiteral == null) {
77 | 0 | continue;
78 |  | }
79 | 6 | ASTName Name = (ASTName) ifStatement.getFirstChildOfType(ASTName.class);
80 | 6 | if (Name == null || !fieldDecls.containsKey(Name.getImage())) {
81 | 1 | continue;
82 |  | }
83 | 5 | List assigmnents = ifStatement.findChildrenOfType(ASTAssignmentOperator.class);
84 | 5 | boolean violation = false;
85 | 5 | for (int ix = 0; ix < assigmnents.size(); ix++) {
86 | 6 | ASTAssignmentOperator oper = (ASTAssignmentOperator) assigmnents.get(ix);
87 | 6 | if (!oper.jjtGetParent().getClass().equals(ASTStatementExpression.class)) {
88 | 0 | continue;
89 |  | }
90 | 6 | ASTStatementExpression expr = (ASTStatementExpression) oper.jjtGetParent();
91 | 6 | if (expr.jjtGetChild(0).getClass().equals(ASTPrimaryExpression.class) && ((ASTPrimaryExpression) expr.jjtGetChild(0)).jjtGetChild(0).getClass().equals(ASTPrimaryPrefix.class)) {
92 | 6 | ASTPrimaryPrefix pp = (ASTPrimaryPrefix) ((ASTPrimaryExpression) expr.jjtGetChild(0)).jjtGetChild(0);
93 | 6 | String name = null;
94 | 6 | if (pp.usesThisModifier()) {
95 | 0 | ASTPrimarySuffix priSuf = (ASTPrimarySuffix)expr.getFirstChildOfType(ASTPrimarySuffix.class);
96 | 0 | name = priSuf.getImage();
97 |  | } else {
98 | 6 | ASTName astName = (ASTName) pp.jjtGetChild(0);
99 | 6 | name = astName.getImage();
100 |  | }
101 | 6 | if (fieldDecls.containsKey(name)) {
102 | 5 | violation = true;
103 |  | }
104 |  | }
105 |  | }
106 | 5 | if (violation) {
107 | 4 | addViolation(data, ifStatement);
108 |  | }
109 |  | }
110 |  | }
111 | 6 | return super.visit(node, data);
112 |  | }
113 |  |
114 |  | /**
115 |  | * @return Map
116 |  | */
117 | 0 | protected Map propertiesByName() {
118 | 0 | return propertyDescriptorsByName;
119 |  | }
120 |  | }