KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > props > WarningPropertyUtil


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2005, 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 package edu.umd.cs.findbugs.props;
20
21 import java.util.BitSet JavaDoc;
22 import java.util.Iterator JavaDoc;
23
24 import org.apache.bcel.Constants;
25 import org.apache.bcel.classfile.Method;
26 import org.apache.bcel.generic.Instruction;
27 import org.apache.bcel.generic.ReferenceType;
28 import org.apache.bcel.generic.Type;
29
30 import edu.umd.cs.findbugs.ba.CFG;
31 import edu.umd.cs.findbugs.ba.CFGBuilderException;
32 import edu.umd.cs.findbugs.ba.ClassContext;
33 import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
34 import edu.umd.cs.findbugs.ba.Location;
35 import edu.umd.cs.findbugs.ba.ca.Call;
36 import edu.umd.cs.findbugs.ba.ca.CallList;
37 import edu.umd.cs.findbugs.ba.ca.CallListDataflow;
38 import edu.umd.cs.findbugs.ba.type.TypeDataflow;
39 import edu.umd.cs.findbugs.ba.type.TypeFrame;
40
41 /**
42  * Utility methods for creating general warning properties.
43  *
44  * @author David Hovemeyer
45  */

46 public abstract class WarningPropertyUtil {
47     
48     /** Set of instructions which operate on a receiver object. */
49     private static final BitSet JavaDoc receiverObjectInstructionSet= new BitSet JavaDoc();
50     static {
51         receiverObjectInstructionSet.set(Constants.INVOKEINTERFACE);
52         receiverObjectInstructionSet.set(Constants.INVOKEVIRTUAL);
53         receiverObjectInstructionSet.set(Constants.INVOKESPECIAL);
54         receiverObjectInstructionSet.set(Constants.GETFIELD);
55         receiverObjectInstructionSet.set(Constants.PUTFIELD);
56         receiverObjectInstructionSet.set(Constants.CHECKCAST);
57         receiverObjectInstructionSet.set(Constants.INSTANCEOF);
58     }
59
60     /**
61      * Get a Location matching the given PC value.
62      * Because of JSR subroutines, there may be multiple
63      * Locations referring to the given instruction. This method simply
64      * returns one of them arbitrarily.
65      *
66      * @param classContext the ClassContext containing the method
67      * @param method the method
68      * @param pc a PC value of an instruction in the method
69      * @return a Location corresponding to the PC value, or null
70      * if no such Location can be found
71      * @throws CFGBuilderException
72      */

73     private static Location pcToLocation(
74             ClassContext classContext,
75             Method method,
76             int pc) throws CFGBuilderException {
77         CFG cfg = classContext.getCFG(method);
78         for (Iterator JavaDoc<Location> i = cfg.locationIterator(); i.hasNext();) {
79             Location location = i.next();
80             if (location.getHandle().getPosition() == pc)
81                 return location;
82         }
83         return null;
84     }
85     
86     /**
87      * Add a RECEIVER_OBJECT_TYPE warning property for a particular
88      * location in a method to given warning property set.
89      *
90      * @param propertySet the property set
91      * @param classContext ClassContext of the class containing the method
92      * @param method the method
93      * @param location Location within the method
94      */

95     private static void addReceiverObjectType(
96             WarningPropertySet propertySet,
97             ClassContext classContext,
98             Method method,
99             Location location) {
100         try {
101             Instruction ins = location.getHandle().getInstruction();
102             
103             if (!receiverObjectInstructionSet.get(ins.getOpcode()))
104                 return;
105             
106             TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
107             TypeFrame frame = typeDataflow.getFactAtLocation(location);
108             if (frame.isValid()) {
109                 Type type = frame.getInstance(ins, classContext.getConstantPoolGen());
110                 if (type instanceof ReferenceType) {
111                     propertySet.setProperty(GeneralWarningProperty.RECEIVER_OBJECT_TYPE, type.toString());
112                 }
113             }
114         } catch (DataflowAnalysisException e) {
115             // Ignore
116
} catch (CFGBuilderException e) {
117             // Ignore
118
}
119     }
120     
121     /**
122      * Add CALLED_METHOD_<i>n</i> warning properties based on methods
123      * which have been called and returned normally at given Location.
124      *
125      * @param propertySet the WarningPropertySet
126      * @param classContext the ClassContext
127      * @param method the Method
128      * @param location the Location
129      */

130     private static void addRecentlyCalledMethods(
131             WarningPropertySet propertySet,
132             ClassContext classContext,
133             Method method,
134             Location location) {
135         try {
136             CallListDataflow dataflow = classContext.getCallListDataflow(method);
137             CallList callList = dataflow.getFactAtLocation(location);
138             if (!callList.isValid())
139                 return;
140             int count = 0;
141             for (Iterator JavaDoc<Call> i = callList.callIterator(); count < 4 && i.hasNext(); ++count) {
142                 Call call = i.next();
143                 WarningProperty prop = null;
144                 switch (count) {
145                 case 0:
146                     prop = GeneralWarningProperty.CALLED_METHOD_1; break;
147                 case 1:
148                     prop = GeneralWarningProperty.CALLED_METHOD_2; break;
149                 case 2:
150                     prop = GeneralWarningProperty.CALLED_METHOD_3; break;
151                 case 3:
152                     prop = GeneralWarningProperty.CALLED_METHOD_4; break;
153                 }
154                 // XXX: encode class name? signature? break down as words?
155
propertySet.setProperty(prop, call.getMethodName());
156             }
157         } catch (CFGBuilderException e) {
158             // Ignore
159
} catch (DataflowAnalysisException e) {
160             // Ignore
161
}
162     }
163     
164     /**
165      * Add all relevant general warning properties to the given property set
166      * for the given Location.
167      *
168      * @param propertySet the WarningPropertySet
169      * @param classContext the ClassContext
170      * @param method the Method
171      * @param location the Location
172      */

173     public static void addPropertiesForLocation(
174             WarningPropertySet propertySet,
175             ClassContext classContext,
176             Method method,
177             Location location) {
178         addReceiverObjectType(propertySet, classContext, method, location);
179         addRecentlyCalledMethods(propertySet, classContext, method, location);
180     }
181     
182     /**
183      * Add all relevant general warning properties to the given property set
184      * for the given Location.
185      *
186      * @param propertySet the WarningPropertySet
187      * @param classContext the ClassContext
188      * @param method the Method
189      * @param pc the bytecode offset of an instruction to get properties for
190      */

191     public static void addPropertiesForLocation(
192             WarningPropertySet propertySet,
193             ClassContext classContext,
194             Method method,
195             int pc) {
196         try {
197             Location location = pcToLocation(classContext, method, pc);
198             if (location != null) {
199                 addPropertiesForLocation(propertySet, classContext, method, location);
200             }
201         } catch (CFGBuilderException e) {
202             // Ignore
203
}
204     }
205 }
206
Popular Tags