Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7035/src/com/mebigfatguy/fbcontrib/detect
Modified Files:
ArrayBasedCollections.java
Log Message:
if a class uses a TreeMap or TreeSet with a comparator, then call off the dogs when putting arrays in these containers.
Index: ArrayBasedCollections.java
===================================================================
RCS file: /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ArrayBasedCollections.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ArrayBasedCollections.java 17 Dec 2005 08:27:01 -0000 1.1
+++ ArrayBasedCollections.java 21 Dec 2005 05:13:39 -0000 1.2
@@ -18,18 +18,27 @@
*/
package com.mebigfatguy.fbcontrib.detect;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.bcel.classfile.Code;
+import org.apache.bcel.generic.Type;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.StatelessDetector;
+import edu.umd.cs.findbugs.ba.ClassContext;
public class ArrayBasedCollections extends BytecodeScanningDetector implements StatelessDetector
{
private BugReporter bugReporter;
private OpcodeStack stack = new OpcodeStack();
+ private List<BugInstance> mapBugs = new ArrayList<BugInstance>();
+ private List<BugInstance> setBugs = new ArrayList<BugInstance>();
+ private boolean hasMapComparator;
+ private boolean hasSetComparator;
public ArrayBasedCollections(BugReporter bugReporter) {
this.bugReporter = bugReporter;
@@ -41,6 +50,26 @@
}
@Override
+ public void visitClassContext(ClassContext classContext) {
+ mapBugs.clear();
+ setBugs.clear();
+ hasMapComparator = false;
+ hasSetComparator = false;
+ super.visitClassContext(classContext);
+ if (!hasMapComparator) {
+ for (BugInstance bi : mapBugs) {
+ bugReporter.reportBug(bi);
+ }
+ }
+
+ if (!hasSetComparator) {
+ for (BugInstance bi : setBugs) {
+ bugReporter.reportBug(bi);
+ }
+ }
+ }
+
+ @Override
public void visitCode(Code obj) {
stack.resetForMethodEntry(this);
super.visitCode(obj);
@@ -54,6 +83,7 @@
String methodName = getNameConstantOperand();
String methodSig = getSigConstantOperand();
boolean found = false;
+ List<BugInstance> bugList = null;
if ("java/util/Map".equals(className)
&& "put".equals(methodName)
@@ -61,8 +91,10 @@
if (stack.getStackDepth() > 1) {
OpcodeStack.Item itm = stack.getStackItem(1);
String pushedSig = itm.getSignature();
- if (pushedSig.charAt(0) == '[')
+ if (pushedSig.charAt(0) == '[') {
+ bugList = mapBugs;
found = true;
+ }
}
} else if ("java/util/Set".equals(className)
&& "add".equals(methodName)
@@ -70,8 +102,10 @@
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
String pushedSig = itm.getSignature();
- if (pushedSig.charAt(0) == '[')
+ if (pushedSig.charAt(0) == '[') {
+ bugList = setBugs;
found = true;
+ }
}
} else if ("java/util/List".equals(className)
&& "contains".equals(methodName)
@@ -85,12 +119,32 @@
}
if (found) {
- bugReporter.reportBug(new BugInstance(this, "ABC_ARRAY_BASED_COLLECTIONS", NORMAL_PRIORITY)
- .addClass(this)
- .addMethod(this)
- .addSourceLine(this));
+ BugInstance bi = new BugInstance(this, "ABC_ARRAY_BASED_COLLECTIONS", NORMAL_PRIORITY)
+ .addClass(this)
+ .addMethod(this)
+ .addSourceLine(this);
+ if (bugList != null)
+ bugList.add(bi);
+ else
+ bugReporter.reportBug(bi);
}
+ } else if (seen == INVOKESPECIAL) {
+ String className = getClassConstantOperand();
+ String methodName = getNameConstantOperand();
+ String sig = getSigConstantOperand();
+
+ if ("<init>".equals(methodName)) {
+ if (!hasMapComparator && "java/util/TreeMap".equals(className)) {
+ Type[] parms = Type.getArgumentTypes(sig);
+ if ((parms.length == 1) && "Ljava/util/Comparator;".equals(parms[0].getSignature()))
+ hasMapComparator = true;
+ } else if (!hasSetComparator && "java/util/TreeSet".equals(className)) {
+ Type[] parms = Type.getArgumentTypes(sig);
+ if ((parms.length == 1) && "Ljava/util/Comparator;".equals(parms[0].getSignature()))
+ hasSetComparator = true;
+ }
+ }
}
} finally {
stack.sawOpcode(this, seen);
|