Search in sources :

Example 11 with QMethod

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;
}
Also used : QMethod(com.mebigfatguy.fbcontrib.utils.QMethod) HashMap(java.util.HashMap) Method(org.apache.bcel.classfile.Method) QMethod(com.mebigfatguy.fbcontrib.utils.QMethod) Code(org.apache.bcel.classfile.Code)

Example 12 with QMethod

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);
        }
    }
}
Also used : QMethod(com.mebigfatguy.fbcontrib.utils.QMethod) OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) ImmutabilityType(com.mebigfatguy.fbcontrib.collect.ImmutabilityType) StopOpcodeParsingException(com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException) BugInstance(edu.umd.cs.findbugs.BugInstance) MethodInfo(com.mebigfatguy.fbcontrib.collect.MethodInfo)

Example 13 with QMethod

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();
}
Also used : QMethod(com.mebigfatguy.fbcontrib.utils.QMethod) AnnotationEntry(org.apache.bcel.classfile.AnnotationEntry) Set(java.util.Set) UnmodifiableSet(com.mebigfatguy.fbcontrib.utils.UnmodifiableSet) HashSet(java.util.HashSet) HashMap(java.util.HashMap) Map(java.util.Map)

Example 14 with QMethod

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);
    }
}
Also used : QMethod(com.mebigfatguy.fbcontrib.utils.QMethod) OpcodeStack(edu.umd.cs.findbugs.OpcodeStack)

Aggregations

QMethod (com.mebigfatguy.fbcontrib.utils.QMethod)14 BugInstance (edu.umd.cs.findbugs.BugInstance)7 OpcodeStack (edu.umd.cs.findbugs.OpcodeStack)6 ToString (com.mebigfatguy.fbcontrib.utils.ToString)5 HashMap (java.util.HashMap)5 Map (java.util.Map)4 JavaClass (org.apache.bcel.classfile.JavaClass)4 FQMethod (com.mebigfatguy.fbcontrib.utils.FQMethod)2 FieldAnnotation (edu.umd.cs.findbugs.FieldAnnotation)2 SourceLineAnnotation (edu.umd.cs.findbugs.SourceLineAnnotation)2 XMethod (edu.umd.cs.findbugs.ba.XMethod)2 AbstractMap (java.util.AbstractMap)2 HashSet (java.util.HashSet)2 Method (org.apache.bcel.classfile.Method)2 ImmutabilityType (com.mebigfatguy.fbcontrib.collect.ImmutabilityType)1 MethodInfo (com.mebigfatguy.fbcontrib.collect.MethodInfo)1 StopOpcodeParsingException (com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException)1 UnmodifiableSet (com.mebigfatguy.fbcontrib.utils.UnmodifiableSet)1 XField (edu.umd.cs.findbugs.ba.XField)1 FieldDescriptor (edu.umd.cs.findbugs.classfile.FieldDescriptor)1