Search in sources :

Example 1 with BasicBlock

use of edu.umd.cs.findbugs.ba.BasicBlock in project fb-contrib by mebigfatguy.

the class CyclomaticComplexity method visitMethod.

/**
 * overrides the visitor to navigate the basic block list to count branches
 *
 * @param obj
 *            the method of the currently parsed method
 */
@Override
public void visitMethod(final Method obj) {
    try {
        if (obj.isSynthetic()) {
            return;
        }
        Code code = obj.getCode();
        if (code == null) {
            return;
        }
        // bother
        if (code.getCode().length < (2 * reportLimit)) {
            return;
        }
        BitSet exceptionNodeTargets = new BitSet();
        CFG cfg = classContext.getCFG(obj);
        int branches = 0;
        Iterator<BasicBlock> bbi = cfg.blockIterator();
        while (bbi.hasNext()) {
            BasicBlock bb = bbi.next();
            Iterator<Edge> iei = cfg.outgoingEdgeIterator(bb);
            int lastSwitchTargetBlockLabel = Integer.MIN_VALUE;
            while (iei.hasNext()) {
                Edge e = iei.next();
                int edgeType = e.getType();
                if ((edgeType != EdgeTypes.FALL_THROUGH_EDGE) && (edgeType != EdgeTypes.RETURN_EDGE) && (edgeType != EdgeTypes.UNKNOWN_EDGE)) {
                    if ((edgeType == EdgeTypes.UNHANDLED_EXCEPTION_EDGE) || (edgeType == EdgeTypes.HANDLED_EXCEPTION_EDGE)) {
                        int nodeTarget = e.getTarget().getLabel();
                        if (!exceptionNodeTargets.get(nodeTarget)) {
                            exceptionNodeTargets.set(nodeTarget);
                            branches++;
                        }
                    } else if ((edgeType == EdgeTypes.SWITCH_EDGE) || (edgeType == EdgeTypes.SWITCH_DEFAULT_EDGE)) {
                        int nodeTarget = e.getTarget().getLabel();
                        if (nodeTarget != lastSwitchTargetBlockLabel) {
                            branches++;
                        }
                        lastSwitchTargetBlockLabel = nodeTarget;
                    } else {
                        branches++;
                    }
                }
            }
        }
        if (branches > reportLimit) {
            int priority = (branches > (reportLimit * 2) ? HIGH_PRIORITY : NORMAL_PRIORITY);
            BugInstance bug = new BugInstance(this, BugType.CC_CYCLOMATIC_COMPLEXITY.name(), priority).addClass(this).addMethod(this).addSourceLine(classContext, this, 0).addInt(branches);
            bugReporter.reportBug(bug);
        }
    } catch (CFGBuilderException cbe) {
        bugReporter.logError("Failure examining basic blocks for method " + classContext.getJavaClass().getClassName() + '.' + obj.getName() + " in Cyclomatic Complexity detector", cbe);
    }
}
Also used : CFG(edu.umd.cs.findbugs.ba.CFG) CFGBuilderException(edu.umd.cs.findbugs.ba.CFGBuilderException) BitSet(java.util.BitSet) BasicBlock(edu.umd.cs.findbugs.ba.BasicBlock) BugInstance(edu.umd.cs.findbugs.BugInstance) Code(org.apache.bcel.classfile.Code) Edge(edu.umd.cs.findbugs.ba.Edge)

Example 2 with BasicBlock

use of edu.umd.cs.findbugs.ba.BasicBlock in project fb-contrib by mebigfatguy.

the class FieldCouldBeLocal method visitMethod.

/**
 * overrides the visitor to navigate basic blocks looking for all first usages of fields, removing those that are read from first.
 *
 * @param obj
 *            the context object of the currently parsed method
 */
@Override
public void visitMethod(Method obj) {
    if (localizableFields.isEmpty()) {
        return;
    }
    try {
        cfg = clsContext.getCFG(obj);
        cpg = cfg.getMethodGen().getConstantPool();
        BasicBlock bb = cfg.getEntry();
        Set<String> uncheckedFields = new HashSet<>(localizableFields.keySet());
        visitedBlocks.clear();
        checkBlock(bb, uncheckedFields);
    } catch (CFGBuilderException cbe) {
        localizableFields.clear();
    } finally {
        cfg = null;
        cpg = null;
    }
}
Also used : CFGBuilderException(edu.umd.cs.findbugs.ba.CFGBuilderException) BasicBlock(edu.umd.cs.findbugs.ba.BasicBlock) ToString(com.mebigfatguy.fbcontrib.utils.ToString) HashSet(java.util.HashSet)

Example 3 with BasicBlock

use of edu.umd.cs.findbugs.ba.BasicBlock in project fb-contrib by mebigfatguy.

the class FieldCouldBeLocal method checkBlock.

/**
 * looks in this basic block for the first access to the fields in uncheckedFields. Once found the item is removed from uncheckedFields, and removed from
 * localizableFields if the access is a GETFIELD. If any unchecked fields remain, this method is recursively called on all outgoing edges of this basic
 * block.
 *
 * @param startBB
 *            this basic block
 * @param uncheckedFields
 *            the list of fields to look for
 */
