// Copyright (c) 2017, 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.analysis.type;

import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
import static com.android.tools.r8.ir.analysis.type.TypeElement.fromDexType;
import static com.android.tools.r8.ir.analysis.type.TypeElement.stringClassType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.ArrayGet;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.AssumeInserter;
import com.android.tools.r8.ir.optimize.NonNullTrackerTestBase;
import com.android.tools.r8.ir.optimize.nonnull.FieldAccessTest;
import com.android.tools.r8.ir.optimize.nonnull.NonNullAfterArrayAccess;
import com.android.tools.r8.ir.optimize.nonnull.NonNullAfterFieldAccess;
import com.android.tools.r8.ir.optimize.nonnull.NonNullAfterInvoke;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.function.BiConsumer;
import org.junit.Test;

public class NullabilityTest extends NonNullTrackerTestBase {
  private void buildAndTest(
      Class<?> mainClass,
      MethodSignature signature,
      boolean npeCaught,
      BiConsumer<AppView<?>, IRCode> inspector)
      throws Exception {
    AppView<? extends AppInfoWithClassHierarchy> appView = build(mainClass);
    CodeInspector codeInspector = new CodeInspector(appView.appInfo().app());
    MethodSubject fooSubject = codeInspector.clazz(mainClass.getName()).method(signature);
    IRCode irCode = fooSubject.buildIR();
    new AssumeInserter(appView).insertAssumeInstructions(irCode, Timing.empty());
    inspector.accept(appView, irCode);
    verifyLastInvoke(irCode, npeCaught);
  }

  private static void verifyClassTypeLattice(
      Map<Class<? extends Instruction>, TypeElement> expectedLattices,
      DexType receiverType,
      Value v,
      TypeElement l) {
    // Due to the last invocation that will check nullability of the argument,
    // there is one exceptional mapping to PRIMITIVE.
    if (l.isPrimitiveType()) {
      return;
    }
    assertTrue(l.isClassType());
    ClassTypeElement lattice = l.asClassType();
    // Receiver
    if (lattice.getClassType().equals(receiverType)) {
      assertFalse(l.isNullable());
    } else {
      Instruction definition = v.definition;
      if (definition != null) {
        TypeElement expected = expectedLattices.get(v.definition.getClass());
        if (expected != null) {
          assertEquals(expected, l);
        }
      }
    }
  }

  private void verifyLastInvoke(IRCode code, boolean npeCaught) {
    boolean metInvokeVirtual = false;
    for (Instruction instruction : code.instructions()) {
      if (instruction.isInvokeMethodWithReceiver()) {
        InvokeMethodWithReceiver invoke = instruction.asInvokeMethodWithReceiver();
        if (invoke.getInvokedMethod().name.toString().contains("hash")) {
          metInvokeVirtual = true;
          TypeElement l = invoke.getReceiver().getType();
          assertEquals(npeCaught, l.isNullable());
        }
      }
    }
    assertTrue(metInvokeVirtual);
  }

  private void forEachOutValue(IRCode irCode, BiConsumer<Value, TypeElement> consumer) {
    irCode
        .instructionIterator()
        .forEachRemaining(
            instruction -> {
              Value outValue = instruction.outValue();
              if (outValue != null) {
                TypeElement element = outValue.getType();
                consumer.accept(outValue, element);
              }
            });
  }

