package edu.umd.cs.findbugs.detect; import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.Method; import edu.umd.cs.findbugs.BugAccumulator; import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.BytecodeScanningDetector; import edu.umd.cs.findbugs.SourceLineAnnotation; import edu.umd.cs.findbugs.SystemProperties; import edu.umd.cs.findbugs.util.ClassName; public class IDivResultCastToDouble extends BytecodeScanningDetector { private static final boolean DEBUG = SystemProperties.getBoolean("idcd.debug"); private final BugReporter bugReporter; private final BugAccumulator bugAccumulator; private int prevOpCode; public IDivResultCastToDouble(BugReporter bugReporter) { this.bugReporter = bugReporter; this.bugAccumulator = new BugAccumulator(bugReporter); } @Override public void visit(Method obj) { if (DEBUG) System.out.println("Visiting " + obj); } @Override public void visit(Code obj) { super.visit(obj); bugAccumulator.reportAccumulatedBugs(); } SourceLineAnnotation pendingIdivCastToDivBugLocation = null; @Override public void sawOpcode(int seen) { if (DEBUG) System.out.println("Saw opcode " + OPCODE_NAMES[seen] + " " + pendingIdivCastToDivBugLocation); if ((prevOpCode == I2D || prevOpCode == L2D) && seen == INVOKESTATIC && ClassName.isMathClass(getClassConstantOperand()) && getNameConstantOperand().equals("ceil")) { bugAccumulator .accumulateBug(new BugInstance(this, "ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL", HIGH_PRIORITY) .addClassAndMethod(this), this); pendingIdivCastToDivBugLocation = null; } else if ((prevOpCode == I2F || prevOpCode == L2F) && seen == INVOKESTATIC && ClassName.isMathClass(getClassConstantOperand()) && getNameConstantOperand().equals("round")) { bugAccumulator.accumulateBug( new BugInstance(this, "ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND", NORMAL_PRIORITY).addClassAndMethod(this), this); pendingIdivCastToDivBugLocation = null; } else if (pendingIdivCastToDivBugLocation != null) { bugAccumulator.accumulateBug( new BugInstance(this, "ICAST_IDIV_CAST_TO_DOUBLE", NORMAL_PRIORITY).addClassAndMethod(this), pendingIdivCastToDivBugLocation); pendingIdivCastToDivBugLocation = null; } if (prevOpCode == IDIV && (seen == I2D || seen == I2F) || prevOpCode == LDIV && (seen == L2D || seen == L2F)) pendingIdivCastToDivBugLocation = SourceLineAnnotation.fromVisitedInstruction(this); prevOpCode = seen; } }