Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27741/src/com/mebigfatguy/fbcontrib/detect
Added Files:
ConfusingAutoboxedOverriding.java
Log Message:
new detector, CAO, initial check in
--- NEW FILE: ConfusingAutoboxedOverriding.java ---
/*
* fb-contrib - Auxilliary detectors for Java programs
* Copyright (C) 2005 Dave Brosius
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.mebigfatguy.fbcontrib.detect;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.Type;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.StatelessDetector;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
public class ConfusingAutoboxedOverriding extends PreorderVisitor implements Detector, StatelessDetector
{
private static final int JDK15_MAJOR = 49;
private static final int JDK15_MINOR = 0;
private static final Set<String> primitiveSigs = new HashSet<String>();
static {
primitiveSigs.add("I");
primitiveSigs.add("J");
primitiveSigs.add("D");
primitiveSigs.add("F");
}
private BugReporter bugReporter;
public ConfusingAutoboxedOverriding(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void visitClassContext(ClassContext classContext) {
JavaClass cls = classContext.getJavaClass();
if (cls.getMajor() >= JDK15_MAJOR) {
Map<String, Set<String>> methodInfo = new HashMap<String, Set<String>>();
populateMethodInfo(cls, methodInfo);
Method[] methods = cls.getMethods();
for (Method m : methods) {
String name = m.getName();
String signature = m.getSignature();
Set<String> sigs = methodInfo.get(name);
if (sigs != null) {
for (String sig : sigs) {
if (confusingSignatures(sig, signature)) {
bugReporter.reportBug(new BugInstance(this, "CAO_CONFUSING_AUTOBOXED_OVERRIDING", NORMAL_PRIORITY)
.addClass(this)
.addString(name + signature)
.addString(name + sig));
}
}
}
}
}
}
private boolean confusingSignatures(String sig1, String sig2) {
if (sig1.equals(sig2))
return false;
Type[] type1 = Type.getArgumentTypes(sig1);
Type[] type2 = Type.getArgumentTypes(sig2);
if (type1.length != type2.length)
return false;
for (int i = 0; i < type1.length; i++) {
Type t1 = type1[i];
Type t2 = type2[i];
if (!t1.getSignature().equals(t2.getSignature())) {
if ("Ljava/lang/Character;".equals(t1.getSignature())) {
if (!primitiveSigs.contains(t2.getSignature()))
return false;
} else if ("Ljava/lang/Character;".equals(t2.getSignature())) {
if (!primitiveSigs.contains(t1.getSignature()))
return false;
} else
return false;
}
}
return true;
}
private void populateMethodInfo(JavaClass cls, Map<String, Set<String>> methodInfo) {
try {
if ("java.lang.Object".equals(cls.getClassName()))
return;
Method[] methods = cls.getMethods();
for (Method m : methods) {
String sig = m.getSignature();
if (!isPossiblyConfusingSignature(sig))
continue;
String name = m.getName();
Set<String> sigs = methodInfo.get(name);
if (sigs == null) {
sigs = new HashSet<String>();
methodInfo.put(name, sigs);
}
sigs.add(m.getSignature());
}
populateMethodInfo(cls.getSuperClass(), methodInfo);
} catch (ClassNotFoundException cnfe) {
bugReporter.reportMissingClass(cnfe);
}
}
private boolean isPossiblyConfusingSignature(String sig) {
Type[] types = Type.getArgumentTypes(sig);
for (Type t : types) {
sig = t.getSignature();
if (primitiveSigs.contains(sig))
return true;
if ("Ljava/lang/Character;".equals(sig))
return true;
}
return false;
}
public void report() {
}
}
|