KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2004-2006 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.detect;
21
22 import org.apache.bcel.classfile.Code;
23 import org.apache.bcel.classfile.JavaClass;
24 import org.apache.bcel.classfile.Method;
25
26 import edu.umd.cs.findbugs.BugInstance;
27 import edu.umd.cs.findbugs.BugReporter;
28 import edu.umd.cs.findbugs.BytecodeScanningDetector;
29 import edu.umd.cs.findbugs.FieldAnnotation;
30 import edu.umd.cs.findbugs.LocalVariableAnnotation;
31 import edu.umd.cs.findbugs.OpcodeStack;
32 import edu.umd.cs.findbugs.ba.SignatureParser;
33 import edu.umd.cs.findbugs.ba.XField;
34
35 public class FindSelfComparison extends BytecodeScanningDetector {
36
37     BugReporter bugReporter;
38
39     OpcodeStack stack = new OpcodeStack();
40
41     public FindSelfComparison(BugReporter bugReporter) {
42         this.bugReporter = bugReporter;
43     }
44
45     @Override JavaDoc
46     public void visit(JavaClass obj) {
47     }
48
49     @Override JavaDoc
50     public void visit(Method obj) {
51     }
52
53     @Override JavaDoc
54     public void visit(Code obj) {
55         whichRegister = -1;
56         registerLoadCount = 0;
57         stack.resetForMethodEntry(this);
58         super.visit(obj);
59     }
60
61     @Override JavaDoc
62     public void sawOpcode(int seen) {
63         // System.out.println(getPC() + " " + OPCODE_NAMES[seen] + " " + whichRegister + " " + registerLoadCount);
64
stack.mergeJumps(this);
65         
66         switch (seen) {
67         case INVOKEVIRTUAL:
68         case INVOKEINTERFACE:
69             if (getClassName().toLowerCase().indexOf("test") >= 0) break;
70             if (getMethodName().toLowerCase().indexOf("test") >= 0) break;
71             if (getSuperclassName().toLowerCase().indexOf("test") >= 0) break;
72              
73             String JavaDoc name = getNameConstantOperand();
74             if (name.equals("equals") ||
75                     name.equals("compareTo")) {
76             String JavaDoc sig = getSigConstantOperand();
77             SignatureParser parser = new SignatureParser(sig);
78             if (parser.getNumParameters() == 1 &&
79                     (name.equals("equals") && sig.endsWith(";)Z")
80                     || name.equals("compareTo") && sig.endsWith(";)I")))
81                 checkForSelfOperation(seen, "COMPARISON");
82             }
83             break;
84            
85         case LOR:
86         case LAND:
87         case LXOR:
88         case LSUB:
89         case IOR:
90         case IAND:
91         case IXOR:
92         case ISUB:
93             checkForSelfOperation(seen, "COMPUTATION");
94             break;
95         case FCMPG:
96         case DCMPG:
97         case DCMPL:
98         case FCMPL:
99             break;
100         case LCMP:
101         case IF_ACMPEQ:
102         case IF_ACMPNE:
103         case IF_ICMPNE:
104         case IF_ICMPEQ:
105         case IF_ICMPGT:
106         case IF_ICMPLE:
107         case IF_ICMPLT:
108         case IF_ICMPGE:
109             checkForSelfOperation(seen, "COMPARISON");
110         }
111         stack.sawOpcode(this, seen);
112         if (isRegisterLoad() && seen != IINC) {
113             if (getRegisterOperand() == whichRegister) registerLoadCount++;
114             else {
115                 whichRegister = getRegisterOperand();
116                 registerLoadCount = 1;
117             }
118         } else {
119             whichRegister = -1;
120             registerLoadCount = 0;
121         }
122     }
123     int whichRegister;
124     int registerLoadCount;
125
126
127
128 private void checkForSelfOperation(int opCode, String JavaDoc op) {
129     {
130
131         OpcodeStack.Item item0 = stack.getStackItem(0);
132         OpcodeStack.Item item1 = stack.getStackItem(1);
133
134         if (item0.getSignature().equals("D")
135                 || item0.getSignature().equals("F"))
136             return;
137         if (item1.getSignature().equals("D")
138                 || item1.getSignature().equals("F"))
139             return;
140
141         XField field0 = item0.getXField();
142         XField field1 = item1.getXField();
143         int fr0 = item0.getFieldLoadedFromRegister();
144         int fr1 = item1.getFieldLoadedFromRegister();
145         if (field0 != null && field0.equals(field1) && fr0 != -1 && fr0 == fr1)
146             bugReporter.reportBug(new BugInstance(this,
147                     "SA_FIELD_SELF_" + op, NORMAL_PRIORITY)
148             .addClassAndMethod(this).addField(field0)
149             .addSourceLine(this));
150
151         else if (opCode == ISUB && registerLoadCount >= 2) { // let FindSelfComparison2 report this; more accurate
152
bugReporter.reportBug(new BugInstance(this,
153                     "SA_LOCAL_SELF_" + op, (opCode == ISUB || opCode == LSUB || opCode == INVOKEINTERFACE || opCode == INVOKEVIRTUAL) ? NORMAL_PRIORITY : HIGH_PRIORITY)
154             .addClassAndMethod(this).add(
155                     LocalVariableAnnotation
156                     .getLocalVariableAnnotation(
157                             getMethod(), whichRegister, getPC(),
158                             getPC() - 1))
159                             .addSourceLine(this));
160         }
161     }
162 }
163 }
Popular Tags