1 19 package edu.umd.cs.findbugs.detect; 20 21 import edu.umd.cs.findbugs.*; 22 import edu.umd.cs.findbugs.ba.*; 23 import java.util.BitSet ; 24 import org.apache.bcel.Constants; 25 import org.apache.bcel.classfile.*; 26 27 34 public class MethodReturnCheck extends BytecodeScanningDetector { 35 private static final boolean DEBUG = SystemProperties.getBoolean("mrc.debug"); 36 37 private static final int SCAN = 0; 38 39 private static final int SAW_INVOKE = 1; 40 41 private static final BitSet INVOKE_OPCODE_SET = new BitSet (); 42 static { 43 INVOKE_OPCODE_SET.set(Constants.INVOKEINTERFACE); 44 INVOKE_OPCODE_SET.set(Constants.INVOKESPECIAL); 45 INVOKE_OPCODE_SET.set(Constants.INVOKESTATIC); 46 INVOKE_OPCODE_SET.set(Constants.INVOKEVIRTUAL); 47 } 48 49 boolean previousOpcodeWasNEW; 50 51 private BugReporter bugReporter; 52 53 private ClassContext classContext; 54 55 private CheckReturnAnnotationDatabase checkReturnAnnotationDatabase; 56 57 private Method method; 58 59 private XMethod callSeen; 60 61 private int state; 62 63 private int callPC; 64 65 private String className, methodName, signature; 66 67 public MethodReturnCheck(BugReporter bugReporter) { 68 this.bugReporter = bugReporter; 69 } 70 71 @Override 72 public void visitClassContext(ClassContext classContext) { 73 this.classContext = classContext; 74 checkReturnAnnotationDatabase = AnalysisContext 75 .currentAnalysisContext().getCheckReturnAnnotationDatabase(); 76 super.visitClassContext(classContext); 77 this.classContext = null; 78 } 79 80 @Override 81 public void visit(Method method) { 82 this.method = method; 83 } 84 85 @Override 86 public void visitCode(Code code) { 87 90 if (DEBUG) 91 System.out.println("Visiting " + method); 92 super.visitCode(code); 93 } 94 95 @Override 96 public void sawOpcode(int seen) { 97 98 if (DEBUG) 99 System.out.println(state + " " + OPCODE_NAMES[seen]); 100 101 if (state == SAW_INVOKE && isPop(seen)) { 102 CheckReturnValueAnnotation annotation = checkReturnAnnotationDatabase 103 .getResolvedAnnotation(callSeen, false); 104 if (annotation != null 105 && annotation != CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE) { 106 int popPC = getPC(); 107 if (DEBUG) 108 System.out.println("Saw POP @" + popPC); 109 int catchSize = getSizeOfSurroundingTryBlock(popPC); 110 111 int priority = annotation.getPriority(); 112 if (catchSize <= 1) 113 priority += 2; 114 else if (catchSize <= 2) 115 priority += 1; 116 if (!checkReturnAnnotationDatabase.annotationIsDirect(callSeen) 117 && !callSeen.getSignature() 118 .endsWith( 119 callSeen.getClassName().replace('.', 120 '/') 121 + ";")) 122 priority++; 123 BugInstance warning = new BugInstance(this, 124 "RV_RETURN_VALUE_IGNORED", priority).addClassAndMethod( 125 this).addMethod(className, methodName, signature, 126 seen == Constants.INVOKESTATIC).describe( 127 "METHOD_CALLED").addSourceLine(this, callPC); 128 bugReporter.reportBug(warning); 129 } 130 state = SCAN; 131 } else if (INVOKE_OPCODE_SET.get(seen)) { 132 callPC = getPC(); 133 className = getDottedClassConstantOperand(); 134 methodName = getNameConstantOperand(); 135 signature = getSigConstantOperand(); 136 callSeen = XFactory.createXMethod(className, methodName, signature, 137 seen == INVOKESTATIC); 138 state = SAW_INVOKE; 139 if (DEBUG) System.out.println(" invoking " + callSeen); 140 } else 141 state = SCAN; 142 143 if (seen == NEW) { 144 previousOpcodeWasNEW = true; 145 } else { 146 if (seen == INVOKESPECIAL && previousOpcodeWasNEW) { 147 CheckReturnValueAnnotation annotation = checkReturnAnnotationDatabase 148 .getResolvedAnnotation(callSeen, false); 149 if (annotation != null 150 && annotation != CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE) { 151 int priority = annotation.getPriority(); 152 if (!checkReturnAnnotationDatabase 153 .annotationIsDirect(callSeen) 154 && !callSeen.getSignature().endsWith( 155 callSeen.getClassName().replace('.', '/') 156 + ";")) 157 priority++; 158 bugReporter.reportBug(new BugInstance(this, 159 "RV_RETURN_VALUE_IGNORED", priority) 160 .addClassAndMethod(this).addCalledMethod(this).describe( 161 "METHOD_CALLED").addSourceLine(this)); 162 } 163 164 } 165 previousOpcodeWasNEW = false; 166 } 167 168 } 169 170 private boolean isPop(int seen) { 171 return seen == Constants.POP || seen == Constants.POP2; 172 } 173 174 } 175 | Popular Tags |