  @Test
  public void nonNullAfterSafeInvokes() throws Exception {
    MethodSignature signature =
        new MethodSignature("foo", "int", new String[]{"java.lang.String"});
    buildAndTest(
        NonNullAfterInvoke.class,
        signature,
        false,
        (appInfo, irCode) -> {
          DexType assertionErrorType =
              appInfo.dexItemFactory().createType("Ljava/lang/AssertionError;");
          DexType mainClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          NonNullAfterInvoke.class.getCanonicalName()));
          Map<Class<? extends Instruction>, TypeElement> expectedLattices =
              ImmutableMap.of(
                  InvokeVirtual.class, stringClassType(appInfo, maybeNull()),
                  Assume.class, stringClassType(appInfo, definitelyNotNull()),
                  NewInstance.class, fromDexType(assertionErrorType, definitelyNotNull(), appInfo));
          forEachOutValue(
              irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
        });
  }

  @Test
  public void stillNullAfterExceptionCatch_invoke() throws Exception {
    MethodSignature signature =
        new MethodSignature("bar", "int", new String[]{"java.lang.String"});
    buildAndTest(
        NonNullAfterInvoke.class,
        signature,
        true,
        (appInfo, irCode) -> {
          DexType assertionErrorType =
              appInfo.dexItemFactory().createType("Ljava/lang/AssertionError;");
          DexType mainClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          NonNullAfterInvoke.class.getCanonicalName()));
          Map<Class<? extends Instruction>, TypeElement> expectedLattices =
              ImmutableMap.of(
                  InvokeVirtual.class, stringClassType(appInfo, maybeNull()),
                  Assume.class, stringClassType(appInfo, definitelyNotNull()),
                  NewInstance.class, fromDexType(assertionErrorType, definitelyNotNull(), appInfo));
          forEachOutValue(
              irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
        });
  }

  @Test
  public void nonNullAfterSafeArrayAccess() throws Exception {
    MethodSignature signature =
        new MethodSignature("foo", "int", new String[]{"java.lang.String[]"});
    buildAndTest(
        NonNullAfterArrayAccess.class,
        signature,
        false,
        (appInfo, irCode) -> {
          DexType assertionErrorType =
              appInfo.dexItemFactory().createType("Ljava/lang/AssertionError;");
          DexType mainClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          NonNullAfterArrayAccess.class.getCanonicalName()));
          Map<Class<? extends Instruction>, TypeElement> expectedLattices =
              ImmutableMap.of(
                  // An element inside a non-null array could be null.
                  ArrayGet.class,
                      fromDexType(appInfo.dexItemFactory().stringType, maybeNull(), appInfo),
                  NewInstance.class, fromDexType(assertionErrorType, definitelyNotNull(), appInfo));
          forEachOutValue(
              irCode,
              (v, l) -> {
                if (l.isArrayType()) {
                  ArrayTypeElement lattice = l.asArrayType();
                  assertEquals(1, lattice.getNesting());
                  TypeElement elementType = lattice.getMemberType();
                  assertTrue(elementType.isClassType());
                  assertEquals(
                      appInfo.dexItemFactory().stringType,
                      elementType.asClassType().getClassType());
                  assertEquals(v.definition.isArgument(), l.isNullable());
                } else if (l.isClassType()) {
                  verifyClassTypeLattice(expectedLattices, mainClass, v, l);
                }
              });
        });
  }

  @Test
  public void stillNullAfterExceptionCatch_aget() throws Exception {
    MethodSignature signature =
        new MethodSignature("bar", "int", new String[]{"java.lang.String[]"});
    buildAndTest(
        NonNullAfterArrayAccess.class,
        signature,
        true,
        (appInfo, irCode) -> {
          DexType assertionErrorType =
              appInfo.dexItemFactory().createType("Ljava/lang/AssertionError;");
          DexType mainClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          NonNullAfterArrayAccess.class.getCanonicalName()));
          Map<Class<? extends Instruction>, TypeElement> expectedLattices =
              ImmutableMap.of(
                  // An element inside a non-null array could be null.
                  ArrayGet.class,
                      fromDexType(appInfo.dexItemFactory().stringType, maybeNull(), appInfo),
                  NewInstance.class, fromDexType(assertionErrorType, definitelyNotNull(), appInfo));
          forEachOutValue(
              irCode,
              (v, l) -> {
                if (l.isArrayType()) {
                  ArrayTypeElement lattice = l.asArrayType();
                  assertEquals(1, lattice.getNesting());
                  TypeElement elementTypeLattice = lattice.getMemberType();
                  assertTrue(elementTypeLattice.isClassType());
                  assertEquals(
                      appInfo.dexItemFactory().stringType,
                      elementTypeLattice.asClassType().getClassType());
                  assertEquals(v.definition.isArgument(), l.isNullable());
                } else if (l.isClassType()) {
                  verifyClassTypeLattice(expectedLattices, mainClass, v, l);
                }
              });
        });
  }

  @Test
  public void nonNullAfterSafeFieldAccess() throws Exception {
    MethodSignature signature = new MethodSignature("foo", "int",
        new String[]{FieldAccessTest.class.getCanonicalName()});
    buildAndTest(
        NonNullAfterFieldAccess.class,
        signature,
        false,
        (appInfo, irCode) -> {
          DexType assertionErrorType =
              appInfo.dexItemFactory().createType("Ljava/lang/AssertionError;");
          DexType mainClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          NonNullAfterFieldAccess.class.getCanonicalName()));
          DexType testClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          FieldAccessTest.class.getCanonicalName()));
          Map<Class<? extends Instruction>, TypeElement> expectedLattices =
              ImmutableMap.of(
                  Argument.class, fromDexType(testClass, maybeNull(), appInfo),
                  Assume.class, fromDexType(testClass, definitelyNotNull(), appInfo),
                  // instance may not be initialized.
                  InstanceGet.class,
                      fromDexType(appInfo.dexItemFactory().stringType, maybeNull(), appInfo),
                  NewInstance.class, fromDexType(assertionErrorType, definitelyNotNull(), appInfo));
          forEachOutValue(
              irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
        });
  }

  @Test
  public void stillNullAfterExceptionCatch_iget() throws Exception {
    MethodSignature signature = new MethodSignature("bar", "int",
        new String[]{FieldAccessTest.class.getCanonicalName()});
    buildAndTest(
        NonNullAfterFieldAccess.class,
        signature,
        true,
        (appInfo, irCode) -> {
          DexType assertionErrorType =
              appInfo.dexItemFactory().createType("Ljava/lang/AssertionError;");
          DexType mainClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          NonNullAfterFieldAccess.class.getCanonicalName()));
          DexType testClass =
              appInfo
                  .dexItemFactory()
                  .createType(
                      DescriptorUtils.javaTypeToDescriptor(
                          FieldAccessTest.class.getCanonicalName()));
          Map<Class<? extends Instruction>, TypeElement> expectedLattices =
              ImmutableMap.of(
                  Argument.class, fromDexType(testClass, maybeNull(), appInfo),
                  Assume.class, fromDexType(testClass, definitelyNotNull(), appInfo),
                  // instance may not be initialized.
                  InstanceGet.class,
                      fromDexType(appInfo.dexItemFactory().stringType, maybeNull(), appInfo),
                  NewInstance.class, fromDexType(assertionErrorType, definitelyNotNull(), appInfo));
          forEachOutValue(
              irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
        });
  }
}
