[Fb-contrib-commit] SF.net SVN: fb-contrib: [612] trunk/fb-contrib/etc
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2006-08-12 15:21:30
|
Revision: 612 Author: dbrosius Date: 2006-08-12 08:20:44 -0700 (Sat, 12 Aug 2006) ViewCVS: http://svn.sourceforge.net/fb-contrib/?rev=612&view=rev Log Message: ----------- initial checkin, new TR detector Modified Paths: -------------- trunk/fb-contrib/etc/findbugs.xml trunk/fb-contrib/etc/messages.xml Added Paths: ----------- trunk/fb-contrib/samples/TR_Sample.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/TailRecursion.java Modified: trunk/fb-contrib/etc/findbugs.xml =================================================================== --- trunk/fb-contrib/etc/findbugs.xml 2006-08-12 13:38:45 UTC (rev 611) +++ trunk/fb-contrib/etc/findbugs.xml 2006-08-12 15:20:44 UTC (rev 612) @@ -238,6 +238,10 @@ speed="fast" reports="UCPM_USE_CHARACTER_PARAMETERIZED_METHOD" /> + <Detector class="com.mebigfatguy.fbcontrib.detect.TailRecursion" + speed="fast" + reports="TR_TAIL_RECURSION" /> + <!-- BugPattern --> <BugPattern abbrev="ISB" type="ISB_INEFFICIENT_STRING_BUFFERING" category="PERFORMANCE" /> @@ -297,4 +301,5 @@ <BugPattern abbrev="UTA" type="UTA_USE_TO_ARRAY" category="STYLE" /> <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" /> + <BugPattern abbrev="TR" type="TR_TAIL_RECURSION" 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-12 13:38:45 UTC (rev 611) +++ trunk/fb-contrib/etc/messages.xml 2006-08-12 15:20:44 UTC (rev 612) @@ -641,6 +641,17 @@ ]]> </Details> </Detector> + + <Detector class="com.mebigfatguy.fbcontrib.detect.TailRecursion"> + <Details> + <![CDATA[ + <p>looks for methods that make a recursive call to itself as the last statement in the + method. This tail recursion could be converted into a simple loop which would improve + the performance and stack requirements.</p> + <p>It is a fast detector.</p> + ]]> + </Details> + </Detector> <!-- BugPattern --> @@ -1387,6 +1398,18 @@ </Details> </BugPattern> + <BugPattern type="TR_TAIL_RECURSION"> + <ShortDescription>Method employs tail recursion</ShortDescription> + <LongDescription>Method {1} employs tail recursion</LongDescription> + <Details> + <![CDATA[ + <p>This method recursively calls itself as the last statement of the method + (Tail Recursion). This method can be easily refactored into a simple loop, which + will make it more performant, and reduce the stack size requirements. + ]]> + </Details> + </BugPattern> + <!-- BugCode --> <BugCode abbrev="ISB">Inefficient String Buffering</BugCode> @@ -1441,4 +1464,5 @@ <BugCode abbrev="UTA">Use toArray</BugCode> <BugCode abbrev="LEST">Lost Exception Stack Trace</BugCode> <BugCode abbrev="UCPM">Use Character Parameterized Method</BugCode> + <BugCode abbrev="TR">Tail Recursion</BugCode> </MessageCollection> \ No newline at end of file Added: trunk/fb-contrib/samples/TR_Sample.java =================================================================== --- trunk/fb-contrib/samples/TR_Sample.java (rev 0) +++ trunk/fb-contrib/samples/TR_Sample.java 2006-08-12 15:20:44 UTC (rev 612) @@ -0,0 +1,11 @@ + +public class TR_Sample +{ + public int factorial(int n) + { + if (n == 1) + return 1; + + return n * factorial(n-1); + } +} Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/TailRecursion.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/TailRecursion.java (rev 0) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/TailRecursion.java 2006-08-12 15:20:44 UTC (rev 612) @@ -0,0 +1,94 @@ +/* + * 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 org.apache.bcel.classfile.Code; +import org.apache.bcel.classfile.Method; + +import edu.umd.cs.findbugs.BugInstance; +import edu.umd.cs.findbugs.BugReporter; +import edu.umd.cs.findbugs.BytecodeScanningDetector; + +/** + * looks for methods that make a recursive call to itself as the last statement in the + * method. This tail recursion could be converted into a simple loop which would improve + * the performance and stack requirements. + */ +public class TailRecursion extends BytecodeScanningDetector +{ + public static final int TAILRECURSIONFUDGE = 6; + + private BugReporter bugReporter; + private int trPCPos; + private boolean possibleTailRecursion; + /** + * constructs a TR detector given the reporter to report bugs on + + * @param bugReporter the sync of bug reports + */ + public TailRecursion(BugReporter bugReporter) { + this.bugReporter = bugReporter; + } + + /** + * implements the visitor to figure the pc where the method call must occur + * depending on whether the method returns a value, or not. + * + * @param obj the context object of the currently parsed method + */ + @Override + public void visitMethod(Method obj) { + Code c = obj.getCode(); + if (c != null) { + byte[] opcodes = c.getCode(); + if (opcodes != null) { + trPCPos = c.getCode().length - 1; + if (!obj.getSignature().endsWith("V")) { + trPCPos -= 1; + } + trPCPos -= TAILRECURSIONFUDGE; + possibleTailRecursion = true; + super.visitMethod(obj); + } + } + } + + /** + * implements the visitor to find methods that employ tail recursion + * + * @param seen the opcode of the currently parsed instruction + */ + @Override + public void sawOpcode(int seen) { + if (seen == INVOKEVIRTUAL) { + boolean isRecursion = (getMethodName().equals(getNameConstantOperand())) + && (getMethodSig().equals(getSigConstantOperand())) + && (getClassName().equals(getClassConstantOperand())); + + if (isRecursion && possibleTailRecursion && (getPC() >= trPCPos)) { + bugReporter.reportBug(new BugInstance(this, "TR_TAIL_RECURSION", NORMAL_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this)); + } + else + possibleTailRecursion = false; + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |