[Fb-contrib-commit] SF.net SVN: fb-contrib: [564] trunk/fb-contrib/etc
Brought to you by:
dbrosius
From: <dbr...@us...> - 2006-06-19 00:06:12
|
Revision: 564 Author: dbrosius Date: 2006-06-18 17:05:58 -0700 (Sun, 18 Jun 2006) ViewCVS: http://svn.sourceforge.net/fb-contrib/?rev=564&view=rev Log Message: ----------- start working on UTA - not working yet. Modified Paths: -------------- trunk/fb-contrib/etc/findbugs.xml trunk/fb-contrib/etc/messages.xml Added Paths: ----------- trunk/fb-contrib/samples/UTA_Sample.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseToArray.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/MapEntry.java Modified: trunk/fb-contrib/etc/findbugs.xml =================================================================== --- trunk/fb-contrib/etc/findbugs.xml 2006-06-09 03:29:47 UTC (rev 563) +++ trunk/fb-contrib/etc/findbugs.xml 2006-06-19 00:05:58 UTC (rev 564) @@ -211,6 +211,11 @@ speed="fast" reports="RMC_REDUNDANT_METHOD_CALLS" /> + <Detector class="com.mebigfatguy.fbcontrib.detect.UseToArray" + speed="fast" + reports="UTA_USE_TO_ARRAY" + hidden="true" /> + <!-- BugPattern --> <BugPattern abbrev="ISB" type="ISB_INEFFICIENT_STRING_BUFFERING" category="PERFORMANCE" /> @@ -267,4 +272,5 @@ <BugPattern abbrev="ITC" type="ITC_INHERITANCE_TYPE_CHECKING" category="STYLE" experimental="true" /> <BugPattern abbrev="SACM" type="SACM_STATIC_ARRAY_CREATED_IN_METHOD" category="PERFORMANCE" experimental="true" /> <BugPattern abbrev="RMC" type="RMC_REDUNDANT_METHOD_CALLS" category="PERFORMANCE" experimental="true" /> + <BugPattern abbrev="UTA" type="UTA_USE_TO_ARRAY" category="STYLE" experimental="true" /> </FindbugsPlugin> \ No newline at end of file Modified: trunk/fb-contrib/etc/messages.xml =================================================================== --- trunk/fb-contrib/etc/messages.xml 2006-06-09 03:29:47 UTC (rev 563) +++ trunk/fb-contrib/etc/messages.xml 2006-06-19 00:05:58 UTC (rev 564) @@ -600,6 +600,18 @@ ]]> </Details> </Detector> + + <Detector class="com.mebigfatguy.fbcontrib.detect.UseToArray"> + <Details> + <![CDATA[ + <p>looks for code that builds an array of values from a collection, by manually looping + over the elements of the collection, and adding them to the array. It is simpler and + cleaner to use mycollection.toArray(new type[mycollection.size()].</p> + <p>It is a fast detector</p> + ]]> + </Details> + </Detector> + <!-- BugPattern --> @@ -1307,6 +1319,19 @@ </Details> </BugPattern> + <BugPattern type="UTA_USE_TO_ARRAY"> + <ShortDescription>Method manually creates array from collection</ShortDescription> + <LongDescription>Method {1} manually creates array from collection</LongDescription> + <Details> + <![CDATA[ + <p>This method manually loops over a collection, pulling each element out and storing + it in an array to build an array from the collection. It is easier, and clearer to use + the built in collections method toArray. Given a collection 'mycollection' of type T, use + mycollection.toArray(new T[mycollection.size()]); + ]]> + </Details> + </BugPattern> + <!-- BugCode --> <BugCode abbrev="ISB">Inefficient String Buffering</BugCode> @@ -1358,4 +1383,5 @@ <BugCode abbrev="ITC">Inheritance Type Checking</BugCode> <BugCode abbrev="SACM">Static Array Created in Method</BugCode> <BugCode abbrev="RMC">Redundant Method Calls</BugCode> + <BugCode abbrev="UTA">Use toArray</BugCode> </MessageCollection> \ No newline at end of file Added: trunk/fb-contrib/samples/UTA_Sample.java =================================================================== --- trunk/fb-contrib/samples/UTA_Sample.java (rev 0) +++ trunk/fb-contrib/samples/UTA_Sample.java 2006-06-19 00:05:58 UTC (rev 564) @@ -0,0 +1,23 @@ +import java.util.List; + +public class UTA_Sample +{ + public String[] testList1(List<String> l) + { + String[] data = new String[l.size()]; + for (int i = 0; i < l.size(); i++) + data[i] = l.get(i); + + return data; + } + + public Integer[] testList2(List<Integer> l) + { + int size = l.size(); + Integer[] data = new Integer[size]; + for (int i = 0; i < size; i++) + data[i] = l.get(i); + + return data; + } +} Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseToArray.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseToArray.java (rev 0) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseToArray.java 2006-06-19 00:05:58 UTC (rev 564) @@ -0,0 +1,197 @@ +/* + * fb-contrib - Auxilliary detectors for Java programs + * Copyright (C) 2005-2006 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.Map; + +import org.apache.bcel.Repository; +import org.apache.bcel.classfile.Code; +import org.apache.bcel.classfile.JavaClass; + +import com.mebigfatguy.fbcontrib.utils.Integer14; +import com.mebigfatguy.fbcontrib.utils.MapEntry; +import com.mebigfatguy.fbcontrib.utils.RegisterUtils; + +import edu.umd.cs.findbugs.BugReporter; +import edu.umd.cs.findbugs.BytecodeScanningDetector; +import edu.umd.cs.findbugs.OpcodeStack; +import edu.umd.cs.findbugs.ba.ClassContext; + +public class UseToArray extends BytecodeScanningDetector +{ + private static JavaClass collectionClass; + private static ClassNotFoundException ex; + static { + try { + collectionClass = Repository.lookupClass("java/util/Collection"); + } catch (ClassNotFoundException cnfe) { + collectionClass = null; + ex = cnfe; + } + } + + private BugReporter bugReporter; + private OpcodeStack stack; + private Map<Integer, Object> userValues; + /** map of pc of loop starts to map entry of index register to collection register */ + private Map<Integer, Map.Entry<Integer, Integer>> loopStarts; + + + /** + * constructs a UTA detector given the reporter to report bugs on + * @param bugReporter the sync of bug reports + */ + public UseToArray(BugReporter bugReporter) { + this.bugReporter = bugReporter; + } + + public void visitClassContext(ClassContext classContext) { + if (collectionClass == null) { + if (ex != null) { + bugReporter.reportMissingClass(ex); + ex = null; + } + return; + } + + try { + stack = new OpcodeStack(); + super.visitClassContext(classContext); + } finally { + stack = null; + } + } + + @Override + public void visitCode(Code obj) { + try { + stack.resetForMethodEntry(this); + userValues = new HashMap<Integer, Object>(); + loopStarts = new HashMap<Integer, Map.Entry<Integer, Integer>>(); + super.visitCode(obj); + } finally { + userValues = null; + loopStarts = null; + } + } + + @Override + public void sawOpcode(int seen) { + int reg = -1; + Object uValue = null; + boolean sawSize = false; + boolean sawLoad = false; + boolean sawNewArray = false; + + try { + if (seen == INVOKEINTERFACE) { + if ("size".equals(getNameConstantOperand()) && "()I".equals(getSigConstantOperand())) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + reg = isLocalCollection(itm); + if (reg >= 0) { + sawSize = true; + } + } + } + } else if (((seen == ISTORE) || ((seen >= ISTORE_0) && (seen <= ISTORE_3))) + || ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3)))) { + if (stack.getStackDepth() > 0) { + reg = Integer14.valueOf(RegisterUtils.getStoreReg(this, seen)); + uValue = stack.getStackItem(0).getUserValue(); + userValues.put(reg, uValue); + } + } else if (((seen == ILOAD) || ((seen >= ILOAD_0) && (seen <= ILOAD_3))) + || ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3)))) { + sawLoad = true; + } else if (seen == ANEWARRAY) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + uValue = itm.getUserValue(); + sawNewArray = true; + } + } else if (seen == IF_ICMPGE) { + if (stack.getStackDepth() > 1) { + OpcodeStack.Item itm1 = stack.getStackItem(1); + OpcodeStack.Item itm2 = stack.getStackItem(0); + Object const1 = itm1.getConstant(); + reg = itm1.getRegisterNumber(); + if ((reg >= 0) && (const1 instanceof Integer)) { + if (0 == ((Integer) const1).intValue()) { + uValue = itm2.getUserValue(); + if (uValue != null) { + loopStarts.put(Integer14.valueOf(getPC()), new MapEntry<Integer, Integer>(Integer14.valueOf(reg), (Integer)uValue)); + } + } + } + } + } + } catch (ClassNotFoundException cnfe) { + bugReporter.reportMissingClass(cnfe); + } finally { + stack.sawOpcode(this, seen); + if (sawSize) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + itm.setUserValue(Integer14.valueOf(reg)); + } + } else if (sawLoad) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + reg = itm.getRegisterNumber(); + if (reg >= 0) { + uValue = userValues.get(Integer14.valueOf(reg)); + itm.setUserValue(uValue); + } + } + } else if (sawNewArray) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + itm.setUserValue(uValue); + } + } + } + } + + /** + * determines if the stack item refers to a collection that is stored in a local variable + * + * param item the stack item to check + * + * @return the register number of the local variable that this collection refers to, or -1 + * @throws ClassNotFoundException if the items class cannot be found + */ + private int isLocalCollection(OpcodeStack.Item item) throws ClassNotFoundException { + Integer aliasReg = (Integer)item.getUserValue(); + if (aliasReg != null) + return aliasReg.intValue(); + + int reg = item.getRegisterNumber(); + if (reg < 0) + return -1; + + JavaClass cls = item.getJavaClass(); + if (cls.implementationOf(collectionClass)) + return reg; + + return -1; + } + +} Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/MapEntry.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/MapEntry.java (rev 0) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/MapEntry.java 2006-06-19 00:05:58 UTC (rev 564) @@ -0,0 +1,55 @@ +/* + * fb-contrib - Auxilliary detectors for Java programs + * Copyright (C) 2005-2006 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.utils; + +import java.util.Map.Entry; + +/** + * a simple implementation of the Map.Entry interface + */ +public class MapEntry<K,V> implements Entry<K,V> { + + private K key; + private V value; + + public MapEntry() { + key = null; + value = null; + } + + public MapEntry(K k, V v) { + key = k; + value = v; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V v) { + V temp = value; + value = v; + return temp; + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |