use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class NonRecycleableTaglibs method getAttributes.
/**
* collect all possible attributes given the name of methods available.
*
* @param cls
* the class to look for setter methods to infer properties
* @return the map of possible attributes/types
*/
private static Map<QMethod, String> getAttributes(JavaClass cls) {
Map<QMethod, String> atts = new HashMap<>();
Method[] methods = cls.getMethods();
for (Method m : methods) {
String name = m.getName();
if (name.startsWith("set") && m.isPublic() && !m.isStatic()) {
String sig = m.getSignature();
List<String> args = SignatureUtils.getParameterSignatures(sig);
if ((args.size() == 1) && Values.SIG_VOID.equals(SignatureUtils.getReturnSignature(sig))) {
String parmSig = args.get(0);
if (validAttrTypes.contains(parmSig)) {
Code code = m.getCode();
if ((code != null) && (code.getCode().length < MAX_ATTRIBUTE_CODE_LENGTH)) {
atts.put(new QMethod(name, sig), parmSig);
}
}
}
}
}
return atts;
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class ModifyingUnmodifiableCollection method sawOpcode.
/**
* overrides the visitor to find method mutations on collections that have previously been determined to have been created as immutable collections
*
* @param seen
* the currently parsed opcode
*/
@Override
public void sawOpcode(int seen) {
ImmutabilityType imType = null;
try {
stack.precomputation(this);
switch(seen) {
case INVOKESTATIC:
case INVOKEINTERFACE:
case INVOKESPECIAL:
case INVOKEVIRTUAL:
{
String className = getClassConstantOperand();
String methodName = getNameConstantOperand();
String signature = getSigConstantOperand();
MethodInfo mi = Statistics.getStatistics().getMethodStatistics(className, methodName, signature);
imType = mi.getImmutabilityType();
if (seen == INVOKEINTERFACE) {
Integer collectionOffset = MODIFYING_METHODS.get(new QMethod(methodName, signature));
if ((collectionOffset != null) && CollectionUtils.isListSetMap(className) && (stack.getStackDepth() > collectionOffset.intValue())) {
OpcodeStack.Item item = stack.getStackItem(collectionOffset.intValue());
ImmutabilityType type = (ImmutabilityType) item.getUserValue();
if ((type == ImmutabilityType.IMMUTABLE) || ((type == ImmutabilityType.POSSIBLY_IMMUTABLE) && (reportedType != ImmutabilityType.POSSIBLY_IMMUTABLE))) {
bugReporter.reportBug(new BugInstance(this, BugType.MUC_MODIFYING_UNMODIFIABLE_COLLECTION.name(), (type == ImmutabilityType.IMMUTABLE) ? HIGH_PRIORITY : NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
if (type == ImmutabilityType.IMMUTABLE) {
throw new StopOpcodeParsingException();
}
reportedType = type;
}
}
}
}
break;
default:
break;
}
} catch (ClassNotFoundException cnfe) {
bugReporter.reportMissingClass(cnfe);
} finally {
stack.sawOpcode(this, seen);
if ((imType != null) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item item = stack.getStackItem(0);
item.setUserValue(imType);
}
}
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class CollectStatistics method performModifyStateClosure.
private void performModifyStateClosure(JavaClass cls) {
boolean foundNewCall = true;
Statistics statistics = Statistics.getStatistics();
String clsName = cls.getClassName();
while (foundNewCall && !selfCallTree.isEmpty()) {
foundNewCall = false;
Iterator<Map.Entry<QMethod, Set<CalledMethod>>> callerIt = selfCallTree.entrySet().iterator();
while (callerIt.hasNext()) {
Map.Entry<QMethod, Set<CalledMethod>> callerEntry = callerIt.next();
QMethod caller = callerEntry.getKey();
MethodInfo callerMi = statistics.getMethodStatistics(clsName, caller.getMethodName(), caller.getSignature());
if (callerMi == null) {
// odd, shouldn't happen
foundNewCall = true;
} else if (callerMi.getModifiesState()) {
foundNewCall = true;
} else {
for (CalledMethod calledMethod : callerEntry.getValue()) {
if (calledMethod.isSuper) {
callerMi.setModifiesState(true);
foundNewCall = true;
break;
}
MethodInfo calleeMi = statistics.getMethodStatistics(clsName, calledMethod.callee.getMethodName(), calledMethod.callee.getSignature());
if (calleeMi == null) {
// a super or sub class probably implements this method so just assume it
// modifies state
callerMi.setModifiesState(true);
foundNewCall = true;
break;
}
if (calleeMi.getModifiesState()) {
callerMi.setModifiesState(true);
foundNewCall = true;
break;
}
}
}
if (foundNewCall) {
callerIt.remove();
}
}
}
selfCallTree.clear();
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class CollectStatistics method sawOpcode.
@Override
public void sawOpcode(int seen) {
try {
switch(seen) {
case Const.INVOKEVIRTUAL:
case Const.INVOKEINTERFACE:
case Const.INVOKESPECIAL:
case Const.INVOKESTATIC:
case Const.INVOKEDYNAMIC:
numMethodCalls++;
if (seen != Const.INVOKESTATIC) {
int numParms = SignatureUtils.getNumParameters(getSigConstantOperand());
if (stack.getStackDepth() > numParms) {
OpcodeStack.Item itm = stack.getStackItem(numParms);
if (itm.getRegisterNumber() == 0) {
Set<CalledMethod> calledMethods;
if (curMethod == null) {
curMethod = new QMethod(getMethodName(), getMethodSig());
calledMethods = new HashSet<>();
selfCallTree.put(curMethod, calledMethods);
} else {
calledMethods = selfCallTree.get(curMethod);
}
calledMethods.add(new CalledMethod(new QMethod(getNameConstantOperand(), getSigConstantOperand()), seen == Const.INVOKESPECIAL));
}
}
}
break;
case Const.PUTSTATIC:
case Const.PUTFIELD:
modifiesState = true;
break;
default:
break;
}
} finally {
stack.sawOpcode(this, seen);
}
}
Aggregations