public static void generateNativeMethodStubs(
     AnnotationProcessorEnvironment env,
     TypeMap type_map,
     PrintWriter writer,
     InterfaceDeclaration d,
     boolean generate_error_checks,
     boolean context_specific) {
   for (MethodDeclaration method : d.getMethods()) {
     Alternate alt_annotation = method.getAnnotation(Alternate.class);
     if (alt_annotation != null && !alt_annotation.nativeAlt()) continue;
     generateMethodStub(
         env,
         type_map,
         writer,
         Utils.getQualifiedClassName(d),
         method,
         Mode.NORMAL,
         generate_error_checks,
         context_specific);
     if (Utils.hasMethodBufferObjectParameter(method))
       generateMethodStub(
           env,
           type_map,
           writer,
           Utils.getQualifiedClassName(d),
           method,
           Mode.BUFFEROBJECT,
           generate_error_checks,
           context_specific);
   }
 }
  /** TODO : fix info multi-type methods print. */
  private static void generateMethodJava(
      ProcessingEnvironment env,
      TypeMap type_map,
      PrintWriter writer,
      TypeElement interface_decl,
      ExecutableElement method,
      boolean generate_error_checks,
      boolean context_specific) {
    writer.println();
    if (Utils.isMethodIndirect(generate_error_checks, context_specific, method)) {
      if (method.getAnnotation(GenerateAutos.class) != null) {
        printMethodWithMultiType(
            env,
            type_map,
            writer,
            interface_decl,
            method,
            TypeInfo.getDefaultTypeInfoMap(method),
            Mode.AUTOS,
            generate_error_checks,
            context_specific);
      }
      Collection<Map<VariableElement, TypeInfo>> cross_product =
          TypeInfo.getTypeInfoCrossProduct(type_map, method);
      for (Map<VariableElement, TypeInfo> typeinfos_instance : cross_product) {
        printMethodWithMultiType(
            env,
            type_map,
            writer,
            interface_decl,
            method,
            typeinfos_instance,
            Mode.NORMAL,
            generate_error_checks,
            context_specific);
      }
    }
    if (method.getAnnotation(CachedResult.class) != null
        && !method.getAnnotation(CachedResult.class).isRange()) {
      printMethodWithMultiType(
          env,
          type_map,
          writer,
          interface_decl,
          method,
          TypeInfo.getDefaultTypeInfoMap(method),
          Mode.CACHEDRESULT,
          generate_error_checks,
          context_specific);
    }

    Reuse reuse_annotation = method.getAnnotation(Reuse.class);
    Alternate alt_annotation = method.getAnnotation(Alternate.class);
    if (alt_annotation == null || (alt_annotation.nativeAlt() && !alt_annotation.skipNative())) {
      if (alt_annotation != null
          && method.getSimpleName().toString().equals(alt_annotation.value())) {
        throw new RuntimeException(
            "An alternate function with native code should have a different name than the main function.");
      }

      if (reuse_annotation == null) {
        printJavaNativeStub(
            env, writer, method, Mode.NORMAL, generate_error_checks, context_specific);
      }

      if (Utils.hasMethodBufferObjectParameter(method)) {
        printMethodWithMultiType(
            env,
            type_map,
            writer,
            interface_decl,
            method,
            TypeInfo.getDefaultTypeInfoMap(method),
            Mode.BUFFEROBJECT,
            generate_error_checks,
            context_specific);
        if (reuse_annotation == null) {
          printJavaNativeStub(
              env, writer, method, Mode.BUFFEROBJECT, generate_error_checks, context_specific);
        }
      }
    }
  }