use of com.mebigfatguy.fbcontrib.collect.MethodInfo in project fb-contrib by mebigfatguy.
the class OverlyPermissiveMethod method visitCode.
@Override
public void visitCode(Code obj) {
Method m = getMethod();
String methodName = m.getName();
String sig = m.getSignature();
if (isAssumedPublic(methodName)) {
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(cls.getClassName(), methodName, sig);
mi.addCallingAccess(Const.ACC_PUBLIC);
} else {
if (!hasRuntimeAnnotations(m) && !isGetterSetter(methodName, sig)) {
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(cls.getClassName(), methodName, sig);
mi.addCallingAccess(Const.ACC_PUBLIC);
}
stack.resetForMethodEntry(this);
super.visitCode(obj);
}
}
use of com.mebigfatguy.fbcontrib.collect.MethodInfo in project fb-contrib by mebigfatguy.
the class OverlyPermissiveMethod method report.
/**
* after collecting all method calls, build a report of all methods that have been called, but in a way that is less permissive then is defined.
*/
@Override
public void report() {
for (Map.Entry<FQMethod, MethodInfo> entry : Statistics.getStatistics()) {
MethodInfo mi = entry.getValue();
int declaredAccess = mi.getDeclaredAccess();
if ((declaredAccess & Const.ACC_PRIVATE) != 0) {
continue;
}
if (mi.wasCalledPublicly() || !mi.wasCalled()) {
continue;
}
FQMethod key = entry.getKey();
String methodName = key.getMethodName();
if (isGetterSetter(methodName, key.getSignature())) {
continue;
}
if (isOverlyPermissive(declaredAccess) && !isConstrainedByInterface(key)) {
try {
String clsName = key.getClassName();
if (!isDerived(Repository.lookupClass(clsName), key)) {
BugInstance bi = new BugInstance(this, BugType.OPM_OVERLY_PERMISSIVE_METHOD.name(), LOW_PRIORITY).addClass(clsName).addMethod(clsName, key.getMethodName(), key.getSignature(), (declaredAccess & Const.ACC_STATIC) != 0);
String descr = String.format("- Method declared %s but could be declared %s", getDeclaredAccessValue(declaredAccess), getRequiredAccessValue(mi));
bi.addString(descr);
bugReporter.reportBug(bi);
}
} catch (ClassNotFoundException cnfe) {
bugReporter.reportMissingClass(cnfe);
}
}
}
}
use of com.mebigfatguy.fbcontrib.collect.MethodInfo in project fb-contrib by mebigfatguy.
the class AnnotationIssues method isMethodNullable.
public static boolean isMethodNullable(@SlashedClassName String className, String methodName, String methodSignature) {
char returnTypeChar = methodSignature.charAt(methodSignature.indexOf(')') + 1);
if ((returnTypeChar != 'L') && (returnTypeChar != '[')) {
return false;
}
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(className, methodName, methodSignature);
return ((mi != null) && mi.getCanReturnNull());
// can we check if it has @Nullable on it? hmm need to convert to Method
}
use of com.mebigfatguy.fbcontrib.collect.MethodInfo in project fb-contrib by mebigfatguy.
the class OverlyPermissiveMethod method sawOpcode.
@Override
public void sawOpcode(int seen) {
try {
stack.precomputation(this);
switch(seen) {
case Const.INVOKEVIRTUAL:
case Const.INVOKEINTERFACE:
case Const.INVOKESTATIC:
case Const.INVOKESPECIAL:
{
String calledClass = getClassConstantOperand();
String sig = getSigConstantOperand();
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(calledClass, getNameConstantOperand(), sig);
if (mi != null) {
if (seen == Const.INVOKEINTERFACE) {
mi.addCallingAccess(Const.ACC_PUBLIC);
} else {
String calledPackage;
int slashPos = calledClass.lastIndexOf('/');
if (slashPos >= 0) {
calledPackage = calledClass.substring(0, slashPos);
} else {
calledPackage = "";
}
boolean sameClass = calledClass.equals(callingClass);
boolean samePackage = calledPackage.equals(callingPackage);
if (sameClass) {
mi.addCallingAccess(Const.ACC_PRIVATE);
} else if (samePackage) {
mi.addCallingAccess(0);
} else {
if (seen == Const.INVOKESTATIC) {
mi.addCallingAccess(Const.ACC_PUBLIC);
} else if (isCallingOnThis(sig)) {
mi.addCallingAccess(Const.ACC_PROTECTED);
} else {
mi.addCallingAccess(Const.ACC_PUBLIC);
}
}
}
}
}
break;
case Const.INVOKEDYNAMIC:
ConstantInvokeDynamic id = (ConstantInvokeDynamic) getConstantRefOperand();
BootstrapMethod bm = getBootstrapMethod(id.getBootstrapMethodAttrIndex());
if (bm != null) {
ConstantPool pool = getConstantPool();
ConstantMethodHandle mh = getFirstMethodHandle(pool, bm);
if (mh != null) {
ConstantCP ref = (ConstantCP) pool.getConstant(mh.getReferenceIndex());
ConstantClass cc = (ConstantClass) pool.getConstant(ref.getClassIndex());
String clz = ((ConstantUtf8) pool.getConstant(cc.getNameIndex())).getBytes();
ConstantNameAndType nameAndType = (ConstantNameAndType) pool.getConstant(ref.getNameAndTypeIndex());
String sig = ((ConstantUtf8) pool.getConstant(nameAndType.getSignatureIndex())).getBytes();
String name = ((ConstantUtf8) pool.getConstant(nameAndType.getNameIndex())).getBytes();
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(clz, name, sig);
mi.addCallingAccess(Const.ACC_PUBLIC);
}
}
break;
default:
break;
}
} finally {
stack.sawOpcode(this, seen);
}
}
use of com.mebigfatguy.fbcontrib.collect.MethodInfo in project fb-contrib by mebigfatguy.
the class SuboptimalExpressionOrder method sawOpcode.
/**
* overrides the visitor to look for chains of expressions joined by 'and' that have method calls before simple local variable conditions
*
* @param seen
* the currently parse opcode
*/
@Override
public void sawOpcode(int seen) {
Integer userValue = null;
if ((conditionalTarget != -1) && (getPC() >= conditionalTarget)) {
conditionalTarget = -1;
sawMethodWeight = 0;
}
try {
switch(seen) {
case Const.INVOKESPECIAL:
case Const.INVOKESTATIC:
case Const.INVOKEINTERFACE:
case Const.INVOKEVIRTUAL:
String signature = getSigConstantOperand();
if (Values.SIG_VOID.equals(SignatureUtils.getReturnSignature(signature))) {
sawMethodWeight = 0;
return;
}
String clsName = getClassConstantOperand();
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(clsName, getNameConstantOperand(), signature);
if ((mi == null) || (mi.getNumBytes() == 0)) {
userValue = Values.ONE;
} else {
userValue = Integer.valueOf(mi.getNumBytes());
}
break;
case Const.LCMP:
case Const.FCMPL:
case Const.FCMPG:
case Const.DCMPL:
case Const.DCMPG:
case Const.IAND:
case Const.IOR:
case Const.IXOR:
if (stack.getStackDepth() >= 2) {
for (int i = 0; i <= 1; i++) {
OpcodeStack.Item itm = stack.getStackItem(i);
userValue = (Integer) itm.getUserValue();
if (userValue != null) {
break;
}
}
} else {
sawMethodWeight = 0;
}
break;
case Const.IF_ICMPEQ:
case Const.IF_ICMPNE:
case Const.IF_ICMPLT:
case Const.IF_ICMPGE:
case Const.IF_ICMPGT:
case Const.IF_ICMPLE:
case Const.IF_ACMPEQ:
case Const.IF_ACMPNE:
if (conditionalTarget < 0) {
conditionalTarget = getBranchTarget();
} else if (conditionalTarget != getBranchTarget()) {
conditionalTarget = -1;
sawMethodWeight = 0;
return;
}
if (stack.getStackDepth() >= 2) {
int expWeight = 0;
for (int i = 0; i <= 1; i++) {
OpcodeStack.Item itm = stack.getStackItem(i);
Integer uv = (Integer) itm.getUserValue();
if (uv != null) {
expWeight = Math.max(uv.intValue(), expWeight);
}
}
if ((expWeight == 0) && (sawMethodWeight > 0)) {
bugReporter.reportBug(new BugInstance(this, BugType.SEO_SUBOPTIMAL_EXPRESSION_ORDER.name(), sawMethodWeight >= NORMAL_WEIGHT_LIMIT ? NORMAL_PRIORITY : LOW_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
sawMethodWeight = 0;
conditionalTarget = Integer.MAX_VALUE;
} else {
sawMethodWeight = Math.max(sawMethodWeight, expWeight);
}
}
break;
case Const.IFEQ:
case Const.IFNE:
case Const.IFLT:
case Const.IFGE:
case Const.IFGT:
case Const.IFLE:
case Const.IFNULL:
case Const.IFNONNULL:
if (conditionalTarget < 0) {
conditionalTarget = getBranchTarget();
} else if (conditionalTarget != getBranchTarget()) {
conditionalTarget = -1;
sawMethodWeight = 0;
return;
}
if (stack.getStackDepth() >= 1) {
OpcodeStack.Item itm = stack.getStackItem(0);
Integer uv = (Integer) itm.getUserValue();
if (uv == null) {
if (sawMethodWeight > 0) {
bugReporter.reportBug(new BugInstance(this, BugType.SEO_SUBOPTIMAL_EXPRESSION_ORDER.name(), sawMethodWeight >= NORMAL_WEIGHT_LIMIT ? NORMAL_PRIORITY : LOW_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
sawMethodWeight = 0;
conditionalTarget = Integer.MAX_VALUE;
}
} else {
sawMethodWeight = Math.max(sawMethodWeight, uv.intValue());
}
}
break;
case Const.ISTORE:
case Const.LSTORE:
case Const.FSTORE:
case Const.DSTORE:
case Const.ASTORE:
case Const.ISTORE_0:
case Const.ISTORE_1:
case Const.ISTORE_2:
case Const.ISTORE_3:
case Const.LSTORE_0:
case Const.LSTORE_1:
case Const.LSTORE_2:
case Const.LSTORE_3:
case Const.FSTORE_0:
case Const.FSTORE_1:
case Const.FSTORE_2:
case Const.FSTORE_3:
case Const.DSTORE_0:
case Const.DSTORE_1:
case Const.DSTORE_2:
case Const.DSTORE_3:
case Const.ASTORE_0:
case Const.ASTORE_1:
case Const.ASTORE_2:
case Const.ASTORE_3:
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
itm.setUserValue(null);
}
sawMethodWeight = 0;
conditionalTarget = -1;
break;
case Const.ATHROW:
case Const.POP:
case Const.POP2:
case Const.GOTO:
case Const.GOTO_W:
case Const.PUTFIELD:
case Const.PUTSTATIC:
case Const.IINC:
case Const.INSTANCEOF:
case Const.RETURN:
case Const.ARETURN:
case Const.IRETURN:
case Const.LRETURN:
case Const.FRETURN:
case Const.DRETURN:
sawMethodWeight = 0;
conditionalTarget = -1;
break;
case Const.ARRAYLENGTH:
case Const.CHECKCAST:
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
userValue = (Integer) itm.getUserValue();
}
break;
case Const.GETFIELD:
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
if (itm.getReturnValueOf() != null) {
sawMethodWeight = 0;
conditionalTarget = -1;
}
}
break;
}
} finally {
stack.sawOpcode(this, seen);
if ((userValue != null) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item itm = stack.getStackItem(0);
itm.setUserValue(userValue);
}
}
}
Aggregations