// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.desugar.desugaredlibrary;

import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.onlyIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import org.hamcrest.Matcher;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

@RunWith(Parameterized.class)
public class ObjectsTest extends DesugaredLibraryTestBase implements Opcodes {

  private final TestParameters parameters;
  private final boolean libraryDesugarJavaUtilObjects;
  private final boolean shrinkDesugaredLibrary = false;
  private final Path androidJar;

  @Parameters(name = "{0}, libraryDesugarJavaUtilObjects: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
        BooleanUtils.values());
  }

  public ObjectsTest(TestParameters parameters, boolean libraryDesugarJavaUtilObjects) {
    this.parameters = parameters;
    this.libraryDesugarJavaUtilObjects = libraryDesugarJavaUtilObjects;
    // Using desugared library require a compile SDK of 26 or higher.
    this.androidJar =
        ToolHelper.getAndroidJar(Ordered.max(parameters.getApiLevel(), AndroidApiLevel.O));
  }

  DesugaredLibraryConfiguration desugaredLibraryConfiguration(
      InternalOptions options, boolean libraryCompilation, TestParameters parameters) {
    return new DesugaredLibraryConfigurationParser(
            options.dexItemFactory(),
            options.reporter,
            libraryCompilation,
            parameters.getApiLevel().getLevel())
        .parse(
            StringResource.fromFile(
                libraryDesugarJavaUtilObjects
                    ? ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING_ALTERNATIVE_3
                    : ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING));
  }

  private void configurationForProgramCompilation(InternalOptions options) {
    options.desugaredLibraryConfiguration =
        desugaredLibraryConfiguration(options, false, parameters);
  }

  private void configurationForLibraryCompilation(InternalOptions options) {
    options.desugaredLibraryConfiguration =
        desugaredLibraryConfiguration(options, true, parameters);
  }

  private Matcher<MethodSubject> invokesObjectsCompare(String holder) {
    return invokesMethod(
        "int",
        holder,
        "compare",
        ImmutableList.of("java.lang.Object", "java.lang.Object", "java.util.Comparator"));
  }

  private Matcher<MethodSubject> invokesObjectsEquals(String holder) {
    return invokesMethod(
        "boolean", holder, "equals", ImmutableList.of("java.lang.Object", "java.lang.Object"));
  }

  private Matcher<MethodSubject> invokesObjectsDeepEquals(String holder) {
    return invokesMethod(
        "boolean", holder, "deepEquals", ImmutableList.of("java.lang.Object", "java.lang.Object"));
  }

  private Matcher<MethodSubject> invokesObjectsHash(String holder) {
    return invokesMethod("int", holder, "hash", ImmutableList.of("java.lang.Object[]"));
  }

  private Matcher<MethodSubject> invokesObjectsHashCode(String holder) {
    return invokesMethod("int", holder, "hashCode", ImmutableList.of("java.lang.Object"));
  }

  private Matcher<MethodSubject> invokesClassGetClass() {
    return invokesMethod("java.lang.Class", "java.lang.Object", "getClass", ImmutableList.of());
  }

  private Matcher<MethodSubject> invokesObjectsRequireNonNull(String holder) {
    return invokesMethod(
        "java.lang.Object", holder, "requireNonNull", ImmutableList.of("java.lang.Object"));
  }

  private Matcher<MethodSubject> invokesObjectsRequireNonNullWithMessage(String holder) {
    return invokesMethod(
        "java.lang.Object",
        holder,
        "requireNonNull",
        ImmutableList.of("java.lang.Object", "java.lang.String"));
  }

  private Matcher<MethodSubject> invokesObjectsRequireNonNullWithSupplier(
      String holder, String Supplier) {
    return invokesMethod(
        "java.lang.Object",
        holder,
        "requireNonNull",
        ImmutableList.of("java.lang.Object", Supplier));
  }

  private Matcher<MethodSubject> invokesObjectsToString(String holder) {
    return invokesMethod(
        "java.lang.String", holder, "toString", ImmutableList.of("java.lang.Object"));
  }

  private Matcher<MethodSubject> invokesObjectsToStringWithNullDefault(String holder) {
    return invokesMethod(
        "java.lang.String",
        holder,
        "toString",
        ImmutableList.of("java.lang.Object", "java.lang.String"));
  }

  private Matcher<MethodSubject> invokesObjectsIsNull(String holder) {
    return invokesMethod("boolean", holder, "isNull", ImmutableList.of("java.lang.Object"));
  }

  private Matcher<MethodSubject> invokesObjectsNonNull(String holder) {
    return invokesMethod("boolean", holder, "nonNull", ImmutableList.of("java.lang.Object"));
  }

  private void inspect(CodeInspector inspector) {
    ClassSubject testClass = inspector.clazz(TestClass.class);
    assertThat(testClass, isPresent());

    // Objects.equals as added in Android K, so when backporting, this is only backported below K.
    // However, for library desugaring, the desugaring of Objects.equals happens all the way up to
    // Android M, as that is grouped with other methods like Objects.requireNonNull which was
    // added in Android N.
    boolean invokeJavaUtilObjects =
        !libraryDesugarJavaUtilObjects
                && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.K)
            || (libraryDesugarJavaUtilObjects
                && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N));
    boolean invokeJDollarUtilObjects =
        libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
    boolean invokeJavaUtilObjectsWithSupplier =
        !libraryDesugarJavaUtilObjects || !parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
    boolean invokeJDollarUtilObjectsWithSupplier =
        libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);

    assertThat(
        testClass.uniqueMethodWithName("objectsCompare"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsCompare("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsCompare"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsCompare("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsDeepEquals"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsDeepEquals("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsDeepEquals"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsDeepEquals("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsEquals"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsEquals("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsEquals"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsEquals("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsHash"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsHash("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsHash"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsHash("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsHashCode"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsHashCode("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsHashCode"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsHashCode("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsRequireNonNull"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsRequireNonNull("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsRequireNonNull"),
        onlyIf(parameters.getApiLevel().isLessThan(AndroidApiLevel.K), invokesClassGetClass()));

    assertThat(
        testClass.uniqueMethodWithName("objectsRequireNonNullWithMessage"),
        onlyIf(
            invokeJavaUtilObjects, invokesObjectsRequireNonNullWithMessage("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsRequireNonNullWithMessage"),
        onlyIf(
            invokeJDollarUtilObjects, invokesObjectsRequireNonNullWithMessage("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsRequireNonNullWithSupplier"),
        onlyIf(
            invokeJavaUtilObjectsWithSupplier,
            invokesObjectsRequireNonNullWithSupplier(
                "java.util.Objects", "java.util.function.Supplier")));
    assertThat(
        testClass.uniqueMethodWithName("objectsRequireNonNullWithSupplier"),
        onlyIf(
            invokeJDollarUtilObjectsWithSupplier,
            invokesObjectsRequireNonNullWithSupplier(
                "j$.util.Objects", "j$.util.function.Supplier")));

    assertThat(
        testClass.uniqueMethodWithName("objectsToString"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsToString("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsToString"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsToString("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsToStringWithNullDefault"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsToStringWithNullDefault("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsToStringWithNullDefault"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsToStringWithNullDefault("j$.util.Objects")));

    invokeJavaUtilObjects = parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);

    assertThat(
        testClass.uniqueMethodWithName("objectsIsNull"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsIsNull("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsIsNull"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsIsNull("j$.util.Objects")));

    assertThat(
        testClass.uniqueMethodWithName("objectsNonNull"),
        onlyIf(invokeJavaUtilObjects, invokesObjectsNonNull("java.util.Objects")));
    assertThat(
        testClass.uniqueMethodWithName("objectsNonNull"),
        onlyIf(invokeJDollarUtilObjects, invokesObjectsNonNull("j$.util.Objects")));
  }

  @Test
  public void testD8Cf() throws Exception {
    // Adjust API level if running on JDK 8. The java.util.Objects methods added in
    // Android R where added in JDK 9, so setting the the API level to Android P will backport
    // these methods for JDK 8.
    AndroidApiLevel apiLevel = parameters.getApiLevel();
    if (parameters.getRuntime().isCf()
        && parameters.getRuntime().asCf().getVm() == CfVm.JDK8
        && apiLevel.isGreaterThanOrEqualTo(AndroidApiLevel.R)) {
      apiLevel = AndroidApiLevel.P;
    }

    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    // Use D8 to desugar with Java classfile output.
    Path jar =
        testForD8(Backend.CF)
            .addLibraryFiles(androidJar)
            .addOptionsModification(this::configurationForProgramCompilation)
            .addInnerClasses(ObjectsTest.class)
            .addProgramClassFileData(dumpAndroidRUtilsObjectsMethods())
            .setMinApi(apiLevel)
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
            .compile()
            .inspect(this::inspect)
            .writeToZip();

    if (parameters.getRuntime().isDex()) {
      // Collection keep rules is only implemented in the DEX writer.
      String desugaredLibraryKeepRules = keepRuleConsumer.get();
      if (desugaredLibraryKeepRules != null) {
        assertEquals(0, desugaredLibraryKeepRules.length());
        desugaredLibraryKeepRules = "-keep class * { *; }";
      }

      // Convert to DEX without desugaring and run.
      testForD8()
          .addLibraryFiles(androidJar)
          .addProgramFiles(jar)
          .setMinApi(apiLevel)
          .disableDesugaring()
          .compile()
          .addDesugaredCoreLibraryRunClassPath(
              (apiLevel_, keepRules, shrink) ->
                  buildDesugaredLibrary(
                      apiLevel_,
                      keepRules,
                      shrink,
                      ImmutableList.of(),
                      this::configurationForLibraryCompilation),
              parameters.getApiLevel(),
              desugaredLibraryKeepRules,
              shrinkDesugaredLibrary)
          .run(
              parameters.getRuntime(),
              TestClass.class,
              Boolean.toString(libraryDesugarJavaUtilObjects))
          .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
    } else {
      // Build the desugared library in class file format.
      Path desugaredLib =
          getDesugaredLibraryInCF(parameters, this::configurationForLibraryCompilation);

      // Run on the JVM with desuagred library on classpath.
      testForJvm()
          .addProgramFiles(jar)
          .addRunClasspathFiles(desugaredLib)
          .run(
              parameters.getRuntime(),
              TestClass.class,
              Boolean.toString(libraryDesugarJavaUtilObjects))
          .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
    }
  }

  @Test
  public void testD8() throws Exception {
    Assume.assumeTrue(parameters.getRuntime().isDex());
    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    testForD8()
        .addLibraryFiles(androidJar)
        .addOptionsModification(this::configurationForProgramCompilation)
        .addInnerClasses(ObjectsTest.class)
        .addProgramClassFileData(dumpAndroidRUtilsObjectsMethods())
        .setMinApi(parameters.getApiLevel())
        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
        .compile()
        .addDesugaredCoreLibraryRunClassPath(
            (apiLevel, keepRules, shrink) ->
                buildDesugaredLibrary(
                    apiLevel,
                    keepRules,
                    shrink,
                    ImmutableList.of(),
                    this::configurationForLibraryCompilation),
            parameters.getApiLevel(),
            keepRuleConsumer.get(),
            shrinkDesugaredLibrary)
        .inspect(this::inspect)
        .run(
            parameters.getRuntime(),
            TestClass.class,
            Boolean.toString(libraryDesugarJavaUtilObjects))
        .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
  }

  @Test
  public void testR8() throws Exception {
    Assume.assumeTrue(parameters.getRuntime().isDex());
    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    testForR8(parameters.getBackend())
        .addLibraryFiles(androidJar)
        .addOptionsModification(this::configurationForProgramCompilation)
        .addInnerClasses(ObjectsTest.class)
        .addKeepMainRule(TestClass.class)
        .addProgramClassFileData(dumpAndroidRUtilsObjectsMethods())
        .enableInliningAnnotations()
        .noMinification()
        .addKeepRules("-keep class AndroidRUtilsObjectsMethods { *; }")
        .addKeepRules("-neverinline class AndroidRUtilsObjectsMethods { *; }")
        .setMinApi(parameters.getApiLevel())
        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
        .compile()
        .addDesugaredCoreLibraryRunClassPath(
            (apiLevel, keepRules, shrink) ->
                buildDesugaredLibrary(
                    apiLevel,
                    keepRules,
                    shrink,
                    ImmutableList.of(),
                    this::configurationForLibraryCompilation),
            parameters.getApiLevel(),
            keepRuleConsumer.get(),
            shrinkDesugaredLibrary)
        .inspect(this::inspect)
        .run(
            parameters.getRuntime(),
            TestClass.class,
            Boolean.toString(libraryDesugarJavaUtilObjects))
        .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
  }

  private String expectedOutput(boolean objectsRequireNonNullWithSupplierSupported) {
    return StringUtils.lines(
        "1",
        "true",
        "true",
        Objects.toString(Objects.hash(1, 2)),
        "4",
        "NPE",
        "Was null",
        objectsRequireNonNullWithSupplierSupported
            ? "Supplier said was null"
            : "Not supported (b/174840626)",
        "5",
        "6",
        "true",
        "false",
        "1",
        "2",
        "3",
        "4");
  }

  static class TestClass {
    @NeverInline
    private static void objectsCompare(String s1, String s2) {
      Comparator<String> stringsNullLast =
          (o1, o2) -> {
            if (o1 == null) {
              return o2 == null ? 0 : 1;
            }
            return o2 == null ? -1 : o1.compareTo(o2);
          };
      System.out.println(Objects.compare(s1, s2, stringsNullLast));
    }

    @NeverInline
    private static void objectsDeepEquals(Object o1, Object o2) {
      System.out.println(Objects.deepEquals(o1, o2));
    }

    @NeverInline
    private static void objectsEquals(Object o1, Object o2) {
      System.out.println(Objects.equals(o1, o2));
    }

    @NeverInline
    private static void objectsHash(Object o1, Object o2) {
      System.out.println(Objects.hash(o1, o2));
    }

    @NeverInline
    private static void objectsHashCode(Object o) {
      System.out.println(Objects.hashCode(o));
    }

    @NeverInline
    private static void objectsRequireNonNull(Object o) {
      try {
        System.out.println(Objects.requireNonNull(o));
      } catch (NullPointerException e) {
        System.out.println("NPE");
      }
    }

    @NeverInline
    private static void objectsRequireNonNullWithMessage(Object o, String message) {
      try {
        System.out.println(Objects.requireNonNull(o, message));
      } catch (NullPointerException e) {
        System.out.println(e.getMessage());
      }
    }

    @NeverInline
    private static void objectsRequireNonNullWithSupplier(
        Object o, Supplier<String> messageSupplier) {
      try {
        System.out.println(Objects.requireNonNull(o, messageSupplier));
      } catch (NullPointerException e) {
        System.out.println(e.getMessage());
      }
    }

    @NeverInline
    private static void objectsToString(Object o) {
      System.out.println(Objects.toString(o));
    }

    @NeverInline
    private static void objectsToStringWithNullDefault(Object o, String nullDefault) {
      System.out.println(Objects.toString(o, nullDefault));
    }

    @NeverInline
    private static void objectsIsNull(Object o) {
      System.out.println(Objects.isNull(o));
    }

    @NeverInline
    private static void objectsNonNull(Object o) {
      System.out.println(Objects.nonNull(o));
    }

    public static void main(String[] args) throws Exception {
      boolean objectsRequireNonNullWithSupplierSupported = Boolean.parseBoolean(args[0]);
      // Android K methods.
      objectsCompare("b", "a");
      objectsDeepEquals(args, args);
      objectsEquals(args, args);
      objectsHash(1, 2);
      objectsHashCode(4);
      objectsRequireNonNull(System.currentTimeMillis() >= 0 ? null : new Object());
      objectsRequireNonNullWithMessage(null, "Was null");
      if (objectsRequireNonNullWithSupplierSupported) {
        objectsRequireNonNullWithSupplier(null, () -> "Supplier said was null");
      } else {
        System.out.println("Not supported (b/174840626)");
      }
      objectsToString("5");
      objectsToStringWithNullDefault(null, "6");

      // Android N methods.
      objectsIsNull(null);
      objectsNonNull(null);

      // Android R methods.
      Class<?> c = Class.forName("AndroidRUtilsObjectsMethods");
      c.getDeclaredMethod("checkFromIndexSize", int.class, int.class, int.class)
          .invoke(null, 1, 2, 10);
      c.getDeclaredMethod("checkFromToIndex", int.class, int.class, int.class)
          .invoke(null, 2, 4, 10);
      c.getDeclaredMethod("checkIndex", int.class, int.class).invoke(null, 3, 10);
      c.getDeclaredMethod("requireNonNullElse", Object.class, Object.class).invoke(null, null, 4);
      // TODO(b/174840626) Also support requireNonNullElseGet.
    }
  }

  /*
    Dump below is from this source:

    import java.util.function.Supplier;
    import java.util.Objects;

    public class AndroidRUtilsObjectsMethods {
      public static void checkFromIndexSize(int fromIndex, int size, int length) {
        System.out.println(Objects.checkFromIndexSize(fromIndex, size, length));
      }
      public static void checkFromToIndex(int fromIndex, int toIndex, int length) {
        System.out.println(Objects.checkFromToIndex(fromIndex, toIndex, length));
      }
      public static void checkIndex(int index, int length) {
        System.out.println(Objects.checkIndex(index, length));
      }
      public static <T> void requireNonNullElse(T obj, T defaultObj) {
        System.out.println(Objects.requireNonNullElse(obj, defaultObj));
      }
      public static <T> void requireNonNullElseGet(T obj, Supplier<? extends T> supplier) {
        System.out.println(Objects.requireNonNullElse(obj, supplier));
      }
    }

    This is added as a dump as it use APIs which are only abailable from JDK 9.
  */
  public static byte[] dumpAndroidRUtilsObjectsMethods() throws Exception {

    ClassWriter classWriter = new ClassWriter(0);
    MethodVisitor methodVisitor;

    classWriter.visit(
        V9, ACC_PUBLIC | ACC_SUPER, "AndroidRUtilsObjectsMethods", null, "java/lang/Object", null);

    classWriter.visitSource("AndroidRUtilsObjectsMethods.java", null);

    {
      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(3, label0);
      methodVisitor.visitVarInsn(ALOAD, 0);
      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(1, 1);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor =
          classWriter.visitMethod(
              ACC_PUBLIC | ACC_STATIC, "checkFromIndexSize", "(III)V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(5, label0);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitVarInsn(ILOAD, 0);
      methodVisitor.visitVarInsn(ILOAD, 1);
      methodVisitor.visitVarInsn(ILOAD, 2);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC, "java/util/Objects", "checkFromIndexSize", "(III)I", false);
      methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
      Label label1 = new Label();
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(6, label1);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(4, 3);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor =
          classWriter.visitMethod(
              ACC_PUBLIC | ACC_STATIC, "checkFromToIndex", "(III)V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(8, label0);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitVarInsn(ILOAD, 0);
      methodVisitor.visitVarInsn(ILOAD, 1);
      methodVisitor.visitVarInsn(ILOAD, 2);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC, "java/util/Objects", "checkFromToIndex", "(III)I", false);
      methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
      Label label1 = new Label();
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(9, label1);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(4, 3);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor =
          classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "checkIndex", "(II)V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(11, label0);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitVarInsn(ILOAD, 0);
      methodVisitor.visitVarInsn(ILOAD, 1);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC, "java/util/Objects", "checkIndex", "(II)I", false);
      methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
      Label label1 = new Label();
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(12, label1);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(3, 2);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor =
          classWriter.visitMethod(
              ACC_PUBLIC | ACC_STATIC,
              "requireNonNullElse",
              "(Ljava/lang/Object;Ljava/lang/Object;)V",
              "<T:Ljava/lang/Object;>(TT;TT;)V",
              null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(14, label0);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitVarInsn(ALOAD, 0);
      methodVisitor.visitVarInsn(ALOAD, 1);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC,
          "java/util/Objects",
          "requireNonNullElse",
          "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
          false);
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
      Label label1 = new Label();
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(15, label1);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(3, 2);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor =
          classWriter.visitMethod(
              ACC_PUBLIC | ACC_STATIC,
              "requireNonNullElseGet",
              "(Ljava/lang/Object;Ljava/util/function/Supplier;)V",
              "<T:Ljava/lang/Object;>(TT;Ljava/util/function/Supplier<+TT;>;)V",
              null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(18, label0);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitVarInsn(ALOAD, 0);
      methodVisitor.visitVarInsn(ALOAD, 1);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC,
          "java/util/Objects",
          "requireNonNullElse",
          "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
          false);
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
      Label label1 = new Label();
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(19, label1);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(3, 2);
      methodVisitor.visitEnd();
    }
    classWriter.visitEnd();

    return classWriter.toByteArray();
  }
}
