KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 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 java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import edu.umd.cs.findbugs.BugInstance;
26 import edu.umd.cs.findbugs.BugReporter;
27 import edu.umd.cs.findbugs.BytecodeScanningDetector;
28 import edu.umd.cs.findbugs.ba.ClassContext;
29
30 /**
31  * Detector to find calls to Number constructors with base type argument in
32  * Java 5 or newer bytecode.
33  *
34  * Using <code>new Integer(int)</code> is guaranteed to always result in a
35  * new object whereas <code>Integer.valueOf(int)</code> allows caching of
36  * values to be done by the javac, JVM class library or JIT.
37  *
38  * Currently only the JVM class library seems to do caching in the range of
39  * -128 to 127. There does not seem to be any caching for float and double
40  * which is why those are reported as low priority.
41  *
42  * All invokes of Number constructor with a constant argument are
43  * flagged as high priority and invokes with unknwon value are normal priority.
44  *
45  * @author Mikko Tiihonen
46  */

47 public class NumberConstructor extends BytecodeScanningDetector {
48
49   /**
50    * Immutable information class of one handled number types.
51    */

52   static class Info {
53     public final boolean isRealNumber;
54     public final String JavaDoc argName;
55     public final String JavaDoc constrArgs;
56        
57     public Info(boolean isRealNumber, String JavaDoc argName, String JavaDoc constrArgs) {
58       this.isRealNumber = isRealNumber;
59       this.argName = argName;
60       this.constrArgs = constrArgs;
61     }
62   }
63   
64   private static final Map JavaDoc<String JavaDoc, Info> boxClasses = new HashMap JavaDoc<String JavaDoc, Info>();
65   static {
66     boxClasses.put("java/lang/Byte", new Info(false, "byte", "(B)V"));
67     boxClasses.put("java/lang/Character", new Info(false, "char", "(C)V"));
68     boxClasses.put("java/lang/Short", new Info(false, "short", "(S)V"));
69     boxClasses.put("java/lang/Integer", new Info(false, "int", "(I)V"));
70     boxClasses.put("java/lang/Long", new Info(false, "long", "(J)V"));
71     boxClasses.put("java/lang/Float", new Info(true, "float", "(F)V"));
72     boxClasses.put("java/lang/Double", new Info(true, "double", "(D)V"));
73   }
74
75   private final BugReporter bugReporter;
76   private boolean constantArgument;
77     
78   /**
79    * Constructs a NC detector given the reporter to report bugs on
80    * @param bugReporter the sync of bug reports
81    */

82   public NumberConstructor(BugReporter bugReporter) {
83     this.bugReporter = bugReporter;
84   }
85     
86   /**
87    * The detector is only meaningful for Java5 class libraries.
88    *
89    * @param classContext the context object that holds the JavaClass parsed
90    */

91   @Override JavaDoc
92   public void visitClassContext(ClassContext classContext) {
93     int majorVersion = classContext.getJavaClass().getMajor();
94     if (majorVersion >= MAJOR_1_5) {
95       super.visitClassContext(classContext);
96     }
97   }
98
99   @Override JavaDoc
100   public void sawOpcode(int seen) {
101     // detect if previous op was a constant number
102
if (seen == ICONST_0 || seen == LCONST_0 ||
103     seen == ICONST_1 || seen == LCONST_1 ||
104     seen == ICONST_2 || seen == ICONST_3 ||
105     seen == ICONST_4 || seen == ICONST_5 ||
106     seen == BIPUSH || seen == LDC) {
107       constantArgument = true;
108       return;
109     }
110         
111     // only acts on constructor invoke
112
if (seen != INVOKESPECIAL) {
113       constantArgument = false;
114       return;
115     }
116         
117     if (!"<init>".equals(getNameConstantOperand())) {
118       return;
119     }
120     String JavaDoc cls = getClassConstantOperand();
121     Info info = boxClasses.get(cls);
122     if (info == null) {
123       return;
124     }
125         
126     if (!info.constrArgs.equals(getSigConstantOperand())) {
127       return;
128     }
129         
130     int prio;
131     String JavaDoc type;
132     if (info.isRealNumber) {
133       prio = LOW_PRIORITY;
134       type = "DM_FP_NUMBER_CTOR";
135     } else {
136       prio = NORMAL_PRIORITY;
137       type = "DM_NUMBER_CTOR";
138     }
139         
140     cls = cls.substring(cls.lastIndexOf('/')+1);
141     bugReporter.reportBug(new BugInstance(this, type, prio)
142               .addClass(this)
143               .addMethod(this)
144               .addSourceLine(this)
145               .addString(cls+"("+info.argName+")")
146               .addString(cls+".valueOf("+info.argName+")"));
147   }
148 }
149
Popular Tags