Package com.mebigfatguy.fbcontrib.detect
Class OverlyConcreteParameter
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.OverlyConcreteParameter
- All Implemented Interfaces:
edu.umd.cs.findbugs.Detector,edu.umd.cs.findbugs.Priorities,org.apache.bcel.classfile.Visitor
public class OverlyConcreteParameter
extends edu.umd.cs.findbugs.BytecodeScanningDetector
looks for parameters that are defined by classes, but only use methods
defined by an implemented interface or super class. Relying on concrete
classes in public signatures causes cohesion, and makes low impact changes
more difficult.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static classan inner helper class that holds basic information about a method -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final edu.umd.cs.findbugs.BugReporterprivate org.apache.bcel.classfile.JavaClassprivate org.apache.bcel.classfile.JavaClass[]private booleanprivate booleanprivate org.apache.bcel.classfile.JavaClassprivate Map<Integer, Map<org.apache.bcel.classfile.JavaClass, List<OverlyConcreteParameter.MethodInfo>>> private intprivate edu.umd.cs.findbugs.OpcodeStackprivate edu.umd.cs.findbugs.OpcodeStack.Itemprivate edu.umd.cs.findbugs.OpcodeStack.Itemprivate intprivate BitSetFields inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode
codeBytes, lineNumberTable, M_BR, M_CP, M_INT, M_PAD, M_R, M_UINTFields inherited from interface edu.umd.cs.findbugs.Priorities
EXP_PRIORITY, HIGH_PRIORITY, IGNORE_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY -
Constructor Summary
ConstructorsConstructorDescriptionOverlyConcreteParameter(edu.umd.cs.findbugs.BugReporter bugReporter) constructs a OCP detector given the reporter to report bugs on -
Method Summary
Modifier and TypeMethodDescriptionprivate booleanbuilds a map of method information for each method of each interface that each parameter implements of this methodprivate static StringgetCardinality(int num) returns a string defining what parameter in the signature a certain one is, for the bug reportprivate static Map<org.apache.bcel.classfile.JavaClass, List<OverlyConcreteParameter.MethodInfo>> getClassDefiners(org.apache.bcel.classfile.JavaClass cls) returns a map of method information for each public method for each interface this class implementsprivate static List<OverlyConcreteParameter.MethodInfo> getPublicMethodInfos(org.apache.bcel.classfile.JavaClass cls) returns a list of method information of all public or protected methods in this classprivate booleanlooks to see if this method has an overloaded method in actuality, this isn't precise and returns true for methods that are named the same, and have same number of args This will miss some cases, but in practicality doesn't matter.private booleanisaConversionClass(org.apache.bcel.classfile.JavaClass conversionCls) returns whether this class is used to convert types of some sort, such that you don't want to suggest reducing the class specified to be more genericprivate booleanreturns whether this exception is handled either in a try/catch or throws clause at this pcprivate booleanmethodHasSyntheticTwin(String methodName, String methodSig) returns whether this method has an equivalent method that is synthetic, which implies this method is constrained by some Generified interface.private static booleanmethodIsSpecial(String methodName, String methodSig) determines whether the method is a baked in special method of the jdkprivate voidremoveInheritedInterfaces(Map<org.apache.bcel.classfile.JavaClass, List<OverlyConcreteParameter.MethodInfo>> definers) private voidremoveParmDefiner(edu.umd.cs.findbugs.OpcodeStack.Item itm) removes a parameter from the definer list, if the item is in fact a parameterprivate voidremoveUselessDefiners(int reg) parses through the interface that 'may' define a parameter defined by reg, and look to see if we can rule it out, because a method is called on the object that can't be satisfied by the interface, if so remove that candidate interface.private voidremoveUselessDefiners(String parmSig, int reg) private voidimplements the post processing steps to report the remaining unremoved parameter definers, ie those, that can be defined more abstractly.voidsawOpcode(int seen) implements the visitor to filter out parameter use where the actual defined type of the method declaration is needed.voidvisitClassContext(edu.umd.cs.findbugs.ba.ClassContext classContext) implements the visitor to collect classes that constrains this class (super classes/interfaces) and to reset the opcode stackvoidvisitCode(org.apache.bcel.classfile.Code obj) implements the visitor to collect information about the parameters of a this methodvoidvisitMethod(org.apache.bcel.classfile.Method obj) implements the visitor to look to see if this method is constrained by a superclass or interface.Methods inherited from class edu.umd.cs.findbugs.BytecodeScanningDetector
getClassContext, report, shouldVisitCodeMethods 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, visitMethods inherited from class edu.umd.cs.findbugs.visitclass.AnnotationVisitor
getAnnotationParameterAsEnum, getAnnotationParameterAsString, getAnnotationParameterAsStringArray, visitAnnotation, visitAnnotation, visitParameterAnnotation, visitParameterAnnotation, visitSyntheticParameterAnnotationMethods 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, getSurroundingCaughtExceptionTypes, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitBootstrapMethods, visitConstantInvokeDynamic, visitConstantMethodHandle, visitConstantMethodType, visitConstantModule, visitConstantPackage, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitMethodParameters, visitParameterAnnotationEntry, visitStackMap, visitStackMapEntryMethods 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, visitSignature, visitSourceFile, visitSynthetic, visitUnknownMethods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface org.apache.bcel.classfile.Visitor
visitConstantDynamic, visitMethodParameter, visitModule, visitModuleExports, visitModuleMainClass, visitModuleOpens, visitModulePackages, visitModuleProvides, visitModuleRequires, visitNestHost, visitNestMembers, visitRecord, visitRecordComponent, visitStackMapType
-
Field Details
-
CONVERSION_ANNOTATIONS
-
CONVERSION_SUPER_CLASSES
-
OVERLY_CONCRETE_INTERFACES
-
IGNORED_INTERFACES
-
bugReporter
private final edu.umd.cs.findbugs.BugReporter bugReporter -
constrainingClasses
private org.apache.bcel.classfile.JavaClass[] constrainingClasses -
parameterDefiners
private Map<Integer,Map<org.apache.bcel.classfile.JavaClass, parameterDefinersList<OverlyConcreteParameter.MethodInfo>>> -
usedParameters
-
objectClass
private org.apache.bcel.classfile.JavaClass objectClass -
cls
private org.apache.bcel.classfile.JavaClass cls -
stack
private edu.umd.cs.findbugs.OpcodeStack stack -
parmCount
private int parmCount -
methodSignatureIsConstrained
private boolean methodSignatureIsConstrained -
methodIsStatic
private boolean methodIsStatic -
ternary1Value
private edu.umd.cs.findbugs.OpcodeStack.Item ternary1Value -
ternary2Value
private edu.umd.cs.findbugs.OpcodeStack.Item ternary2Value -
ternaryTarget
private int ternaryTarget
-
-
Constructor Details
-
OverlyConcreteParameter
public OverlyConcreteParameter(edu.umd.cs.findbugs.BugReporter bugReporter) constructs a OCP detector given the reporter to report bugs on- Parameters:
bugReporter- the sync of bug reports
-
-
Method Details
-
visitClassContext
public void visitClassContext(edu.umd.cs.findbugs.ba.ClassContext classContext) implements the visitor to collect classes that constrains this class (super classes/interfaces) and to reset the opcode stack- Specified by:
visitClassContextin interfaceedu.umd.cs.findbugs.Detector- Overrides:
visitClassContextin classedu.umd.cs.findbugs.BytecodeScanningDetector- Parameters:
classContext- the currently parse class
-
visitMethod
public void visitMethod(org.apache.bcel.classfile.Method obj) implements the visitor to look to see if this method is constrained by a superclass or interface.- Specified by:
visitMethodin interfaceorg.apache.bcel.classfile.Visitor- Overrides:
visitMethodin classedu.umd.cs.findbugs.visitclass.BetterVisitor- Parameters:
obj- the currently parsed method
-
visitCode
public void visitCode(org.apache.bcel.classfile.Code obj) implements the visitor to collect information about the parameters of a this method- Specified by:
visitCodein interfaceorg.apache.bcel.classfile.Visitor- Overrides:
visitCodein classedu.umd.cs.findbugs.visitclass.PreorderVisitor- Parameters:
obj- the currently parsed code block
-
sawOpcode
public void sawOpcode(int seen) implements the visitor to filter out parameter use where the actual defined type of the method declaration is needed. What remains could be more abstractly defined.- Overrides:
sawOpcodein classedu.umd.cs.findbugs.visitclass.DismantleBytecode- Parameters:
seen- the currently parsed opcode
-
removeParmDefiner
private void removeParmDefiner(edu.umd.cs.findbugs.OpcodeStack.Item itm) removes a parameter from the definer list, if the item is in fact a parameter- Parameters:
itm- the possible parameter
-
methodIsSpecial
determines whether the method is a baked in special method of the jdk- Parameters:
methodName- the method name to checkmethodSig- the parameter signature of the method to check- Returns:
- if it is a well known baked in method
-
methodHasSyntheticTwin
returns whether this method has an equivalent method that is synthetic, which implies this method is constrained by some Generified interface. We could compare parameters but that is a bunch of work that probably doesn't make this test any more precise, so just return true if method name and synthetic is found.- Parameters:
methodName- the method name to look for a synthetic twin ofmethodSig- the method signature to lookfor a synthetic twin of- Returns:
- if a synthetic twin is found
-
reportBugs
private void reportBugs()implements the post processing steps to report the remaining unremoved parameter definers, ie those, that can be defined more abstractly. -
hasOverloadedMethod
private boolean hasOverloadedMethod()looks to see if this method has an overloaded method in actuality, this isn't precise and returns true for methods that are named the same, and have same number of args This will miss some cases, but in practicality doesn't matter.- Returns:
- whether there is a method in this class that overrides the given method
-
removeInheritedInterfaces
private void removeInheritedInterfaces(Map<org.apache.bcel.classfile.JavaClass, List<OverlyConcreteParameter.MethodInfo>> definers) throws ClassNotFoundException- Throws:
ClassNotFoundException
-
getCardinality
returns a string defining what parameter in the signature a certain one is, for the bug report- Parameters:
num- the parameter number- Returns:
- a string describing in english the parameter position
-
buildParameterDefiners
builds a map of method information for each method of each interface that each parameter implements of this method- Returns:
- a map by parameter id of all the method signatures that interfaces of that parameter implements
- Throws:
ClassNotFoundException- if the class can't be loaded
-
getClassDefiners
private static Map<org.apache.bcel.classfile.JavaClass,List<OverlyConcreteParameter.MethodInfo>> getClassDefiners(org.apache.bcel.classfile.JavaClass cls) throws ClassNotFoundException returns a map of method information for each public method for each interface this class implements- Parameters:
cls- the class whose interfaces to record- Returns:
- a map of (method name)(method sig) by interface
- Throws:
ClassNotFoundException- if unable to load the class
-
getPublicMethodInfos
private static List<OverlyConcreteParameter.MethodInfo> getPublicMethodInfos(org.apache.bcel.classfile.JavaClass cls) returns a list of method information of all public or protected methods in this class- Parameters:
cls- the class to look for methods- Returns:
- a map of (method name)(method signature)
-
removeUselessDefiners
private void removeUselessDefiners(int reg) parses through the interface that 'may' define a parameter defined by reg, and look to see if we can rule it out, because a method is called on the object that can't be satisfied by the interface, if so remove that candidate interface.- Parameters:
reg- the parameter register number to look at
-
isExceptionHandled
returns whether this exception is handled either in a try/catch or throws clause at this pc- Parameters:
ex- the name of the exception- Returns:
- whether the exception is handled
-
removeUselessDefiners
-
isaConversionClass
private boolean isaConversionClass(org.apache.bcel.classfile.JavaClass conversionCls) returns whether this class is used to convert types of some sort, such that you don't want to suggest reducing the class specified to be more generic- Parameters:
conversionCls- the class to check- Returns:
- whether this class is used in conversions
-