[Fb-contrib-commit] SF.net SVN: fb-contrib:[1545] trunk/fb-contrib
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2010-05-07 08:30:34
|
Revision: 1545
http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=1545&view=rev
Author: dbrosius
Date: 2010-05-07 08:30:28 +0000 (Fri, 07 May 2010)
Log Message:
-----------
initial checkin, new WOC detector
Modified Paths:
--------------
trunk/fb-contrib/etc/findbugs.xml
trunk/fb-contrib/etc/messages.xml
Added Paths:
-----------
trunk/fb-contrib/samples/WOC_Sample.java
trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/WriteOnlyCollection.java
Modified: trunk/fb-contrib/etc/findbugs.xml
===================================================================
--- trunk/fb-contrib/etc/findbugs.xml 2010-04-24 01:53:11 UTC (rev 1544)
+++ trunk/fb-contrib/etc/findbugs.xml 2010-05-07 08:30:28 UTC (rev 1545)
@@ -331,6 +331,10 @@
<Detector class="com.mebigfatguy.fbcontrib.detect.PossibleConstantAllocationInLoop"
speed="fast"
reports="PCAIL_POSSIBLE_CONSTANT_ALLOCATION_IN_LOOP" />
+
+ <Detector class="com.mebigfatguy.fbcontrib.detect.WriteOnlyCollection"
+ speed="fast"
+ reports="WOC_WRITE_ONLY_COLLECTION" />
<!-- BugPattern -->
@@ -627,4 +631,6 @@
category="CORRECTNESS" experimental="true" />
<BugPattern abbrev="PCAIL" type="PCAIL_POSSIBLE_CONSTANT_ALLOCATION_IN_LOOP"
category="PERFORMANCE" experimental="true" />
+ <BugPattern abbrev="WOC" type="WOC_WRITE_ONLY_COLLECTION"
+ category="CORRECTNESS" experimental="true" />
</FindbugsPlugin>
\ No newline at end of file
Modified: trunk/fb-contrib/etc/messages.xml
===================================================================
--- trunk/fb-contrib/etc/messages.xml 2010-04-24 01:53:11 UTC (rev 1544)
+++ trunk/fb-contrib/etc/messages.xml 2010-05-07 08:30:28 UTC (rev 1545)
@@ -1134,6 +1134,17 @@
]]>
</Details>
</Detector>
+
+ <Detector class="com.mebigfatguy.fbcontrib.detect.WriteOnlyCollection">
+ <Details>
+ <![CDATA[
+ <p>This detector looks for allocations and initializations of java collections, but that are never
+ read from or accessed to gain information. This represents a collection of no use, and most probably
+ can be removed. It is similar to a dead local store.</p>
+ <p>It is a fast detector</p>
+ ]]>
+ </Details>
+ </Detector>
<!-- BugPattern -->
@@ -3107,6 +3118,18 @@
]]>
</Details>
</BugPattern>
+
+ <BugPattern type="WOC_WRITE_ONLY_COLLECTION">
+ <ShortDescription>Method creates and initializes a collection but never reads or gains information from it</ShortDescription>
+ <LongDescription>Method {1} creates and initializes a collection but never reads or gains information from it</LongDescription>
+ <Details>
+ <![CDATA[
+ <p>This method creates and initializes a collection but then never access this collection
+ to gain information, or fetch items from the collection. It is likely that this collection
+ is left over from a past effort, and can be removed.
+ ]]>
+ </Details>
+ </BugPattern>
<!-- BugCode -->
@@ -3203,4 +3226,5 @@
<BugCode abbrev="ROOM">Reflection on Object Methods</BugCode>
<BugCode abbrev="IPU">Improper Properties use</BugCode>
<BugCode abbrev="PCAIL">Possible Constant Allocation In Loop</BugCode>
+ <BugCode abbrev="WOC">Write Only Collection</BugCode>
</MessageCollection>
Added: trunk/fb-contrib/samples/WOC_Sample.java
===================================================================
--- trunk/fb-contrib/samples/WOC_Sample.java (rev 0)
+++ trunk/fb-contrib/samples/WOC_Sample.java 2010-05-07 08:30:28 UTC (rev 1545)
@@ -0,0 +1,40 @@
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+public class WOC_Sample
+{
+ public void testWOCSimple()
+ {
+ Set<String> s = new HashSet<String>();
+ s.add("Foo");
+ }
+
+ public Map<String, String> testFPWOCReturn()
+ {
+ Map<String, String> m = new HashMap<String, String>();
+ m.put("Foo", "Bar");
+ return m;
+ }
+
+ public void testFPWOCAsParm()
+ {
+ Map<String, String> m = new HashMap<String, String>();
+ m.put("Foo", "Bar");
+ helper(0, m);
+ }
+
+ public void testFPWOCCopy()
+ {
+ Set<String> s = new LinkedHashSet<String>();
+ s.add("foo");
+ Set<String> c = s;
+ }
+
+ private void helper(int i, Map<String, String> x)
+ {
+ }
+}
Property changes on: trunk/fb-contrib/samples/WOC_Sample.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/WriteOnlyCollection.java
===================================================================
--- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/WriteOnlyCollection.java (rev 0)
+++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/WriteOnlyCollection.java 2010-05-07 08:30:28 UTC (rev 1545)
@@ -0,0 +1,288 @@
+/*
+ * fb-contrib - Auxiliary detectors for Java programs
+ * Copyright (C) 2005-2010 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.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.generic.Type;
+
+import com.mebigfatguy.fbcontrib.utils.RegisterUtils;
+
+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.OpcodeStack.Item;
+import edu.umd.cs.findbugs.ba.ClassContext;
+import edu.umd.cs.findbugs.ba.XField;
+
+public class WriteOnlyCollection extends BytecodeScanningDetector {
+
+ private static Set<String> collectionClasses = new HashSet<String>();
+ static
+ {
+ collectionClasses.add(HashSet.class.getName());
+ collectionClasses.add(TreeSet.class.getName());
+ collectionClasses.add(LinkedHashSet.class.getName());
+ collectionClasses.add(HashMap.class.getName());
+ collectionClasses.add(TreeMap.class.getName());
+ collectionClasses.add(Hashtable.class.getName());
+ collectionClasses.add(LinkedHashMap.class.getName());
+ collectionClasses.add(Vector.class.getName());
+ collectionClasses.add(ArrayList.class.getName());
+ collectionClasses.add(LinkedList.class.getName());
+ }
+
+ private static Set<String> writeMethods = new HashSet<String>();
+ static
+ {
+ writeMethods.add("add");
+ writeMethods.add("addAll");
+ writeMethods.add("addElement");
+ writeMethods.add("addFirst");
+ writeMethods.add("addLast");
+ writeMethods.add("clear");
+ writeMethods.add("clone");
+ writeMethods.add("ensureCapacity");
+ writeMethods.add("insertElementAt");
+ writeMethods.add("put");
+ writeMethods.add("putAll");
+ writeMethods.add("remove");
+ writeMethods.add("removeAll");
+ writeMethods.add("removeElement");
+ writeMethods.add("removeElementAt");
+ writeMethods.add("removeRange");
+ writeMethods.add("set");
+ writeMethods.add("setElementAt");
+ writeMethods.add("setSize");
+ writeMethods.add("trimToSize");
+ }
+
+ private BugReporter bugReporter;
+ private OpcodeStack stack;
+ /** register to first allocation PC */
+ private Map<Integer, Integer> localWOCollections;
+ /** field to first allocation PC */
+ private Map<String, Integer> fieldWOCollections;
+
+
+ /**
+ * constructs a WOC detector given the reporter to report bugs on
+ * @param bugReporter the sync of bug reports
+ */
+ public WriteOnlyCollection(BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ }
+ /**
+ * overrides the visitor to initialize and tear down the opcode stack
+ *
+ * @param classContext the context object of the currently parsed class
+ */
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ try {
+ stack = new OpcodeStack();
+ localWOCollections = new HashMap<Integer, Integer>();
+ fieldWOCollections = new HashMap<String, Integer>();
+ super.visitClassContext(classContext);
+ } finally {
+ stack = null;
+ localWOCollections = null;
+ fieldWOCollections = null;
+ }
+ }
+
+ /**
+ * overrides the visitor reset the stack
+ *
+ * @param obj the context object of the currently parsed code block
+ */
+ @Override
+ public void visitCode(Code obj) {
+ stack.resetForMethodEntry(this);
+ localWOCollections.clear();
+ super.visitCode(obj);
+
+ for (Integer pc : localWOCollections.values()) {
+ bugReporter.reportBug(new BugInstance(this, "WOC_WRITE_ONLY_COLLECTION", NORMAL_PRIORITY)
+ .addClass(this)
+ .addMethod(this)
+ .addSourceLine(this, pc.intValue()));
+ }
+ }
+
+ /**
+ * overrides the visitor to look for uses of collections where the only access to
+ * to the collection is to write to it
+ *
+ * @param seen the opcode of the currently visited instruction
+ */
+ @Override
+ public void sawOpcode(int seen) {
+ Object userObject = null;
+
+ try {
+ switch (seen) {
+ case INVOKESPECIAL:
+ String methodName = getNameConstantOperand();
+ if ("<init>".equals(methodName)) {
+ String clsName = getClassConstantOperand().replace('/', '.');
+ if (collectionClasses.contains(clsName))
+ userObject = Boolean.TRUE;
+ }
+ processMethodParms();
+ break;
+
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ String sig = getSigConstantOperand();
+ int numParms = Type.getArgumentTypes(sig).length;
+ if (stack.getStackDepth() > numParms) {
+ OpcodeStack.Item item = stack.getStackItem(numParms);
+ Object uo = item.getUserValue();
+ if (uo != null) {
+ String name = getNameConstantOperand();
+ if (!writeMethods.contains(name)) {
+ clearUserValue(item);
+ }
+ }
+ }
+ processMethodParms();
+ break;
+
+ case INVOKESTATIC:
+ processMethodParms();
+ break;
+
+ case ARETURN:
+ if (stack.getStackDepth() > 0) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ clearUserValue(item);
+ }
+ break;
+
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3:
+ case ASTORE:
+ if (stack.getStackDepth() > 0) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ Object uo = item.getUserValue();
+ if (uo != null) {
+ if (uo instanceof Boolean) {
+ int reg = RegisterUtils.getAStoreReg(this, seen);
+ localWOCollections.put(reg, Integer.valueOf(getPC()));
+ } else {
+ clearUserValue(item);
+ }
+ }
+ }
+ break;
+
+ case ALOAD_0:
+ case ALOAD_1:
+ case ALOAD_2:
+ case ALOAD_3:
+ case ALOAD:
+ int reg = RegisterUtils.getALoadReg(this, seen);
+ if (localWOCollections.containsKey(Integer.valueOf(reg))) {
+ userObject = Integer.valueOf(reg);
+ }
+ break;
+
+ case PUTFIELD:
+ if (stack.getStackDepth() > 1) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ Object uo = item.getUserValue();
+ if (uo != null) {
+ if (uo instanceof Boolean) {
+ Item fieldItem = stack.getStackItem(1);
+ boolean storedInThis = fieldItem.getRegisterNumber() == 0;
+ if (storedInThis) {
+ XField field = getXFieldOperand();
+ if ((field.getAccessFlags() & Constants.ACC_PRIVATE) != 0) {
+ String fieldName = field.getName();
+ fieldWOCollections.put(fieldName, getPC());
+ }
+ }
+ } else {
+ clearUserValue(item);
+ }
+ }
+ }
+ break;
+
+ case GETFIELD:
+ if (stack.getStackDepth() > 0) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ if (item.getRegisterNumber() == 0) {
+ XField field = getXFieldOperand();
+ String fieldName = field.getName();
+ if (fieldWOCollections.containsKey(fieldName)) {
+ userObject = fieldName;
+ }
+ }
+ }
+ break;
+ }
+ } finally {
+ stack.sawOpcode(this, seen);
+ if (userObject != null) {
+ if (stack.getStackDepth() > 0) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ item.setUserValue(userObject);
+ }
+ }
+ }
+ }
+
+ private void clearUserValue(OpcodeStack.Item item) {
+ Object uo = item.getUserValue();
+ if (uo instanceof Integer) {
+ localWOCollections.remove(uo);
+ } else if (uo instanceof String) {
+ fieldWOCollections.remove(uo);
+ }
+ item.setUserValue(null);
+ }
+
+ private void processMethodParms() {
+ String sig = getSigConstantOperand();
+ int numParms = Type.getArgumentTypes(sig).length;
+ if (stack.getStackDepth() >= numParms) {
+ for (int i = 0; i < numParms; i++) {
+ clearUserValue(stack.getStackItem(i));
+ }
+ }
+ }
+}
Property changes on: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/WriteOnlyCollection.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|