[Fb-contrib-commit] SF.net SVN: fb-contrib: [655] trunk/fb-contrib
Brought to you by:
dbrosius
From: <dbr...@us...> - 2006-09-24 19:51:25
|
Revision: 655 http://svn.sourceforge.net/fb-contrib/?rev=655&view=rev Author: dbrosius Date: 2006-09-24 12:51:17 -0700 (Sun, 24 Sep 2006) Log Message: ----------- Modified Paths: -------------- trunk/fb-contrib/.classpath Removed Paths: ------------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/RedundantMethodCalls.java Modified: trunk/fb-contrib/.classpath =================================================================== --- trunk/fb-contrib/.classpath 2006-09-24 19:49:47 UTC (rev 654) +++ trunk/fb-contrib/.classpath 2006-09-24 19:51:17 UTC (rev 655) @@ -3,8 +3,7 @@ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="src" path="src"/> <classpathentry kind="src" path="samples"/> - <classpathentry kind="lib" path="O:/fb-contrib/fb-contrib/lib/findbugs.jar"/> - <classpathentry kind="lib" path="O:/fb-contrib/fb-contrib/lib/bcel.jar"/> - <classpathentry kind="lib" path="O:/fb-contrib/fb-contrib/samples/lib/jsp-api.jar"/> + <classpathentry kind="lib" path="O:/fb-contrib/trunk/fb-contrib/lib/findbugs.jar"/> + <classpathentry kind="lib" path="O:/fb-contrib/trunk/fb-contrib/lib/bcel.jar"/> <classpathentry kind="output" path="classes"/> </classpath> Deleted: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/RedundantMethodCalls.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/RedundantMethodCalls.java 2006-09-24 19:49:47 UTC (rev 654) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/RedundantMethodCalls.java 2006-09-24 19:51:17 UTC (rev 655) @@ -1,265 +0,0 @@ -/* - * 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.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import org.apache.bcel.classfile.Code; -import org.apache.bcel.classfile.CodeException; -import org.apache.bcel.generic.Type; - -import com.mebigfatguy.fbcontrib.collect.Statistics; -import com.mebigfatguy.fbcontrib.utils.Integer14; -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.FieldAnnotation; -import edu.umd.cs.findbugs.OpcodeStack; -import edu.umd.cs.findbugs.ba.ClassContext; - -/** - * looks for calls of the same method on the same object when that object hasn't changed. - * This often is redundant, and the second call can be removed, or combined. - */ -public class RedundantMethodCalls extends BytecodeScanningDetector -{ - public static final String RMC_RISKY_FIELD_USER_KEY = "fbcontrib.RMC.riskynames"; - public static final String RMC_RISKY_CLASS_USER_KEY = "fbcontrib.RMC.riskyclasses"; - - private static Set<String> riskyMethodNameContents = new HashSet<String>(); - static { - riskyMethodNameContents.add("next"); - riskyMethodNameContents.add("add"); - riskyMethodNameContents.add("append"); - riskyMethodNameContents.add("put"); - riskyMethodNameContents.add("remove"); - riskyMethodNameContents.add("read"); - riskyMethodNameContents.add("write"); - riskyMethodNameContents.add("push"); - riskyMethodNameContents.add("pop"); - riskyMethodNameContents.add("skip"); - riskyMethodNameContents.add("clone"); - - String userNameProp = System.getProperty(RMC_RISKY_FIELD_USER_KEY); - if (userNameProp != null) { - String[] userNames = userNameProp.split("\\s*,\\s*"); - for (String name : userNames) - riskyMethodNameContents.add(name.toLowerCase()); - } - } - private static Set<String> riskyClassNames = new HashSet<String>(); - static { - riskyClassNames.add("java/nio/ByteBuffer"); - riskyClassNames.add("java/io/DataInputStream"); - riskyClassNames.add("java/io/ObjectInputStream"); - String userNameProp = System.getProperty(RMC_RISKY_CLASS_USER_KEY); - if (userNameProp != null) { - String[] userNames = userNameProp.split("\\s*,\\s*"); - for (String name : userNames) - riskyClassNames.add(name); - } - } - - private BugReporter bugReporter; - private OpcodeStack stack = null; - private Map<Integer, MethodCall> localMethodCalls = null; - private Map<String, MethodCall> fieldMethodCalls = null; - private Set<Integer> branchTargets = null; - - /** - * constructs a RMC detector given the reporter to report bugs on - * @param bugReporter the sync of bug reports - */ - public RedundantMethodCalls(BugReporter bugReporter) { - this.bugReporter = bugReporter; - } - - /** - * implements the visitor to create and clear the stack, method call maps, and branch targets - * - * @param classContext the context object of the currently visited class - */ - public void visitClassContext(ClassContext classContext) { - try { - stack = new OpcodeStack(); - localMethodCalls = new HashMap<Integer, MethodCall>(); - fieldMethodCalls = new HashMap<String, MethodCall>(); - branchTargets = new HashSet<Integer>(); - super.visitClassContext(classContext); - } finally { - stack = null; - localMethodCalls = null; - fieldMethodCalls = null; - branchTargets = null; - } - } - - /** - * implements the visitor to reset the stack, and method call maps for new method - * - * @param obj the context object of the currently parsed code block - */ - public void visitCode(Code obj) { - stack.resetForMethodEntry(this); - localMethodCalls.clear(); - fieldMethodCalls.clear(); - branchTargets.clear(); - CodeException[] codeExceptions = obj.getExceptionTable(); - for (CodeException codeEx : codeExceptions) { - branchTargets.add(codeEx.getHandlerPC()); - } - super.visitCode(obj); - } - - /** - * implements the visitor to look for repetitive calls to the same method on the same object - * using the same constant parameters. These methods must return a value. - * - * @param seen the opcode of the currently parsed instruction - */ - public void sawOpcode(int seen) { - try { - stack.mergeJumps(this); - if (branchTargets.remove(Integer14.valueOf(getPC()))) { - localMethodCalls.clear(); - fieldMethodCalls.clear(); - } - - if (((seen >= IFEQ) && (seen <= GOTO)) || ((seen >= IFNULL) && (seen <= GOTO_W))) { - branchTargets.add(Integer14.valueOf(getBranchTarget())); - } else if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) { - int[] offsets = getSwitchOffsets(); - int pc = getPC(); - for (int offset : offsets) { - branchTargets.add(Integer14.valueOf(offset + pc)); - } - } else if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) { - localMethodCalls.remove(Integer14.valueOf(RegisterUtils.getAStoreReg(this, seen))); - } else if (seen == PUTFIELD) { - fieldMethodCalls.remove(getNameConstantOperand()); - } else if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) { - String className = getClassConstantOperand(); - String methodName = getNameConstantOperand(); - String signature = getSigConstantOperand(); - int parmCount = Type.getArgumentTypes(signature).length; - if (stack.getStackDepth() > parmCount) { - Object[] parmConstants = new Object[parmCount]; - for (int i = 0; i < parmCount; i++) { - OpcodeStack.Item parm = stack.getStackItem(i); - parmConstants[i] = parm.getConstant(); - if (parmConstants[i] == null) - return; - } - OpcodeStack.Item obj = stack.getStackItem(parmCount); - int reg = obj.getRegisterNumber(); - FieldAnnotation fa = obj.getField(); - - MethodCall mc; - if (reg >= 0) { - mc = localMethodCalls.get(Integer14.valueOf(reg)); - } else if (fa != null) { - mc = fieldMethodCalls.get(fa.getFieldName()); - } else - return; - - if (mc != null) { - if (!signature.endsWith("V") && methodName.equals(mc.getName()) && signature.equals(mc.getSignature()) && !isRiskyName(className, methodName)) { - Object[] parms = mc.getParms(); - if (Arrays.equals(parms, parmConstants)) { - Statistics statistics = Statistics.getStatistics(); - bugReporter.reportBug(new BugInstance(this, "RMC_REDUNDANT_METHOD_CALLS", statistics.isSimpleGetter(getClassConstantOperand(), methodName, signature) ? EXP_PRIORITY : NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this) - .addString(methodName + signature)); - } - } - if (reg >= 0) { - localMethodCalls.remove(Integer14.valueOf(reg)); - } else { - fieldMethodCalls.remove(fa.getFieldName()); - } - } else { - if (reg >= 0) { - localMethodCalls.put(Integer14.valueOf(reg), new MethodCall(methodName, signature, parmConstants)); - } else if (fa != null) { - fieldMethodCalls.put(fa.getFieldName(), new MethodCall(methodName, signature, parmConstants)); - } - } - } - } - } finally { - stack.sawOpcode(this, seen); - } - } - - /** - * returns true if the class or method name contains a pattern that is considered likely to be this modifying - * - * @param className the class name to check - * @param methodName the method name to check - * @return whether the method sounds like it modifies this - */ - private boolean isRiskyName(String className, String methodName) { - if (riskyClassNames.contains(className)) - return true; - - methodName = methodName.toLowerCase(Locale.ENGLISH); - for (String riskyName : riskyMethodNameContents) { - if (methodName.indexOf(riskyName) >= 0) - return true; - } - return false; - } - - /** - * contains information about a method call - */ - static class MethodCall - { - private String methodName; - private String methodSignature; - private Object[] methodParms; - - public MethodCall(String name, String signature, Object[] parms) { - methodName = name; - methodSignature = signature; - methodParms = parms; - } - - public String getName() { - return methodName; - } - - public String getSignature() { - return methodSignature; - } - - public Object[] getParms() { - return methodParms; - } - } -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |