private static void annotateBytecode()

in jar-infer/jar-infer-lib/src/main/java/com/uber/nullaway/jarinfer/BytecodeAnnotator.java [146:190]


  private static void annotateBytecode(
      InputStream is,
      OutputStream os,
      MethodParamAnnotations nonnullParams,
      MethodReturnAnnotations nullableReturns,
      String nullableDesc,
      String nonnullDesc)
      throws IOException {
    ClassReader cr = new ClassReader(is);
    ClassWriter cw = new ClassWriter(0);
    ClassNode cn = new ClassNode(Opcodes.ASM7);
    cr.accept(cn, 0);

    String className = cn.name.replace('/', '.');
    List<MethodNode> methods = cn.methods;
    for (MethodNode method : methods) {
      // Skip methods that already have nullability annotations anywhere in their signature
      if (hasNullnessAnnotations(method)) {
        continue;
      }
      boolean visible = annotationsShouldBeVisible(nullableDesc);
      String methodSignature = className + "." + method.name + method.desc;
      if (nullableReturns.contains(methodSignature)) {
        // Add a @Nullable annotation on this method to indicate that the method can return null.
        method.visitAnnotation(nullableDesc, visible);
        LOG(debug, "DEBUG", "Added nullable return annotation for " + methodSignature);
      }
      Set<Integer> params = nonnullParams.get(methodSignature);
      if (params != null) {
        boolean isStatic = (method.access & Opcodes.ACC_STATIC) != 0;
        for (Integer param : params) {
          int paramNum = isStatic ? param : param - 1;
          // Add a @Nonnull annotation on this parameter.
          method.visitParameterAnnotation(paramNum, nonnullDesc, visible);
          LOG(
              debug,
              "DEBUG",
              "Added nonnull parameter annotation for #" + param + " in " + methodSignature);
        }
      }
    }

    cn.accept(cw);
    os.write(cw.toByteArray());
  }