// Copyright (c) 2019, 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.ir.optimize.membervaluepropagation;

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

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
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.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class InstanceFieldValuePropagationTest extends TestBase {

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public InstanceFieldValuePropagationTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void test() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(InstanceFieldValuePropagationTest.class)
        .addKeepMainRule(TestClass.class)
        .enableClassInliningAnnotations()
        .enableInliningAnnotations()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(this::inspect)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(
            StringUtils.times(StringUtils.lines("A", "42", "Hello world!"), 2));
  }

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

    // Verify that all instance-get instructions in testDefinitelyNotNull() has been removed by
    // member value propagation.
    MethodSubject testDefinitelyNotNullMethodSubject =
        testClassSubject.uniqueMethodWithName("testDefinitelyNotNull");
    assertThat(testDefinitelyNotNullMethodSubject, isPresent());
    assertTrue(
        testDefinitelyNotNullMethodSubject
            .streamInstructions()
            .noneMatch(InstructionSubject::isInstanceGet));
    // TODO(b/125282093): Should be able to remove the new-instance instruction since the instance
    //  ends up being unused.
    assertTrue(
        testDefinitelyNotNullMethodSubject
            .streamInstructions()
            .anyMatch(InstructionSubject::isNewInstance));

    // Verify that all instance-get instructions in testMaybeNull() has been removed by member value
    // propagation.
    MethodSubject testMaybeNullMethodSubject =
        testClassSubject.uniqueMethodWithName("testMaybeNull");
    assertThat(testMaybeNullMethodSubject, isPresent());
    // TODO(b/125282093): Should synthesize a null-check and still propagate the field values even
    //  when the receiver is nullable.
    assertTrue(
        testMaybeNullMethodSubject
            .streamInstructions()
            .anyMatch(InstructionSubject::isInstanceGet));
    // TODO(b/125282093): Should be able to remove the new-instance instruction since the instance
    //  ends up being unused.
    assertTrue(
        testMaybeNullMethodSubject
            .streamInstructions()
            .anyMatch(InstructionSubject::isNewInstance));

    ClassSubject aClassSubject = inspector.clazz(A.class);
    assertThat(aClassSubject, isPresent());
    // TODO(b/125282093): Need to remove the instance-put instructions in A.<init>(). This can not
    //  be done safely by the time we process A.<init>(), so some kind of post-processing is needed.
    assertEquals(3, aClassSubject.allInstanceFields().size());
  }

  static class TestClass {

    public static void main(String[] args) {
      testDefinitelyNotNull();
      testMaybeNull();
    }

    @NeverInline
    static void testDefinitelyNotNull() {
      A a = new A();
      System.out.println(a.e);
      System.out.println(a.i);
      System.out.println(a.s);
    }

    @NeverInline
    static void testMaybeNull() {
      A a = System.currentTimeMillis() >= 0 ? new A() : null;
      System.out.println(a.e);
      System.out.println(a.i);
      System.out.println(a.s);
    }
  }

  @NeverClassInline
  static class A {

    MyEnum e = MyEnum.A;
    int i = 42;
    String s = "Hello world!";
  }

  enum MyEnum {
    A,
    B
  }
}
