[Fb-contrib-commit] SF.net SVN: fb-contrib: [505] trunk/fb-contrib/etc
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2006-04-28 03:08:22
|
Revision: 505 Author: dbrosius Date: 2006-04-27 20:07:55 -0700 (Thu, 27 Apr 2006) ViewCVS: http://svn.sourceforge.net/fb-contrib/?rev=505&view=rev Log Message: ----------- initial checkin - new UEC Detector Modified Paths: -------------- trunk/fb-contrib/etc/findbugs.xml trunk/fb-contrib/etc/messages.xml Added Paths: ----------- trunk/fb-contrib/samples/UEC_Sample.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java Modified: trunk/fb-contrib/etc/findbugs.xml =================================================================== --- trunk/fb-contrib/etc/findbugs.xml 2006-04-27 03:27:09 UTC (rev 504) +++ trunk/fb-contrib/etc/findbugs.xml 2006-04-28 03:07:55 UTC (rev 505) @@ -187,6 +187,10 @@ speed="fast" reports="S508C_NULL_LAYOUT,S508C_NO_SETLABELFOR,S508C_NO_SETSIZE,S508C_NON_ACCESSIBLE_JCOMPONENT" /> + <Detector class="com.mebigfatguy.fbcontrib.detect.UseEnumCollections" + speed="fast" + reports="UEC_USE_ENUM_COLLECTIONS" /> + <!-- BugPattern --> <BugPattern abbrev="ISB" type="ISB_INEFFICIENT_STRING_BUFFERING" category="PERFORMANCE" /> @@ -235,4 +239,5 @@ <BugPattern abbrev="S508C" type="S508C_NO_SETLABELFOR" category="CORRECTNESS" experimental="true" /> <BugPattern abbrev="S508C" type="S508C_NO_SETSIZE" category="CORRECTNESS" experimental="true" /> <BugPattern abbrev="S508C" type="S508C_NON_ACCESSIBLE_JCOMPONENT" category="CORRECTNESS" experimental="true"/> + <BugPattern abbrev="UEC" type="UEC_USE_ENUM_COLLECTIONS" category="PERFORMANCE" experimental="true" /> </FindbugsPlugin> \ No newline at end of file Modified: trunk/fb-contrib/etc/messages.xml =================================================================== --- trunk/fb-contrib/etc/messages.xml 2006-04-27 03:27:09 UTC (rev 504) +++ trunk/fb-contrib/etc/messages.xml 2006-04-28 03:07:55 UTC (rev 505) @@ -537,6 +537,15 @@ ]]> </Details> </Detector> + + <Detector class="com.mebigfatguy.fbcontrib.detect.UseEnumCollections"> + <Details> + <![CDATA[ + <p>looks for use of sets and maps using enums. It is more efficient to use EnumSet or EnumMap</p> + <p>It is a fast detector</p> + ]]> + </Details> + </Detector> <!-- BugPattern --> @@ -1141,6 +1150,17 @@ </Details> </BugPattern> + <BugPattern type="UEC_USE_ENUM_COLLECTIONS"> + <ShortDescription>Class uses an ordinary set or map with an enum class as the key</ShortDescription> + <LongDescription>Class {0} uses an ordinary set or map with an enum class as the key</LongDescription> + <Details> + <![CDATA[ + <p>This class uses an ordinary set or map collection and uses an enum class as the key type. + It is better performant to use the jdk 1.5 EnumSet or EnumMap classes.</p> + ]]> + </Details> + </BugPattern> + <!-- BugCode --> <BugCode abbrev="ISB">Inefficient String Buffering</BugCode> @@ -1186,4 +1206,5 @@ <BugCode abbrev="NOS">Non Owned Synchronization</BugCode> <BugCode abbrev="NRTL">Non Recycleable Taglib</BugCode> <BugCode abbrev="S508C">Section 508 Compliance Violations</BugCode> + <BugCode abbrev="UEC">Use Enum Collections</BugCode> </MessageCollection> \ No newline at end of file Added: trunk/fb-contrib/samples/UEC_Sample.java =================================================================== --- trunk/fb-contrib/samples/UEC_Sample.java (rev 0) +++ trunk/fb-contrib/samples/UEC_Sample.java 2006-04-28 03:07:55 UTC (rev 505) @@ -0,0 +1,31 @@ +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + + +public class UEC_Sample +{ + enum Suite { Spades, Hearts, Clubs, Diamonds }; + + private Set<Suite> wildSuites = new HashSet<Suite>(); + private EnumSet<Suite> eWildSuites = EnumSet.noneOf(Suite.class); + + public Map<Suite, Integer> deal() { + Map<Suite, Integer> hand = new HashMap<Suite, Integer>(); + hand.put(Suite.Spades, new Integer(10)); + hand.put(Suite.Hearts, new Integer(9)); + + return hand; + } + + public EnumMap<Suite, Integer> eDeal() { + EnumMap<Suite, Integer> hand = new EnumMap(Suite.class); + hand.put(Suite.Spades, new Integer(10)); + hand.put(Suite.Hearts, new Integer(9)); + + return hand; + } +} Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java (rev 0) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java 2006-04-28 03:07:55 UTC (rev 505) @@ -0,0 +1,108 @@ +package com.mebigfatguy.fbcontrib.detect; + +import org.apache.bcel.Constants; +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; + +import edu.umd.cs.findbugs.BugInstance; +import edu.umd.cs.findbugs.BugReporter; +import edu.umd.cs.findbugs.BytecodeScanningDetector; +import edu.umd.cs.findbugs.ba.ClassContext; + +/** + * looks for uses of sets or maps where the key is an enum. In these cases, it is + * more efficient to use EnumSet or EnumMap. It is a jdk1.5 only detector. + */ +public class UseEnumCollections extends BytecodeScanningDetector +{ + private static final int SEEN_NOTHING = 0; + private static final int SEEN_BIPUSH = 1; + private static final int SEEN_NEWINT = 2; + + private BugReporter bugReporter; + private int state; + private boolean methodReported; + /** + * constructs a UEC detector given the reporter to report bugs on + * @param bugReporter the sync of bug reports + */ + public UseEnumCollections(BugReporter bugReporter) { + this.bugReporter = bugReporter; + } + + /** + * implements the visitor to check that the class is greater or equal than 1.5 + * + * @param classContext the context object for the currently parsed class + */ + public void visitClassContext(ClassContext classContext) { + try { + JavaClass cls = classContext.getJavaClass(); + if (cls.getMajor() >= Constants.MAJOR_1_5) { + super.visitClassContext(classContext); + } + } finally { + + } + } + + /** + * implements the visitor to reset the state + * + * @param obj the context object for the currently parsed method + */ + public void visitMethod(Method obj) { + state = SEEN_NOTHING; + methodReported = false; + super.visitMethod(obj); + } + + public void sawOpcode(int seen) { + if (methodReported) + return; + + switch (state) { + case SEEN_NOTHING: + if (seen == BIPUSH) + state = SEEN_BIPUSH; + break; + + case SEEN_BIPUSH: + if ((seen == INVOKESPECIAL) + && ("java/lang/Integer".equals(getClassConstantOperand()) + && ("<init>".equals(getNameConstantOperand()) + && ("(I)V".equals(getSigConstantOperand()))))) + state = SEEN_NEWINT; + else + state = SEEN_NOTHING; + break; + + case SEEN_NEWINT: + boolean bug = false; + if (seen == INVOKEINTERFACE) { + String clsName = getClassConstantOperand(); + String methodName = getNameConstantOperand(); + String signature = getSigConstantOperand(); + if (("java/util/Map".equals(clsName)) + && ("put".equals(methodName)) + && ("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;".equals(signature))) { + bug = true; + } else if (("java/util/Set".equals(clsName)) + && ("add".equals(methodName)) + && ("(Ljava/lang/Object;)Ljava/lang/Object;".equals(signature))) { + bug = true; + } + + if (bug) { + bugReporter.reportBug(new BugInstance(this, "UEC_USE_ENUM_COLLECTIONS", NORMAL_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this)); + methodReported = true; + } + } + state = SEEN_NOTHING; + break; + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |