KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > type > StandardTypeMerger


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2003,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.type;
21
22 import org.apache.bcel.Constants;
23 import org.apache.bcel.generic.ObjectType;
24 import org.apache.bcel.generic.ReferenceType;
25 import org.apache.bcel.generic.Type;
26
27 import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
28 import edu.umd.cs.findbugs.ba.MissingClassException;
29 import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
30
31 /**
32  * A TypeMerger which applies standard Java semantics
33  * when merging Types. Subclasses may override mergeReferenceTypes()
34  * in order to implement special typing rules for reference types.
35  *
36  * @author David Hovemeyer
37  * @see TypeMerger
38  */

39 public class StandardTypeMerger implements TypeMerger, Constants, ExtendedTypes {
40     private RepositoryLookupFailureCallback lookupFailureCallback;
41     private ExceptionSetFactory exceptionSetFactory;
42
43     /**
44      * Constructor.
45      *
46      * @param lookupFailureCallback object used to report Repository lookup failures
47      * @param exceptionSetFactory factory for creating ExceptionSet objects
48      */

49     public StandardTypeMerger(RepositoryLookupFailureCallback lookupFailureCallback,
50                               ExceptionSetFactory exceptionSetFactory) {
51         this.lookupFailureCallback = lookupFailureCallback;
52         this.exceptionSetFactory = exceptionSetFactory;
53     }
54
55     public Type mergeTypes(Type a, Type b) throws DataflowAnalysisException {
56         byte aType = a.getType(), bType = b.getType();
57
58         if (aType == T_TOP) // Top is the identity element
59
return b;
60         else if (bType == T_TOP) // Top is the identity element
61
return a;
62         else if (aType == T_BOTTOM || bType == T_BOTTOM) // Bottom meet anything is bottom
63
return BottomType.instance();
64         else if (isReferenceType(aType) && isReferenceType(bType)) { // Two object types!
65
// Handle the Null type, which serves as a special "top"
66
// value for reference types.
67
if (aType == T_NULL)
68                 return b;
69             else if (bType == T_NULL)
70                 return a;
71
72             ReferenceType aRef = (ReferenceType) a;
73             ReferenceType bRef = (ReferenceType) b;
74             return mergeReferenceTypes(aRef, bRef);
75         } else if (isReferenceType(aType) || isReferenceType(bType)) // Object meet non-object is bottom
76
return BottomType.instance();
77         else if (aType == bType) // Same non-object type?
78
return a;
79         else if (isIntegerType(aType) && isIntegerType(bType)) // Two different integer types - use T_INT
80
return Type.INT;
81         else // Default - types are incompatible
82
return BottomType.instance();
83     }
84
85     /**
86      * Determine if the given typecode refers to a reference type.
87      * This implementation just checks that the type code is T_OBJECT,
88      * T_ARRAY, T_NULL, or T_EXCEPTION. Subclasses should override this
89      * if they have defined new object types with different type codes.
90      */

91     protected boolean isReferenceType(byte type) {
92         return type == T_OBJECT || type == T_ARRAY || type == T_NULL || type == T_EXCEPTION;
93     }
94
95     /**
96      * Determine if the given typecode refers to an Object type.
97      * Subclasses should override with any new object types.
98      */

99     protected boolean isObjectType(byte type) {
100         return type == T_OBJECT || type == T_EXCEPTION;
101     }
102
103     /**
104      * Determine if the given typecode refers to an Integer type (other than long).
105      * This implementation checks that the type code is T_INT, T_BYTE, T_BOOLEAN,
106      * T_CHAR, or T_SHORT. Subclasses should override this if they have
107      * defined new integer types with different type codes.
108      */

109     protected boolean isIntegerType(byte type) {
110         return type == T_INT || type == T_BYTE || type == T_BOOLEAN || type == T_CHAR || type == T_SHORT;
111     }
112
113     private static void updateExceptionSet(ExceptionSet exceptionSet, ObjectType type) {
114         if (type instanceof ExceptionObjectType)
115             exceptionSet.addAll(((ExceptionObjectType) type).getExceptionSet());
116         else
117             exceptionSet.addExplicit(type);
118     }
119
120     /**
121      * Default implementation of merging reference types.
122      * This just returns the first common superclass, which is compliant
123      * with the JVM Spec. Subclasses may override this method
124      * in order to implement extended type rules.
125      *
126      * @param aRef a ReferenceType
127      * @param bRef a ReferenceType
128      * @return the merged Type
129      */

130     protected Type mergeReferenceTypes(ReferenceType aRef, ReferenceType bRef) throws DataflowAnalysisException {
131         // Two concrete object types.
132
// According to the JVM spec, 2nd edition, 4.9.2,
133
// the result of merging types is the "first common superclass".
134
// Interfaces are NOT considered!
135
// This will use the Repository to look up classes.
136
try {
137             // Special case: ExceptionObjectTypes.
138
// We want to preserve the ExceptionSets associated,
139
// in order to track the exact set of exceptions
140
if (isObjectType(aRef.getType()) && isObjectType(bRef.getType()) &&
141                     (aRef.getType() == T_EXCEPTION || bRef.getType() == T_EXCEPTION)) {
142                 ExceptionSet union = exceptionSetFactory.createExceptionSet();
143
144                 updateExceptionSet(union, (ObjectType) aRef);
145                 updateExceptionSet(union, (ObjectType) bRef);
146
147                 return ExceptionObjectType.fromExceptionSet(union);
148             }
149
150             return aRef.getFirstCommonSuperclass(bRef);
151         } catch (ClassNotFoundException JavaDoc e) {
152             lookupFailureCallback.reportMissingClass(e);
153             throw new MissingClassException(e);
154         }
155     }
156
157 }
158
159 // vim:ts=4
160
Popular Tags