[Fb-contrib-commit] SF.net SVN: fb-contrib: [600] trunk/fb-contrib/etc
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2006-08-10 04:21:36
|
Revision: 600 Author: dbrosius Date: 2006-08-09 21:21:25 -0700 (Wed, 09 Aug 2006) ViewCVS: http://svn.sourceforge.net/fb-contrib/?rev=600&view=rev Log Message: ----------- Initial checkin UCPM detector Modified Paths: -------------- trunk/fb-contrib/etc/findbugs.xml trunk/fb-contrib/etc/messages.xml Added Paths: ----------- trunk/fb-contrib/samples/UCPM_Sample.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseCharacterParameterizedMethod.java Modified: trunk/fb-contrib/etc/findbugs.xml =================================================================== --- trunk/fb-contrib/etc/findbugs.xml 2006-08-10 01:04:23 UTC (rev 599) +++ trunk/fb-contrib/etc/findbugs.xml 2006-08-10 04:21:25 UTC (rev 600) @@ -234,6 +234,10 @@ speed="moderate" reports="LEST_LOST_EXCEPTION_STACK_TRACE" /> + <Detector class="com.mebigfatguy.fbcontrib.detect.UseCharacterParameterizedMethod" + speed="fast" + reports="UCPM_USE_CHARACTER_PARAMETERIZED_METHOD" /> + <!-- BugPattern --> <BugPattern abbrev="ISB" type="ISB_INEFFICIENT_STRING_BUFFERING" category="PERFORMANCE" /> @@ -291,5 +295,6 @@ <BugPattern abbrev="SACM" type="SACM_STATIC_ARRAY_CREATED_IN_METHOD" category="PERFORMANCE" /> <BugPattern abbrev="RMC" type="RMC_REDUNDANT_METHOD_CALLS" category="PERFORMANCE" /> <BugPattern abbrev="UTA" type="UTA_USE_TO_ARRAY" category="STYLE" /> - <BugPattern abbrev="LEST" type="LEST_LOST_EXCEPTION_STACK_TRACE" category="CORRECTNESS" /> + <BugPattern abbrev="LEST" type="LEST_LOST_EXCEPTION_STACK_TRACE" category="CORRECTNESS" experimental="true" /> + <BugPattern abbrev="UCPM" type="UCPM_USE_CHARACTER_PARAMETERIZED_METHOD" 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-08-10 01:04:23 UTC (rev 599) +++ trunk/fb-contrib/etc/messages.xml 2006-08-10 04:21:25 UTC (rev 600) @@ -630,6 +630,17 @@ ]]> </Details> </Detector> + + <Detector class="com.mebigfatguy.fbcontrib.detect.UseCharacterParameterizedMethod"> + <Details> + <![CDATA[ + <p>looks for methods that pass single character string constants as parameters to + methods that alternatively have an overridden method that accepts a character instead. + It is easier for the method to handle a single character than a String.</p> + <p>It is a fast detector.</p> + ]]> + </Details> + </Detector> <!-- BugPattern --> @@ -1364,6 +1375,18 @@ </Details> </BugPattern> + <BugPattern type="UCPM_USE_CHARACTER_PARAMETERIZED_METHOD"> + <ShortDescription>Method passes constant String of length 1 to character overridden method</ShortDescription> + <LongDescription>Method {1} passes constant String of length 1 to character overridden method</LongDescription> + <Details> + <![CDATA[ + <p>This method passes a constant literal String of length 1 as a parameter to a method, that + exposes a similar method that takes a character. It is simpler and more expedient to handle one + character, rather than pass a string.</p> + ]]> + </Details> + </BugPattern> + <!-- BugCode --> <BugCode abbrev="ISB">Inefficient String Buffering</BugCode> @@ -1417,4 +1440,5 @@ <BugCode abbrev="RMC">Redundant Method Calls</BugCode> <BugCode abbrev="UTA">Use toArray</BugCode> <BugCode abbrev="LEST">Lost Exception Stack Trace</BugCode> + <BugCode abbrev="UCPM">Use Character Parameterized Method</BugCode> </MessageCollection> \ No newline at end of file Added: trunk/fb-contrib/samples/UCPM_Sample.java =================================================================== --- trunk/fb-contrib/samples/UCPM_Sample.java (rev 0) +++ trunk/fb-contrib/samples/UCPM_Sample.java 2006-08-10 04:21:25 UTC (rev 600) @@ -0,0 +1,13 @@ + +public class UCPM_Sample +{ + public int testUcpm1(String s) + { + return s.indexOf("*") * 10; + } + + public String testUcpm2(String s) + { + return s.startsWith("*") ? s.substring(1) : s; + } +} Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseCharacterParameterizedMethod.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseCharacterParameterizedMethod.java (rev 0) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseCharacterParameterizedMethod.java 2006-08-10 04:21:25 UTC (rev 600) @@ -0,0 +1,118 @@ +package com.mebigfatguy.fbcontrib.detect; + +import java.util.BitSet; +import java.util.HashMap; +import java.util.Map; + +import org.apache.bcel.Constants; +import org.apache.bcel.classfile.Code; +import org.apache.bcel.classfile.Method; + +import com.mebigfatguy.fbcontrib.utils.Integer14; + +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.ba.ClassContext; + +/** + * looks for methods that pass single character string constants as parameters to + * methods that alternatively have an overridden method that accepts a character instead. + * It is easier for the method to handle a single character than a String. + */ +public class UseCharacterParameterizedMethod extends BytecodeScanningDetector +{ + private static Map<String, Integer> characterMethods = new HashMap<String, Integer>(); + static { + //characterMethods.put("java/lang/StringBuffer:append:(Ljava/lang/String;)Ljava/lang/StringBuffer;", Integer14.valueOf(0)); + //characterMethods.put("java/lang/StringBuilder:append:(Ljava/lang/String;)Ljava/lang/StringBuilder;", Integer14.valueOf(0)); + characterMethods.put("java/lang/String:indexOf:(Ljava/lang/String;)I", Integer14.valueOf(0)); + characterMethods.put("java/lang/String:indexOf:(Ljava/lang/String;I)I", Integer14.valueOf(1)); + characterMethods.put("java/lang/String:lastIndexOf:(Ljava/lang/String;)I", Integer14.valueOf(0)); + characterMethods.put("java/lang/String:lastIndexOf:(Ljava/lang/String;I)I", Integer14.valueOf(1)); + characterMethods.put("java/lang/String:startsWith:(Ljava/lang/String;)Z", Integer14.valueOf(0)); + } + + private BugReporter bugReporter; + private OpcodeStack stack; + + /** + * constructs a UCPM detector given the reporter to report bugs on + + * @param bugReporter the sync of bug reports + */ + public UseCharacterParameterizedMethod(BugReporter bugReporter) { + this.bugReporter = bugReporter; + } + + /** + * overrides the visitor to create and clear the opcode stack + * + * @param context the context object for the currently parsed class + */ + @Override + public void visitClassContext(final ClassContext context) { + try { + stack = new OpcodeStack(); + super.visitClassContext(context); + } finally { + stack = null; + } + } + + /** + * looks for methods that contain a LDC opcode + * + * @param method the context object of the current method + * @return if the class uses LDC instructions + */ + + private boolean prescreen(Method obj) { + BitSet bytecodeSet = getClassContext().getBytecodeSet(obj); + return (bytecodeSet != null) && (bytecodeSet.get(Constants.LDC)); + } + + /** + * implement the visitor prescreen the method, and reset the stack + * + * @param obj the context object for the currently parsed method + */ + @Override + public void visitCode(Code obj) { + if (prescreen(getMethod())) { + stack.resetForMethodEntry(this); + super.visitCode(obj); + } + } + + /** + * implements the visitor to look for method calls that pass a constant string as a parameter when + * the string is only one character long, and there is an alternate method passing a character. + */ + @Override + public void sawOpcode(int seen) { + try { + stack.mergeJumps(this); + if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) { + String key = getClassConstantOperand() + ":" + getNameConstantOperand() + ":" + getSigConstantOperand(); + Integer parmPos =characterMethods.get(key); + if (parmPos != null) { + int stackPos = parmPos.intValue(); + if (stack.getStackDepth() > stackPos) { + OpcodeStack.Item itm = stack.getStackItem(stackPos); + String con = (String)itm.getConstant(); + if ((con != null) && (con.length() == 1)) { + bugReporter.reportBug(new BugInstance(this, "UCPM_USE_CHARACTER_PARAMETERIZED_METHOD", NORMAL_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this)); + } + } + } + } + } finally { + stack.sawOpcode(this, seen); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |