Package com.mebigfatguy.fbcontrib.detect
Class PossiblyRedundantMethodCalls
- java.lang.Object
-
- edu.umd.cs.findbugs.visitclass.BetterVisitor
-
- edu.umd.cs.findbugs.visitclass.PreorderVisitor
-
- edu.umd.cs.findbugs.visitclass.AnnotationVisitor
-
- edu.umd.cs.findbugs.visitclass.DismantleBytecode
-
- edu.umd.cs.findbugs.BytecodeScanningDetector
-
- com.mebigfatguy.fbcontrib.detect.PossiblyRedundantMethodCalls
-
- All Implemented Interfaces:
edu.umd.cs.findbugs.Detector
,edu.umd.cs.findbugs.Priorities
,edu.umd.cs.findbugs.visitclass.Constants2
,org.apache.bcel.classfile.Visitor
,org.apache.bcel.Constants
@CustomUserValue public class PossiblyRedundantMethodCalls extends edu.umd.cs.findbugs.BytecodeScanningDetector
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.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
PossiblyRedundantMethodCalls.FieldInfo
contains information about a field access(package private) static class
PossiblyRedundantMethodCalls.MethodCall
contains information about a method call
-
Field Summary
Fields Modifier and Type Field Description private java.util.BitSet
branchTargets
private edu.umd.cs.findbugs.BugReporter
bugReporter
private static java.util.Set<FQMethod>
commonMethods
private java.util.Map<PossiblyRedundantMethodCalls.FieldInfo,PossiblyRedundantMethodCalls.MethodCall>
fieldMethodCalls
private static int
highByteCountLimit
private static int
highMethodCallLimit
private java.util.Map<java.lang.Integer,PossiblyRedundantMethodCalls.MethodCall>
localMethodCalls
private static int
lowByteCountLimit
private static int
lowMethodCallLimit
private static int
normalByteCountLimit
private static int
normalMethodCallLimit
static java.lang.String
PRMC_HIGH_BYTECOUNT
static java.lang.String
PRMC_HIGH_METHODCALLS
static java.lang.String
PRMC_LOW_BYTECOUNT
static java.lang.String
PRMC_LOW_METHODCALLS
static java.lang.String
PRMC_NORMAL_BYTECOUNT
static java.lang.String
PRMC_NORMAL_METHODCALLS
static java.lang.String
PRMC_RISKY_CLASS_USER_KEY
static java.lang.String
PRMC_RISKY_FIELD_USER_KEY
private static java.util.Set<java.lang.String>
riskyClassNames
private static java.util.Set<java.lang.String>
riskyMethodNameContents
a collection of names that are to be checked against a currently parsed method, to see if that method is risky to be called redundant.private edu.umd.cs.findbugs.OpcodeStack
stack
private java.util.Map<java.lang.String,PossiblyRedundantMethodCalls.MethodCall>
staticMethodCalls
-
Fields inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode
codeBytes, lineNumberTable, M_BR, M_CP, M_INT, M_PAD, M_R, M_UINT
-
Fields inherited from interface org.apache.bcel.Constants
AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_SYPER, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, APPEND_FRAME, APPEND_FRAME_MAX, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_ANNOTATION_DEFAULT, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_ENCLOSING_METHOD, ATTR_EXCEPTIONS, ATTR_INNER_CLASSES, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_LOCAL_VARIABLE_TYPE_TABLE, ATTR_PMG, ATTR_RUNTIME_VISIBLE_ANNOTATIONS, ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_SIGNATURE, ATTR_SOURCE_FILE, ATTR_STACK_MAP, ATTR_STACK_MAP_TABLE, ATTR_SYNTHETIC, ATTR_UNKNOWN, ATTRIBUTE_NAMES, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CHOP_FRAME, CHOP_FRAME_MAX, CLASS_TYPE_NAMES, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_InvokeDynamic, CONSTANT_Long, CONSTANT_MethodHandle, CONSTANT_Methodref, CONSTANT_MethodType, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, FULL_FRAME, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, ITEM_Bogus, ITEM_Double, ITEM_Float, ITEM_InitObject, ITEM_Integer, ITEM_Long, ITEM_NAMES, ITEM_NewObject, ITEM_Null, ITEM_Object, IUSHR, IXOR, JSR, JSR_W, KNOWN_ATTRIBUTES, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAJOR_1_4, MAJOR_1_5, MAJOR_1_6, MAJOR_1_7, MAJOR_1_8, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MINOR_1_4, MINOR_1_5, MINOR_1_6, MINOR_1_7, MINOR_1_8, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SAME_FRAME, SAME_FRAME_EXTENDED, SAME_FRAME_MAX, SAME_LOCALS_1_STACK_ITEM_FRAME, SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED, SAME_LOCALS_1_STACK_ITEM_FRAME_MAX, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
-
-
Constructor Summary
Constructors Constructor Description PossiblyRedundantMethodCalls(edu.umd.cs.findbugs.BugReporter bugReporter)
constructs a PRMC detector given the reporter to report bugs on
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private void
clearFieldMethods(java.lang.String fieldSource)
private static int
getBugPriority(java.lang.String methodName, MethodInfo mi)
returns the bug priority based on metrics about the methodprivate int
getLineNumber(int pc)
returns the source line number for the pc, or just the pc if the line number table doesn't existprivate static boolean
isRiskyName(java.lang.String className, java.lang.String methodName)
returns true if the class or method name contains a pattern that is considered likely to be this modifyingvoid
sawOpcode(int seen)
implements the visitor to look for repetitive calls to the same method on the same object using the same constant parameters.void
visitClassContext(edu.umd.cs.findbugs.ba.ClassContext classContext)
implements the visitor to create and clear the stack, method call maps, and branch targetsvoid
visitCode(org.apache.bcel.classfile.Code obj)
implements the visitor to reset the stack, and method call maps for new method Note: that when collecting branch targets, it's unfortunately not good enough to just collect the handler pcs, as javac plays fast and loose, and will sometimes jam code below the end pc and before the first handler pc, which gets executed.-
Methods inherited from class edu.umd.cs.findbugs.BytecodeScanningDetector
getClassContext, report, shouldVisitCode
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode
afterOpcode, areOppositeBranches, atCatchBlock, beforeOpcode, getBranchFallThrough, getBranchOffset, getBranchTarget, getClassConstantOperand, getClassDescriptorOperand, getCodeByte, getConstantRefOperand, getDefaultSwitchOffset, getDottedClassConstantOperand, getFieldDescriptorOperand, getIntConstant, getLongConstant, getMaxPC, getMethodDescriptorOperand, getNameConstantOperand, getNextCodeByte, getNextOpcode, getNextPC, getOpcode, getPC, getPrevOpcode, getRefConstantOperand, getRefFieldIsStatic, getRegisterOperand, getSigConstantOperand, getStringConstantOperand, getSwitchLabels, getSwitchOffsets, getXClassOperand, getXFieldOperand, getXMethodOperand, isBranch, isMethodCall, isRegisterLoad, isRegisterStore, isRegisterStore, isReturn, isShift, isSwitch, isWideOpcode, printOpCode, sawBranchTo, sawClass, sawDouble, sawField, sawFloat, sawIMethod, sawInt, sawLong, sawMethod, sawRegister, sawString, visit
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.AnnotationVisitor
getAnnotationParameterAsString, getAnnotationParameterAsStringArray, visitAnnotation, visitAnnotation, visitParameterAnnotation, visitParameterAnnotation, visitSyntheticParameterAnnotation
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.PreorderVisitor
amVisitingMainMethod, asUnsignedByte, doVisitMethod, getClassDescriptor, getClassName, getCode, getConstantPool, getDottedClassName, getDottedFieldSig, getDottedMethodSig, getDottedSuperclassName, getField, getFieldDescriptor, getFieldIsStatic, getFieldName, getFieldSig, getFullyQualifiedFieldName, getFullyQualifiedMethodName, getMethod, getMethodDescriptor, getMethodName, getMethodSig, getMethodVisitOrder, getNumberArguments, getNumberMethodArguments, getPackageName, getSizeOfSurroundingTryBlock, getSizeOfSurroundingTryBlock, getSourceFile, getStringFromIndex, getSuperclassName, getSurroundingCaughtExceptions, getSurroundingCaughtExceptions, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitStackMapTable, visitStackMapTableEntry
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.BetterVisitor
clone, report, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visitCodeException, visitConstantClass, visitConstantDouble, visitConstantFieldref, visitConstantFloat, visitConstantInteger, visitConstantInterfaceMethodref, visitConstantLong, visitConstantMethodref, visitConstantNameAndType, visitConstantString, visitConstantUtf8, visitConstantValue, visitDeprecated, visitExceptionTable, visitField, visitInnerClass, visitLineNumber, visitLocalVariable, visitLocalVariableTypeTable, visitMethod, visitSignature, visitSourceFile, visitStackMap, visitStackMapEntry, visitSynthetic, visitUnknown
-
-
-
-
Field Detail
-
PRMC_RISKY_FIELD_USER_KEY
public static final java.lang.String PRMC_RISKY_FIELD_USER_KEY
- See Also:
- Constant Field Values
-
PRMC_RISKY_CLASS_USER_KEY
public static final java.lang.String PRMC_RISKY_CLASS_USER_KEY
- See Also:
- Constant Field Values
-
PRMC_HIGH_BYTECOUNT
public static final java.lang.String PRMC_HIGH_BYTECOUNT
- See Also:
- Constant Field Values
-
PRMC_HIGH_METHODCALLS
public static final java.lang.String PRMC_HIGH_METHODCALLS
- See Also:
- Constant Field Values
-
PRMC_NORMAL_BYTECOUNT
public static final java.lang.String PRMC_NORMAL_BYTECOUNT
- See Also:
- Constant Field Values
-
PRMC_NORMAL_METHODCALLS
public static final java.lang.String PRMC_NORMAL_METHODCALLS
- See Also:
- Constant Field Values
-
PRMC_LOW_BYTECOUNT
public static final java.lang.String PRMC_LOW_BYTECOUNT
- See Also:
- Constant Field Values
-
PRMC_LOW_METHODCALLS
public static final java.lang.String PRMC_LOW_METHODCALLS
- See Also:
- Constant Field Values
-
riskyMethodNameContents
private static java.util.Set<java.lang.String> riskyMethodNameContents
a collection of names that are to be checked against a currently parsed method, to see if that method is risky to be called redundant. The contents are either- a simple name that can be found as part of the methodName, like "destroy" which would match destroy(), or destroyAll()
- a fully qualified method name that exactly matches a method, like "java/lang/String.valueOf"
-
highByteCountLimit
private static int highByteCountLimit
-
highMethodCallLimit
private static int highMethodCallLimit
-
normalByteCountLimit
private static int normalByteCountLimit
-
normalMethodCallLimit
private static int normalMethodCallLimit
-
lowByteCountLimit
private static int lowByteCountLimit
-
lowMethodCallLimit
private static int lowMethodCallLimit
-
riskyClassNames
private static java.util.Set<java.lang.String> riskyClassNames
-
commonMethods
private static final java.util.Set<FQMethod> commonMethods
-
bugReporter
private final edu.umd.cs.findbugs.BugReporter bugReporter
-
stack
private edu.umd.cs.findbugs.OpcodeStack stack
-
localMethodCalls
private java.util.Map<java.lang.Integer,PossiblyRedundantMethodCalls.MethodCall> localMethodCalls
-
fieldMethodCalls
private java.util.Map<PossiblyRedundantMethodCalls.FieldInfo,PossiblyRedundantMethodCalls.MethodCall> fieldMethodCalls
-
staticMethodCalls
private java.util.Map<java.lang.String,PossiblyRedundantMethodCalls.MethodCall> staticMethodCalls
-
branchTargets
private java.util.BitSet branchTargets
-
-
Method Detail
-
visitClassContext
public void visitClassContext(edu.umd.cs.findbugs.ba.ClassContext classContext)
implements the visitor to create and clear the stack, method call maps, and branch targets- Specified by:
visitClassContext
in interfaceedu.umd.cs.findbugs.Detector
- Overrides:
visitClassContext
in classedu.umd.cs.findbugs.BytecodeScanningDetector
- Parameters:
classContext
- the context object of the currently visited class
-
visitCode
public void visitCode(org.apache.bcel.classfile.Code obj)
implements the visitor to reset the stack, and method call maps for new method Note: that when collecting branch targets, it's unfortunately not good enough to just collect the handler pcs, as javac plays fast and loose, and will sometimes jam code below the end pc and before the first handler pc, which gets executed. So we need to clear our maps if we go past the end pc as well.- Specified by:
visitCode
in interfaceorg.apache.bcel.classfile.Visitor
- Overrides:
visitCode
in classedu.umd.cs.findbugs.visitclass.PreorderVisitor
- Parameters:
obj
- the context object of the currently parsed code block
-
sawOpcode
public void sawOpcode(int seen)
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.- Overrides:
sawOpcode
in classedu.umd.cs.findbugs.visitclass.DismantleBytecode
- Parameters:
seen
- the opcode of the currently parsed instruction
-
clearFieldMethods
private void clearFieldMethods(java.lang.String fieldSource)
-
getBugPriority
private static int getBugPriority(java.lang.String methodName, MethodInfo mi)
returns the bug priority based on metrics about the method- Parameters:
methodName
- TODOmi
- metrics about the method- Returns:
- the bug priority
-
isRiskyName
private static boolean isRiskyName(java.lang.String className, java.lang.String methodName)
returns true if the class or method name contains a pattern that is considered likely to be this modifying- Parameters:
className
- the class name to checkmethodName
- the method name to check- Returns:
- whether the method sounds like it modifies this
-
getLineNumber
private int getLineNumber(int pc)
returns the source line number for the pc, or just the pc if the line number table doesn't exist- Parameters:
pc
- current pc- Returns:
- the line number
-
-