MethodVisitor (int access, final String name, final String desc, String signature, String[] exceptions) { final MethodInfo info = myMethodData.myMethodInfos.get(MethodData.key(name, desc)); if ((access & Opcodes.ACC_BRIDGE) != 0 || info == null) { return new FailSafeMethodVisitor(Opcodes.API_VERSION, super.visitMethod(access, name, desc, signature, exceptions)); } final boolean isStatic = isStatic(access); final Type[] args = Type.getArgumentTypes(desc); final NotNullInstructionTracker instrTracker = new NotNullInstructionTracker(cv.visitMethod(access, name, desc, signature, exceptions)); return new FailSafeMethodVisitor(Opcodes.API_VERSION, instrTracker) { private Label myStartGeneratedCodeLabel; @Override public void visitCode() { for (Iterator<NotNullState> iterator = info.paramNullability.values().iterator(); iterator.hasNext(); ) { if (!iterator.next().isNotNull()) { iterator.remove(); } } if (info.paramNullability.size() > 0) { myStartGeneratedCodeLabel = new Label(); mv.visitLabel(myStartGeneratedCodeLabel); } for (Map.Entry<Integer, NotNullState> entry : info.paramNullability.entrySet()) { Integer param = entry.getKey(); int var = isStatic ? 0 : 1; for (int i = 0; i < param; ++i) { var += args[i].getSize(); } mv.visitVarInsn(ALOAD, var); Label end = new Label(); mv.visitJumpInsn(IFNONNULL, end); NotNullState state = entry.getValue(); String paramName = myMethodData.lookupParamName(name, desc, param); String descrPattern = state.getNullParamMessage(paramName); String[] args = state.message != null ? EMPTY_STRING_ARRAY : new String[]{paramName != null ? paramName : String.valueOf(param - info.paramAnnotationOffset), myMethodData.myClassName, name}; reportError(state.exceptionType, end, descrPattern, args); } } @Override public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { boolean isParameterOrThisRef = isStatic ? index < args.length : index <= args.length; Label label = (isParameterOrThisRef && myStartGeneratedCodeLabel != null) ? myStartGeneratedCodeLabel : start; mv.visitLocalVariable(name, desc, signature, label, end, index); } @Override public void visitInsn(int opcode) { if (opcode == ARETURN && instrTracker.canBeNull() && info.nullability.isNotNull()) { mv.visitInsn(DUP); Label skipLabel = new Label(); mv.visitJumpInsn(IFNONNULL, skipLabel); String descrPattern = info.nullability.getNullResultMessage(); String[] args = info.nullability.message != null ? EMPTY_STRING_ARRAY : new String[]{myMethodData.myClassName, name}; reportError(info.nullability.exceptionType, skipLabel, descrPattern, args); } mv.visitInsn(opcode); } private void reportError(String exceptionClass, Label end, String descrPattern, String[] args) { myAuxGenerator.reportError(mv, myMethodData.myClassName, exceptionClass, descrPattern, args); mv.visitLabel(end); myIsModification = true; processPostponedErrors(); } @Override public void visitMaxs(int maxStack, int maxLocals) { try { super.visitMaxs(maxStack, maxLocals); } catch (Throwable e) { registerError(name, "visitMaxs", e); } } }; }