private void checkBlock(BasicBlock startBB, Set<String> uncheckedFields) {
    Deque<BlockState> toBeProcessed = new ArrayDeque<>();
    toBeProcessed.addLast(new BlockState(startBB, uncheckedFields));
    visitedBlocks.set(startBB.getLabel());
    while (!toBeProcessed.isEmpty()) {
        if (localizableFields.isEmpty()) {
            return;
        }
        BlockState bState = toBeProcessed.removeFirst();
        BasicBlock bb = bState.getBasicBlock();
        InstructionIterator ii = bb.instructionIterator();
        while ((bState.getUncheckedFieldSize() > 0) && ii.hasNext()) {
            InstructionHandle ih = ii.next();
            Instruction ins = ih.getInstruction();
            if (ins instanceof FieldInstruction) {
                FieldInstruction fi = (FieldInstruction) ins;
                if (fi.getReferenceType(cpg).getSignature().equals(clsSig)) {
                    String fieldName = fi.getFieldName(cpg);
                    FieldInfo finfo = localizableFields.get(fieldName);
                    if ((finfo != null) && localizableFields.get(fieldName).hasAnnotation()) {
                        localizableFields.remove(fieldName);
                    } else {
                        boolean justRemoved = bState.removeUncheckedField(fieldName);
                        if (ins instanceof GETFIELD) {
                            if (justRemoved) {
                                localizableFields.remove(fieldName);
                                if (localizableFields.isEmpty()) {
                                    return;
                                }
                            }
                        } else if (finfo != null) {
                            finfo.setSrcLineAnnotation(SourceLineAnnotation.fromVisitedInstruction(clsContext, this, ih.getPosition()));
                        }
                    }
                }
            } else if (ins instanceof INVOKESPECIAL) {
                INVOKESPECIAL is = (INVOKESPECIAL) ins;
                ReferenceType rt = is.getReferenceType(cpg);
                if (Values.CONSTRUCTOR.equals(is.getMethodName(cpg))) {
                    if ((rt instanceof ObjectType) && ((ObjectType) rt).getClassName().startsWith(clsContext.getJavaClass().getClassName() + Values.INNER_CLASS_SEPARATOR)) {
                        localizableFields.clear();
                    }
                } else {
                    localizableFields.clear();
                }
            } else if (ins instanceof INVOKEVIRTUAL) {
                INVOKEVIRTUAL is = (INVOKEVIRTUAL) ins;
                ReferenceType rt = is.getReferenceType(cpg);
                if ((rt instanceof ObjectType) && ((ObjectType) rt).getClassName().equals(clsName)) {
                    String methodDesc = is.getName(cpg) + is.getSignature(cpg);
                    Set<String> fields = methodFieldModifiers.get(methodDesc);
                    if (fields != null) {
                        localizableFields.keySet().removeAll(fields);
                    }
                }
            }
        }
        if (bState.getUncheckedFieldSize() > 0) {
            Iterator<Edge> oei = cfg.outgoingEdgeIterator(bb);
            while (oei.hasNext()) {
                Edge e = oei.next();
                BasicBlock cb = e.getTarget();
                int label = cb.getLabel();
                if (!visitedBlocks.get(label)) {
                    toBeProcessed.addLast(new BlockState(cb, bState));
                    visitedBlocks.set(label);
                }
            }
        }
    }
}
Also used : BasicBlock(edu.umd.cs.findbugs.ba.BasicBlock) ToString(com.mebigfatguy.fbcontrib.utils.ToString) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) INVOKESPECIAL(org.apache.bcel.generic.INVOKESPECIAL) ArrayDeque(java.util.ArrayDeque) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ReferenceType(org.apache.bcel.generic.ReferenceType) InstructionIterator(edu.umd.cs.findbugs.ba.BasicBlock.InstructionIterator) GETFIELD(org.apache.bcel.generic.GETFIELD) ObjectType(org.apache.bcel.generic.ObjectType) FieldInstruction(org.apache.bcel.generic.FieldInstruction) Edge(edu.umd.cs.findbugs.ba.Edge) INVOKEVIRTUAL(org.apache.bcel.generic.INVOKEVIRTUAL)

Aggregations

BasicBlock (edu.umd.cs.findbugs.ba.BasicBlock)3 ToString (com.mebigfatguy.fbcontrib.utils.ToString)2 CFGBuilderException (edu.umd.cs.findbugs.ba.CFGBuilderException)2 Edge (edu.umd.cs.findbugs.ba.Edge)2 BugInstance (edu.umd.cs.findbugs.BugInstance)1 InstructionIterator (edu.umd.cs.findbugs.ba.BasicBlock.InstructionIterator)1 CFG (edu.umd.cs.findbugs.ba.CFG)1 ArrayDeque (java.util.ArrayDeque)1 BitSet (java.util.BitSet)1 HashSet (java.util.HashSet)1 Code (org.apache.bcel.classfile.Code)1 FieldInstruction (org.apache.bcel.generic.FieldInstruction)1 GETFIELD (org.apache.bcel.generic.GETFIELD)1 INVOKESPECIAL (org.apache.bcel.generic.INVOKESPECIAL)1 INVOKEVIRTUAL (org.apache.bcel.generic.INVOKEVIRTUAL)1 Instruction (org.apache.bcel.generic.Instruction)1 InstructionHandle (org.apache.bcel.generic.InstructionHandle)1 ObjectType (org.apache.bcel.generic.ObjectType)1 ReferenceType (org.apache.bcel.generic.ReferenceType)1