KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > BlockType


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2004, 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.ba;
21
22 import java.util.BitSet JavaDoc;
23
24 /**
25  * Dataflow value representing the current nesting of
26  * catch and finally blocks. We assume that any catch block
27  * with a non-empty catch type is a user catch block,
28  * and any catch block with an empty catch type (i.e., catch all
29  * exceptions) is a finally block. This assumption isn't quite
30  * accurate, but it seems to be a reasonable first approximation.
31  *
32  * <p>If valid (isValid() returns true),
33  * a BlockType value is a stack of elements, which are either CATCH
34  * or FINALLY values. Call getDepth() to get the current
35  * nesting depth. Call get(int <i>n</i>) to get the
36  * <i>n</i>th stack item. Call getTopValue() to get the current
37  * top of the stack.</p>
38  *
39  * <p>If invalid (isValid() returns false),
40  * a BlockType value is either <i>top</i> or <i>bottom</i>.
41  * These are the special values at the top and bottom of
42  * the dataflow lattice.</p>
43  *
44  * <p>The dataflow lattice is effectively finite-height because
45  * real Java methods are guarnateed to have a finite
46  * catch and finally block nesting level.</p>
47  *
48  * @see BlockTypeAnalysis
49  * @author David Hovemeyer
50  */

51 public class BlockType extends BitSet JavaDoc {
52     /**
53      *
54      */

55     private static final long serialVersionUID = 1L;
56     public static final boolean CATCH = false;
57     public static final boolean FINALLY = true;
58
59     private boolean isValid;
60     private boolean isTop;
61     private int depth;
62
63     /**
64      * Constructor.
65      * Should only be called by BlockTypeAnalysis.
66      */

67     BlockType() {
68     }
69
70     /**
71      * Return whether or not this value is valid,
72      * meaning it contains a valid representation of the
73      * nesting of catch and finally blocks.
74      */

75     public boolean isValid() {
76         return isValid;
77     }
78
79     /**
80      * Get the current nesting depth.
81      * The value must be valid.
82      */

83     public int getDepth() {
84         if (!isValid) throw new IllegalStateException JavaDoc();
85         return depth;
86     }
87
88     /**
89      * Get the top value on the catch and finally block nesting stack.
90      */

91     public boolean getTopValue() {
92         if (depth == 0) throw new IllegalStateException JavaDoc();
93         return get(depth - 1);
94     }
95
96     /**
97      * Return whether or not this value represents "normal" control-flow.
98      * Normal control flow are all blocks outside any catch or finally block.
99      */

100     public boolean isNormal() {
101         if (!isValid) throw new IllegalStateException JavaDoc();
102         return getDepth() == 0;
103     }
104
105     /**
106      * Make this value represent "normal" control flow.
107      */

108     public void setNormal() {
109         this.isValid = true;
110         this.depth = 0;
111     }
112
113     /**
114      * Return whether or not this is the special "top" dataflow value.
115      */

116     public boolean isTop() {
117         return !isValid && isTop;
118     }
119
120     /**
121      * Make this the special "top" dataflow value.
122      */

123     public void setTop() {
124         this.isValid = false;
125         this.isTop = true;
126     }
127
128     /**
129      * Return whether or not this is the special "bottom" dataflow value.
130      */

131     public boolean isBottom() {
132         return !isValid && !isTop;
133     }
134
135     /**
136      * Make this the special "bottom" dataflow value.
137      */

138     public void setBottom() {
139         this.isValid = false;
140         this.isTop = false;
141     }
142
143     /**
144      * Make this object an exact duplicate of given object.
145      *
146      * @param other the other BlockType object
147      */

148     public void copyFrom(BlockType other) {
149         this.isValid = other.isValid;
150         this.isTop = other.isTop;
151         if (isValid) {
152             this.depth = other.depth;
153             this.clear();
154             this.or(other);
155         }
156     }
157
158     /**
159      * Return whether or not this object is identical to the one given.
160      *
161      * @param other the other BlockType object
162      * @return true if this object is identical to the one given,
163      * false otherwise
164      */

165     public boolean sameAs(BlockType other) {
166         if (!this.isValid) {
167             return !other.isValid
168                 && (this.isTop == other.isTop);
169         } else {
170             if (!other.isValid)
171                 return false;
172             else {
173                 // Both facts are valid
174
if (this.depth != other.depth)
175                     return false;
176
177                 // Compare bits
178
for (int i = 0; i < this.depth; ++i) {
179                     if (this.get(i) != other.get(i))
180                         return false;
181                 }
182
183                 return true;
184             }
185         }
186     }
187
188     /**
189      * Merge other dataflow value into this value.
190      *
191      * @param other the other BlockType value
192      */

193     public void mergeWith(BlockType other) {
194         if (this.isTop() || other.isBottom()) {
195             copyFrom(other);
196         } else if (isValid()) {
197             // To merge, we take the common prefix
198
int pfxLen = Math.min(this.depth, other.depth);
199             int commonLen;
200             for (commonLen = 0; commonLen < pfxLen; ++commonLen) {
201                 if (this.get(commonLen) != other.get(commonLen))
202                     break;
203             }
204             this.depth = commonLen;
205         }
206     }
207
208     /**
209      * Enter a catch block.
210      */

211     public void pushCatch() {
212         push(CATCH);
213     }
214
215     /**
216      * Enter a finally block.
217      */

218     public void pushFinally() {
219         push(FINALLY);
220     }
221
222     @Override JavaDoc
223          public String JavaDoc toString() {
224         if (isTop())
225             return "<top>";
226         else if (isBottom())
227             return "<bottom>";
228         else {
229             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
230             buf.append("N");
231             for (int i = 0; i < depth; ++i) {
232                 buf.append(get(i) == CATCH ? "C" : "F");
233             }
234             return buf.toString();
235         }
236     }
237
238     private void push(boolean value) {
239         set(depth, value);
240         ++depth;
241     }
242 }
243
244 // vim:ts=4
245
Popular Tags