Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 193 |  | Methods: | 10
| NCLOC: | 126 |  | Classes: | 2
Source file | Conditionals | Statements | Methods | TOTAL
DaaRule.java | 87.5% | 94.5% | 80% | 91% |

1 |  | /*
2 |  | * Created on 20.07.2004
3 |  | */
4 |  | package net.sourceforge.pmd.dfa;
5 |  |
6 |  | import net.sourceforge.pmd.AbstractRule;
7 |  | import net.sourceforge.pmd.PropertyDescriptor;
8 |  | import net.sourceforge.pmd.RuleContext;
9 |  | import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
10 |  | import net.sourceforge.pmd.ast.ASTMethodDeclaration;
11 |  | import net.sourceforge.pmd.ast.SimpleNode;
12 |  | import net.sourceforge.pmd.dfa.pathfinder.CurrentPath;
13 |  | import net.sourceforge.pmd.dfa.pathfinder.DAAPathFinder;
14 |  | import net.sourceforge.pmd.dfa.pathfinder.Executable;
15 |  | import net.sourceforge.pmd.dfa.variableaccess.VariableAccess;
16 |  | import net.sourceforge.pmd.properties.IntegerProperty;
17 |  |
18 |  | import java.text.MessageFormat;
19 |  | import java.util.ArrayList;
20 |  | import java.util.Hashtable;
21 |  | import java.util.Iterator;
22 |  | import java.util.List;
23 |  | import java.util.Map;
24 |  |
25 |  | /**
26 |  | * Starts path search for each method and runs code if found.
27 |  | *
28 |  | * @author raik
29 |  | * @author Sven Jacob
30 |  | */
31 |  | public class DaaRule extends AbstractRule implements Executable {
32 |  | private RuleContext rc;
33 |  | private List daaRuleViolations;
34 |  | private int maxRuleViolations;
35 |  | private int currentRuleViolationCount;
36 |  |
37 |  | private static final PropertyDescriptor maxPathDescriptor = new IntegerProperty(
38 |  | "maxpaths", "Maximum number of paths per method", 5000, 1.0f
39 |  | );
40 |  |
41 |  | private static final PropertyDescriptor maxViolationsDescriptor = new IntegerProperty(
42 |  | "maxviolations", "Maximum number of anomalys per class", 1000, 2.0f
43 |  | );
44 |  |
45 |  | private static final Map propertyDescriptorsByName = asFixedMap(
46 |  | new PropertyDescriptor[] { maxPathDescriptor, maxViolationsDescriptor});
47 |  |
48 | 0 | protected Map propertiesByName() {
49 | 0 | return propertyDescriptorsByName;
50 |  | }
51 |  |
52 |  | private static class Usage {
53 |  | public int accessType;
54 |  | public IDataFlowNode node;
55 |  |
56 | 45 | public Usage(int accessType, IDataFlowNode node) {
57 | 45 | this.accessType = accessType;
58 | 45 | this.node = node;
59 |  | }
60 |  |
61 | 0 | public String toString() {
62 | 0 | return "accessType = " + accessType + ", line = " + node.getLine();
63 |  | }
64 |  | }
65 |  |
66 | 5 | public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
67 | 5 | this.maxRuleViolations = getIntProperty(maxViolationsDescriptor);
68 | 5 | this.currentRuleViolationCount = 0;
69 | 5 | return super.visit(node, data);
70 |  | }
71 |  |
72 | 5 | public Object visit(ASTMethodDeclaration methodDeclaration, Object data) {
73 | 5 | this.rc = (RuleContext) data;
74 | 5 | this.daaRuleViolations = new ArrayList();
75 |  |
76 | 5 | final IDataFlowNode node = (IDataFlowNode) methodDeclaration.getDataFlowNode().getFlow().get(0);
77 |  |
78 | 5 | final DAAPathFinder pathFinder = new DAAPathFinder(node, this, getIntProperty(maxPathDescriptor));
79 | 5 | pathFinder.run();
80 |  |
81 | 5 | super.visit(methodDeclaration, data);
82 | 5 | return data;
83 |  | }
84 |  |
85 | 7 | public void execute(CurrentPath path) {
86 | 7 | if (maxNumberOfViolationsReached()) {
87 |  | // dont execute this path if the limit is already reached
88 | 0 | return;
89 |  | }
90 |  |
91 | 7 | final Hashtable hash = new Hashtable();
92 |  |
93 | 7 | final Iterator pathIterator = path.iterator();
94 | 7 | while (pathIterator.hasNext()) {
95 |  | // iterate all nodes in this path
96 | 42 | IDataFlowNode inode = (IDataFlowNode) pathIterator.next();
97 | 42 | if (inode.getVariableAccess() != null) {
98 |  | // iterate all variables of this node
99 | 42 | for (int g = 0; g < inode.getVariableAccess().size(); g++) {
100 | 45 | final VariableAccess va = (VariableAccess) inode.getVariableAccess().get(g);
101 |  |
102 |  | // get the last usage of the current variable
103 | 45 | final Usage lastUsage = (Usage) hash.get(va.getVariableName());
104 | 45 | if (lastUsage != null) {
105 |  | // there was a usage to this variable before
106 | 34 | checkVariableAccess(inode, va, lastUsage);
107 |  | }
108 |  |
109 | 45 | final Usage newUsage = new Usage(va.getAccessType(), inode);
110 |  | // put the new usage for the variable
111 | 45 | hash.put(va.getVariableName(), newUsage);
112 |  | }
113 |  | }
114 |  | }
115 |  | }
116 |  |
117 |  | /**
118 |  | * @param inode
119 |  | * @param va
120 |  | * @param o
121 |  | */
122 | 34 | private void checkVariableAccess(IDataFlowNode inode, VariableAccess va, final Usage u) {
123 |  | // get the start and end line
124 | 34 | final int startLine = u.node.getLine();
125 | 34 | final int endLine = inode.getLine();
126 |  |
127 | 34 | final SimpleNode lastNode = inode.getSimpleNode();
128 | 34 | final SimpleNode firstNode = u.node.getSimpleNode();
129 |  |
130 | 34 | if (va.accessTypeMatches(u.accessType) && va.isDefinition() ) { // DD
131 | 2 | addDaaViolation(rc, lastNode, "DD", va.getVariableName(), startLine, endLine);
132 | 32 | } else if (u.accessType == VariableAccess.UNDEFINITION && va.isReference()) { // UR
133 | 1 | addDaaViolation(rc, lastNode, "UR", va.getVariableName(), startLine, endLine);
134 | 31 | } else if (u.accessType == VariableAccess.DEFINITION && va.isUndefinition()) { // DU
135 | 5 | addDaaViolation(rc, firstNode, "DU", va.getVariableName(), startLine, endLine);
136 |  | }
137 |  | }
138 |  |
139 |  | /**
140 |  | * Adds a daa violation to the report.
141 |  | *
142 |  | * @param ctx the RuleContext
143 |  | * @param node the node that produces the violation
144 |  | * @param msg specific message to put in the report
145 |  | */
146 | 8 | private final void addDaaViolation(Object data, SimpleNode node, String type, String var, int startLine, int endLine) {
147 | 8 | if (!maxNumberOfViolationsReached()
148 |  | && !violationAlreadyExists(type, var, startLine, endLine)
149 |  | && node != null) {
150 | 7 | final RuleContext ctx = (RuleContext) data;
151 | 7 | final Object[] params = new Object[] { type, var, new Integer(startLine), new Integer(endLine) };
152 | 7 | String msg = type;
153 | 7 | if (getMessage() != null) {
154 | 7 | msg = MessageFormat.format(getMessage(), params);
155 |  | }
156 | 7 | final DaaRuleViolation violation = new DaaRuleViolation(this, ctx, node, type, msg, var, startLine, endLine);
157 | 7 | ctx.getReport().addRuleViolation(violation);
158 | 7 | this.daaRuleViolations.add(violation);
159 | 7 | this.currentRuleViolationCount++;
160 |  | }
161 |  | }
162 |  |
163 |  | /**
164 |  | * Maximum number of violations was already reached?
165 |  | * @return
166 |  | */
167 | 15 | private boolean maxNumberOfViolationsReached() {
168 | 15 | return this.currentRuleViolationCount >= this.maxRuleViolations;
169 |  | }
170 |  |
171 |  | /**
172 |  | * Checks if a violation already exists.
173 |  | * This is needed because on the different paths same anomalies can occur.
174 |  | * @param type
175 |  | * @param var
176 |  | * @param startLine
177 |  | * @param endLine
178 |  | * @return true if the violation already was added to the report
179 |  | */
180 | 8 | private boolean violationAlreadyExists(String type, String var, int startLine, int endLine) {
181 | 8 | final Iterator violationIterator = this.daaRuleViolations.iterator();
182 | 8 | while (violationIterator.hasNext()) {
183 | 8 | final DaaRuleViolation violation = (DaaRuleViolation)violationIterator.next();
184 | 8 | if ((violation.getBeginLine() == startLine)
185 |  | && (violation.getEndLine() == endLine)
186 |  | && violation.getType().equals(type)
187 |  | && violation.getVariableName().equals(var)) {
188 | 1 | return true;
189 |  | }
190 |  | }
191 | 7 | return false;
192 |  | }
193 |  | }