KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > dfa > DaaRule


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 JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
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 JavaDoc 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 JavaDoc propertyDescriptorsByName = asFixedMap(
46             new PropertyDescriptor[] { maxPathDescriptor, maxViolationsDescriptor});
47             
48     protected Map JavaDoc propertiesByName() {
49         return propertyDescriptorsByName;
50     }
51     
52     private static class Usage {
53         public int accessType;
54         public IDataFlowNode node;
55
56         public Usage(int accessType, IDataFlowNode node) {
57             this.accessType = accessType;
58             this.node = node;
59         }
60
61         public String JavaDoc toString() {
62             return "accessType = " + accessType + ", line = " + node.getLine();
63         }
64     }
65     
66     public Object JavaDoc visit(ASTClassOrInterfaceDeclaration node, Object JavaDoc data) {
67         this.maxRuleViolations = getIntProperty(maxViolationsDescriptor);
68         this.currentRuleViolationCount = 0;
69         return super.visit(node, data);
70     }
71     
72     public Object JavaDoc visit(ASTMethodDeclaration methodDeclaration, Object JavaDoc data) {
73         this.rc = (RuleContext) data;
74         this.daaRuleViolations = new ArrayList JavaDoc();
75         
76         final IDataFlowNode node = (IDataFlowNode) methodDeclaration.getDataFlowNode().getFlow().get(0);
77         
78         final DAAPathFinder pathFinder = new DAAPathFinder(node, this, getIntProperty(maxPathDescriptor));
79         pathFinder.run();
80
81         super.visit(methodDeclaration, data);
82         return data;
83     }
84
85     public void execute(CurrentPath path) {
86         if (maxNumberOfViolationsReached()) {
87             // dont execute this path if the limit is already reached
88
return;
89         }
90         
91         final Hashtable JavaDoc hash = new Hashtable JavaDoc();
92         
93         final Iterator JavaDoc pathIterator = path.iterator();
94         while (pathIterator.hasNext()) {
95             // iterate all nodes in this path
96
IDataFlowNode inode = (IDataFlowNode) pathIterator.next();
97             if (inode.getVariableAccess() != null) {
98                 // iterate all variables of this node
99
for (int g = 0; g < inode.getVariableAccess().size(); g++) {
100                     final VariableAccess va = (VariableAccess) inode.getVariableAccess().get(g);
101                     
102                     // get the last usage of the current variable
103
final Usage lastUsage = (Usage) hash.get(va.getVariableName());
104                     if (lastUsage != null) {
105                         // there was a usage to this variable before
106
checkVariableAccess(inode, va, lastUsage);
107                     }
108                     
109                     final Usage newUsage = new Usage(va.getAccessType(), inode);
110                     // put the new usage for the variable
111
hash.put(va.getVariableName(), newUsage);
112                 }
113             }
114         }
115     }
116
117     /**
118      * @param inode
119      * @param va
120      * @param o
121      */

122     private void checkVariableAccess(IDataFlowNode inode, VariableAccess va, final Usage u) {
123         // get the start and end line
124
final int startLine = u.node.getLine();
125         final int endLine = inode.getLine();
126         
127         final SimpleNode lastNode = inode.getSimpleNode();
128         final SimpleNode firstNode = u.node.getSimpleNode();
129         
130         if (va.accessTypeMatches(u.accessType) && va.isDefinition() ) { // DD
131
addDaaViolation(rc, lastNode, "DD", va.getVariableName(), startLine, endLine);
132         } else if (u.accessType == VariableAccess.UNDEFINITION && va.isReference()) { // UR
133
addDaaViolation(rc, lastNode, "UR", va.getVariableName(), startLine, endLine);
134         } else if (u.accessType == VariableAccess.DEFINITION && va.isUndefinition()) { // DU
135
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     private final void addDaaViolation(Object JavaDoc data, SimpleNode node, String JavaDoc type, String JavaDoc var, int startLine, int endLine) {
147         if (!maxNumberOfViolationsReached()
148                 && !violationAlreadyExists(type, var, startLine, endLine)
149                 && node != null) {
150             final RuleContext ctx = (RuleContext) data;
151             final Object JavaDoc[] params = new Object JavaDoc[] { type, var, new Integer JavaDoc(startLine), new Integer JavaDoc(endLine) };
152             String JavaDoc msg = type;
153             if (getMessage() != null) {
154                 msg = MessageFormat.format(getMessage(), params);
155             }
156             final DaaRuleViolation violation = new DaaRuleViolation(this, ctx, node, type, msg, var, startLine, endLine);
157             ctx.getReport().addRuleViolation(violation);
158             this.daaRuleViolations.add(violation);
159             this.currentRuleViolationCount++;
160       }
161     }
162
163     /**
164      * Maximum number of violations was already reached?
165      * @return
166      */

167     private boolean maxNumberOfViolationsReached() {
168         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     private boolean violationAlreadyExists(String JavaDoc type, String JavaDoc var, int startLine, int endLine) {
181         final Iterator JavaDoc violationIterator = this.daaRuleViolations.iterator();
182         while (violationIterator.hasNext()) {
183             final DaaRuleViolation violation = (DaaRuleViolation)violationIterator.next();
184             if ((violation.getBeginLine() == startLine)
185                     && (violation.getEndLine() == endLine)
186                     && violation.getType().equals(type)
187                     && violation.getVariableName().equals(var)) {
188                 return true;
189             }
190         }
191         return false;
192     }
193 }
194
Popular Tags