KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > detect > FindSelfComparison2


1 package edu.umd.cs.findbugs.detect;
2
3 import static org.apache.bcel.Constants.*;
4
5 import java.util.BitSet JavaDoc;
6 import java.util.Iterator JavaDoc;
7
8 import org.apache.bcel.classfile.Method;
9 import org.apache.bcel.generic.ConstantPoolGen;
10 import org.apache.bcel.generic.Instruction;
11 import org.apache.bcel.generic.InvokeInstruction;
12 import org.apache.bcel.generic.MethodGen;
13
14 import edu.umd.cs.findbugs.BugAnnotation;
15 import edu.umd.cs.findbugs.BugInstance;
16 import edu.umd.cs.findbugs.BugReporter;
17 import edu.umd.cs.findbugs.Detector;
18 import edu.umd.cs.findbugs.FieldAnnotation;
19 import edu.umd.cs.findbugs.LocalVariableAnnotation;
20 import edu.umd.cs.findbugs.SourceLineAnnotation;
21 import edu.umd.cs.findbugs.SystemProperties;
22 import edu.umd.cs.findbugs.ba.CFG;
23 import edu.umd.cs.findbugs.ba.CFGBuilderException;
24 import edu.umd.cs.findbugs.ba.ClassContext;
25 import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
26 import edu.umd.cs.findbugs.ba.Location;
27 import edu.umd.cs.findbugs.ba.MethodUnprofitableException;
28 import edu.umd.cs.findbugs.ba.SignatureParser;
29 import edu.umd.cs.findbugs.ba.XFactory;
30 import edu.umd.cs.findbugs.ba.XField;
31 import edu.umd.cs.findbugs.ba.vna.ValueNumber;
32 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
33 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
34
35 public class FindSelfComparison2 implements Detector {
36
37     private BugReporter bugReporter;
38
39     public FindSelfComparison2(BugReporter bugReporter) {
40         this.bugReporter = bugReporter;
41     }
42
43     public void visitClassContext(ClassContext classContext) {
44         Method[] methodList = classContext.getJavaClass().getMethods();
45
46         for (Method method : methodList) {
47             if (method.getCode() == null)
48                 continue;
49
50             try {
51                 analyzeMethod(classContext, method);
52             } catch (MethodUnprofitableException mue) {
53                 if (SystemProperties.getBoolean("unprofitable.debug")) // otherwise don't report
54
bugReporter.logError("skipping unprofitable method in " + getClass().getName());
55             } catch (CFGBuilderException e) {
56                 bugReporter.logError("Detector " + this.getClass().getName()
57                         + " caught exception", e);
58             } catch (DataflowAnalysisException e) {
59                 bugReporter.logError("Detector " + this.getClass().getName()
60                         + " caught exception", e);
61             }
62         }
63     }
64
65     private void analyzeMethod(ClassContext classContext, Method method)
66             throws CFGBuilderException, DataflowAnalysisException {
67         CFG cfg = classContext.getCFG(method);
68         ValueNumberDataflow valueNumberDataflow = classContext
69                 .getValueNumberDataflow(method);
70         ConstantPoolGen cpg = classContext.getConstantPoolGen();
71         MethodGen methodGen = classContext.getMethodGen(method);
72         String JavaDoc sourceFile = classContext.getJavaClass().getSourceFileName();
73
74         for (Iterator JavaDoc<Location> i = cfg.locationIterator(); i.hasNext();) {
75             Location location = i.next();
76
77             Instruction ins = location.getHandle().getInstruction();
78             switch(ins.getOpcode()) {
79             case INVOKEVIRTUAL:
80             case INVOKEINTERFACE:
81                 InvokeInstruction iins = (InvokeInstruction) ins;
82                 String JavaDoc invoking = iins.getName(cpg);
83                 if (invoking.equals("equals") || invoking.equals("compareTo")) {
84                 if (methodGen.getName().toLowerCase().indexOf("test") >= 0) break;
85                 if (methodGen.getClassName().toLowerCase().indexOf("test") >= 0) break;
86                 if (classContext.getJavaClass().getSuperclassName().toLowerCase().indexOf("test") >= 0) break;
87                 
88                String JavaDoc sig = iins.getSignature(cpg);
89                
90                SignatureParser parser = new SignatureParser(sig);
91                if (parser.getNumParameters() == 1 &&
92                        (invoking.equals("equals") && sig.endsWith(";)Z")
93                        || invoking.equals("compareTo") && sig.endsWith(";)I")))
94                    checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPARISON", methodGen, sourceFile);
95
96        
97                 }
98                 break;
99                
100             case LOR:
101             case LAND:
102             case LXOR:
103             case LSUB:
104             case IOR:
105             case IAND:
106             case IXOR:
107             case ISUB:
108                 checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPUTATION", methodGen, sourceFile);
109                 break;
110             case FCMPG:
111             case DCMPG:
112             case DCMPL:
113             case FCMPL:
114                 break;
115             case LCMP:
116             case IF_ACMPEQ:
117             case IF_ACMPNE:
118             case IF_ICMPNE:
119             case IF_ICMPEQ:
120             case IF_ICMPGT:
121             case IF_ICMPLE:
122             case IF_ICMPLT:
123             case IF_ICMPGE:
124                 checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPARISON", methodGen, sourceFile);
125
126             }
127
128
129         }
130     }
131
132     /**
133      * @param classContext TODO
134      * @param location
135      * @param methodGen TODO
136      * @param sourceFile TODO
137      * @param string
138      * @throws DataflowAnalysisException
139      */

140     private void checkForSelfOperation(ClassContext classContext, Location location, ValueNumberDataflow valueNumberDataflow, String JavaDoc op, MethodGen methodGen, String JavaDoc sourceFile) throws DataflowAnalysisException {
141         ValueNumberFrame frame = valueNumberDataflow.getFactAtLocation(location);
142         if (!frame.isValid()) return;
143         Instruction ins = location.getHandle().getInstruction();
144         int opcode = ins.getOpcode();
145         int offset = 1;
146         if (opcode == LCMP || opcode == LXOR || opcode == LAND || opcode == LOR || opcode == LSUB)
147             offset = 2;
148         ValueNumber v0 = frame.getStackValue(0);
149         ValueNumber v1 = frame.getStackValue(offset);
150         if (!v1.equals(v0)) return;
151
152         int priority = HIGH_PRIORITY;
153         if (opcode == ISUB || opcode == LSUB || opcode == INVOKEINTERFACE || opcode == INVOKEVIRTUAL)
154             priority = NORMAL_PRIORITY;
155         XField field = FindNullDeref.findXFieldFromValueNumber(methodGen.getMethod(), location, v0, frame);
156         BugAnnotation annotation;
157         String JavaDoc prefix;
158         if (field != null) {
159             if (field.isVolatile()) return;
160             annotation = FieldAnnotation.fromXField(field);
161             prefix = "SA_FIELD_SELF_";
162             if (true) return; // don't report these; too many false positives
163
} else {
164             annotation = FindNullDeref.findLocalAnnotationFromValueNumber(methodGen.getMethod(), location, v0, frame);
165             prefix = "SA_LOCAL_SELF_" ;
166             if (opcode == ISUB) return; // only report this if simple detector reports it
167
}
168         if (annotation == null) return;
169         SourceLineAnnotation sourceLine = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, location.getHandle());
170         int line = sourceLine.getStartLine();
171         BitSet JavaDoc occursMultipleTimes = classContext.linesMentionedMultipleTimes(methodGen.getMethod());
172         if (line > 0 && occursMultipleTimes.get(line)) return;
173         BugInstance bug = new BugInstance(this, prefix + op, priority).addClassAndMethod(methodGen, sourceFile)
174         .add(annotation).addSourceLine(classContext, methodGen, sourceFile, location.getHandle());
175         bugReporter.reportBug(bug);
176     }
177
178     public void report() {
179     }
180
181 }
182
Popular Tags