// 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.graph.genericsignature;

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static com.google.common.base.Predicates.alwaysFalse;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.GenericSignaturePrinter;
import com.android.tools.r8.graph.GenericSignatureTypeRewriter;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.Reporter;
import java.util.function.Function;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

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

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

  public ClassSignatureTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  @Test
  public void testSuperClass() {
    testParsingAndPrintingEqual("Lfoo/bar/baz;");
  }

  @Test
  public void testSuperClassWithInnerClasses() {
    testParsingAndPrintingEqual("Lfoo/bar/baz.Foo.Bar;");
  }

  @Test
  public void testSuperClassWithInterfaces1() {
    testParsingAndPrintingEqual("Lfoo/bar/baz;Lfoo/bar/qux;");
  }

  @Test
  public void testSuperClassWithInterfaces2() {
    testParsingAndPrintingEqual("Lfoo/bar/baz;Lfoo/bar/qux;Lfoo/bar/quux;");
  }

  @Test
  public void testSuperClassWithInterfacesInnerClassesSeparatedByDollar() {
    testParsingAndPrintingEqual("Lfoo/bar/baz$Foo$Bar;Lfoo/bar/qux;Lfoo/bar/quux$Foo$Bar;");
  }

  @Test
  public void testSuperClassWithInterfacesInnerClassesSeparatedByPeriod() {
    testParsingAndPrintingEqual("Lfoo/bar/baz.Foo.Bar;Lfoo/bar/qux;Lfoo/bar/quux.Foo.Bar;");
  }

  @Test
  public void testInnerClassesWithSeparatorInName1() {
    testParsingAndPrintingEqual("Lfoo/bar/baz<*>.Foo$$$<*>.Bar;");
  }

  @Test
  public void testInnerClassesWithSeparatorInName2() {
    testParsingAndPrintingEqual("Lfoo/bar/baz<*>.Foo$Bar$$<*>.Qux;");
  }

  @Test
  public void testSuperClassWithInnerClassesGenericArguments2() {
    testParsingAndPrintingEqual("Lfoo/bar/baz<LFoo;>.Foo<LFoo;>.Bar<LFoo;>;");
  }

  @Test
  public void testSuperClassWithInterfacesInnerClassesGenericArguments2() {
    testParsingAndPrintingEqual(
        "Lfoo/bar/baz<LFoo;>.Foo<LFoo;>.Bar<LFoo;>;Lfoo/bar/qux<LFoo;>;Lfoo/bar/quux<LFoo;>.Foo<LFoo;>.Bar<LFoo;>;");
  }

  @Test
  public void testSuperClassWithInterfacesInnerClassesGenericArguments3() {
    testParsingAndPrintingEqual(
        "Lfoo/bar/baz<LFoo;[[I[[[LBar<LFoo;>;>.Foo<LFoo;>.Bar<LFoo;>;Lfoo/bar/qux<LFoo;>;Lfoo/bar/quux<LFoo;>.Foo<LFoo;>.Bar<LFoo;>;");
  }

  @Test
  public void testWildCards() {
    testParsingAndPrintingEqual("Lfoo/Bar<*>;");
  }

  @Test
  public void testWildCardsPositiveNegative() {
    testParsingAndPrintingEqual("Lfoo/Bar<*+[I-LFoo<+LBar;>;>;");
  }

  @Test
  public void testSuperClassError() {
    testParsingAndPrintingError("Lfoo/bar/baz")
        .assertAllWarningsMatch(
            diagnosticMessage(containsString("Invalid signature 'Lfoo/bar/baz'")));
  }

  @Test
  public void testReferenceToTypeVariable() {
    testParsingAndPrintingEqual("Lfoo/bar/baz<TT;>;");
  }

  @Test
  public void testFormalTypeParameters() {
    testParsingAndPrintingEqual("<T:Ljava/lang/Object;>Lfoo/bar/baz<TT;>;");
  }

  @Test
  public void testFormalTypeWithEmpty() {
    testParsingAndPrintingEqual("<T:>Lfoo/bar/baz<TT;>;");
  }

  @Test
  public void testFormalTypeParametersWithInterfaces() {
    testParsingAndPrintingEqual("<T:Ljava/lang/Object;:LI;>Lfoo/bar/baz<TT;>;");
  }

  @Test
  public void testFormalTypeParametersArguments() {
    testParsingAndPrintingEqual(
        "<T:Ljava/lang/Object;:LI;R:LFoo<TT;[Lfoo/bar<TT;>.Baz<TT;[I>;>;>Lfoo/bar/baz<TT;>;");
  }

  @Test
  public void testFormalTypeParameterEmptyInterfaceError() {
    testParsingAndPrintingError("<T:Ljava/lang/Object;:>Lfoo/bar/baz<TT;>;")
        .assertAllWarningsMatch(
            diagnosticMessage(
                containsString("Invalid signature '<T:Ljava/lang/Object;:>Lfoo/bar/baz<TT;>;'")));
  }

  @Test
  public void testFormalTypeParametersEmptyError() {
    // TODO(b/169716723): This should throw an error
    assertThrows(AssertionError.class, () -> testParsingAndPrintingError("<>Lfoo/bar/baz<TT;>;"));
  }

  @Test
  public void testPruningInterfaceBound() {
    DexItemFactory factory = new DexItemFactory();
    DexType context = factory.createType("Lj$/util/stream/Node$OfPrimitive;");
    String methodName = "j$.util.stream.Node$OfPrimitive.foo()";
    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
    MethodTypeSignature parsedMethodSignature =
        GenericSignature.parseMethodSignature(
            methodName,
            "<T_SPLITR::Lj$/util/Spliterator$OfPrimitive;T_NODE:Ljava/lang/Object;>()V",
            Origin.unknown(),
            factory,
            testDiagnosticMessages);
    testDiagnosticMessages.assertNoMessages();
    assertTrue(parsedMethodSignature.hasSignature());
    GenericSignatureTypeRewriter rewriter =
        new GenericSignatureTypeRewriter(
            factory,
            dexType -> dexType.toDescriptorString().equals("Lj$/util/Spliterator$OfPrimitive;"),
            Function.identity(),
            null);
    MethodTypeSignature rewritten = rewriter.rewrite(parsedMethodSignature);
    assertNotNull(rewritten);
    assertTrue(rewritten.hasSignature());
    MethodTypeSignature reparsed =
        GenericSignature.parseMethodSignature(
            methodName, rewritten.toString(), Origin.unknown(), factory, testDiagnosticMessages);
    assertTrue(reparsed.hasSignature());
    testDiagnosticMessages.assertNoMessages();
    assertEquals(rewritten.toString(), reparsed.toString());
  }

  private void testParsingAndPrintingEqual(String signature) {
    ClassSignature parsed =
        GenericSignature.parseClassSignature(
            "A", signature, Origin.unknown(), new DexItemFactory(), new Reporter());
    GenericSignaturePrinter genericSignaturePrinter =
        new GenericSignaturePrinter(NamingLens.getIdentityLens(), alwaysFalse());
    genericSignaturePrinter.visitClassSignature(parsed);
    String outSignature = genericSignaturePrinter.toString();
    assertEquals(signature, outSignature);
  }

  private TestDiagnosticMessages testParsingAndPrintingError(String signature) {
    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
    ClassSignature parsed =
        GenericSignature.parseClassSignature(
            "A",
            signature,
            Origin.unknown(),
            new DexItemFactory(),
            new Reporter(testDiagnosticMessages));
    assertEquals(ClassSignature.noSignature(), parsed);
    return testDiagnosticMessages;
  }
}
