/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.jjs.impl;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.util.arg.SourceLevel;

/**
 * Test for {@link Pruner}.
 */
public class PrunerTest extends OptimizerTestBase {
  @Override
  protected void setUp() throws Exception {
    sourceLevel = SourceLevel.JAVA8;
    super.setUp();
    runDeadCodeElimination = true;
  }

  public void testSmoke() throws Exception {
    addSnippetClassDecl("static int foo(int i) { return i; }");

    addSnippetClassDecl("static void unusedMethod() { }");
    addSnippetClassDecl("static void usedMethod() { }");
    addSnippetClassDecl("static class UnusedClass { }");
    addSnippetClassDecl("static class UninstantiatedClass { "
        + "int field; native int method() /*-{ return 1; }-*/; }");
    addSnippetClassDecl("static UninstantiatedClass uninstantiatedField;");
    addSnippetClassDecl("static int unusedField;");
    addSnippetClassDecl("static int unreadField;");
    addSnippetClassDecl("static int unassignedField;");
    addSnippetClassDecl("static UninstantiatedClass returnUninstantiatedClass() { return null; }");
    addSnippetClassDecl(
        "interface UsedInterface {",
        "  int unusedConstant = 2;",
        "  int usedConstant = 3;",
        "  void method2();",
        "}");
    addSnippetClassDecl("static class UsedClass implements UsedInterface {",
        "  int field2;",
        "  public void method2() { field2 = usedConstant; }",
        "  UsedClass(UninstantiatedClass c) { }",
        "  UsedClass(UninstantiatedClass c1, UninstantiatedClass c2) { }",
        "  UsedClass(UninstantiatedClass c1, int i, UninstantiatedClass c2) { field2 = i; }",
        "  UsedClass(UninstantiatedClass c1, int i, UninstantiatedClass c2, int j) " +
            "{ field2 = i + j; }",
        "}");
    addSnippetClassDecl(
        "static native void usedNativeMethod(UninstantiatedClass c, UsedClass c2)",
        "/*-{",
        "  c.@test.EntryPoint.UninstantiatedClass::field = 2;",
        "  c.@test.EntryPoint.UninstantiatedClass::method();",
        "  c2.@test.EntryPoint.UsedClass::field2++;",
        "  c2.@test.EntryPoint.UsedClass::method2();",
        "}-*/;");
    addSnippetClassDecl(
        "static native void unusedNativeMethod()",
        "/*-{",
        "}-*/;");
    addSnippetClassDecl("static void methodWithUninstantiatedParam(UninstantiatedClass c) { }");
    addSnippetClassDecl("interface UnusedInterface { void foo(); }");
    addSnippetClassDecl("interface Callback { void go(); }");
    addSnippetImport("jsinterop.annotations.JsType");
    addSnippetImport("jsinterop.annotations.JsConstructor");
    addSnippetClassDecl("@JsType interface Js { void doIt(Callback cb); }");
    addSnippetClassDecl("@JsType(isNative=true) static class JsProto { ",
        "public JsProto(int arg) {}",
        "}");
    addSnippetClassDecl("static class JsProtoImpl extends JsProto {",
        "public JsProtoImpl() { super(10); }",
        "}");

    addSnippetClassDecl("static class JsProtoImpl2 extends JsProto {",
        "@JsConstructor public JsProtoImpl2() { super(10); }",
        "}");

    addSnippetClassDecl("static class JsProtoImpl3 extends JsProto {",
        "public JsProtoImpl3() { super(10); }",
        "}");

    Result result;
    (result = optimize("void",
        "usedMethod();",
        "unreadField = 1;",  // should be pruned because it's not read.
        "foo(unassignedField);",
        "returnUninstantiatedClass();",
        "usedNativeMethod(null, null);",
        "foo(uninstantiatedField.field);",
        "uninstantiatedField.method();",
        "methodWithUninstantiatedParam(null);",
        "new UsedClass(null);",
        "new UsedClass(returnUninstantiatedClass(), returnUninstantiatedClass());",
        "new UsedClass(returnUninstantiatedClass(), 3, returnUninstantiatedClass());",
        "new UsedClass(returnUninstantiatedClass(), 3, returnUninstantiatedClass(), 4);",
        "UninstantiatedClass localUninstantiated = null;",
        "JsProtoImpl jsp = new JsProtoImpl();"
        )).intoString(
            "EntryPoint.usedMethod();",
            "EntryPoint.foo(EntryPoint.unassignedField);",
            "EntryPoint.returnUninstantiatedClass();",
            "EntryPoint.usedNativeMethod(null, null);",
            "EntryPoint.foo(null.nullField);",
            "null.nullMethod();",
            "EntryPoint.methodWithUninstantiatedParam();",
            "new EntryPoint$UsedClass();",
            "EntryPoint.returnUninstantiatedClass();",
            "EntryPoint.returnUninstantiatedClass();",
            "new EntryPoint$UsedClass();",
            "int lastArg;",
            "new EntryPoint$UsedClass((lastArg = (EntryPoint.returnUninstantiatedClass(), 3), EntryPoint.returnUninstantiatedClass(), lastArg));",
            "new EntryPoint$UsedClass((EntryPoint.returnUninstantiatedClass(), 3), (EntryPoint.returnUninstantiatedClass(), 4));",
            "new EntryPoint$JsProtoImpl();"
            );

    assertNotNull(result.findMethod("usedMethod"));
    // We do not assign to the field, but we use its default value.
    // Shouldn't be pruned.
    assertNotNull(result.findField("unassignedField"));
    assertNotNull(result.findMethod("usedNativeMethod"));
    assertNotNull(result.findMethod("returnUninstantiatedClass"));
    assertNotNull(result.findMethod("methodWithUninstantiatedParam"));
    assertNotNull(result.findClass("EntryPoint$UsedClass"));
    assertNotNull(result.findClass("EntryPoint$UsedInterface"));

    assertNull(result.findMethod("unusedMethod"));
    assertNull(result.findField("unusedField"));
    assertNull(result.findField("unreadField"));
    assertNull(result.findClass("EntryPoint$UnusedClass"));
    assertNull(result.findMethod("unusedNativeMethod"));
    assertNull(result.findField("uninstantiatedField"));
    assertNull(result.findClass("EntryPoint$UnusedInterface"));

    // Class is never instantiated. Should be pruned.
    assertNull(result.findClass("UninstantiatedClass"));

    assertEquals(
        "static null returnUninstantiatedClass(){\n" +
        "  return null;\n" +
        "}",
        result.findMethod("returnUninstantiatedClass").toSource());

    assertEquals(
        "static void methodWithUninstantiatedParam(){\n" +
        "}",
        result.findMethod("methodWithUninstantiatedParam").toSource());

    assertEquals(
        "[final null nullField, int field2]",
        ((JsniMethodBody) result.findMethod("usedNativeMethod").getBody())
            .getJsniFieldRefs().toString());
    assertEquals(
        "[public final null nullMethod(), public void method2()]",
        ((JsniMethodBody) result.findMethod("usedNativeMethod").getBody())
            .getJsniMethodRefs().toString());

    assertEquals(
        "interface EntryPoint$UsedInterface {\n" +
        "  final static int usedConstant\n\n" +
        "  private static final void $clinit(){\n" +
        "    final static int usedConstant = 3;\n" +
        "  }\n" +
        "\n" +
        "}",
        result.findClass("EntryPoint$UsedInterface").toSource());

    // Neither super ctor call, nor super call's param is pruned
    assertEquals(
        "public EntryPoint$JsProtoImpl(){\n" +
            "  super(10);\n" +
            "  this.$init();\n" +
            "}",
        findMethod(result.findClass("EntryPoint$JsProtoImpl"), "EntryPoint$JsProtoImpl").toSource());

    // Not JsType'd, and not instantiated, so should be pruned
    assertNull(result.findClass("EntryPoint$JsProtoImpl3"));

    // Should be rescued because of @JsType
    assertNotNull(result.findClass("EntryPoint$JsProtoImpl2"));
  }

  public void testCleanupVariableOfNonReferencedType() throws Exception {
    runDeadCodeElimination = false;
    addSnippetClassDecl("static class A {}");
    addSnippetClassDecl("static boolean fun(A a) { return a == null; }");
    Result result = optimize("void", "fun(null);");
    assertNull(result.findClass("EntryPoint$A"));
    assertEquals("test.EntryPoint.fun(Ltest/EntryPoint$A;)Z", result.findMethod("fun").toString());
    assertTrue(result.findMethod("fun").getParams().get(0).getType().isNullType());
  }

  /**
   * Test for issue 2478.
   */
  public void testPrunerThenEqualityNormalizer() throws Exception {
    runDeadCodeElimination = false;
    addSnippetClassDecl("static int foo(int i) { return i; }");

    addSnippetClassDecl("static class UninstantiatedClass { "
        + "int field[]; native int method() /*-{ return 1; }-*/; }");
    addSnippetClassDecl("static UninstantiatedClass uninstantiatedField;");
    Result result;
    (result = optimize("int",
        "int i = 0;",
        "if (uninstantiatedField.field[i] == 0) { i = 2; }",
        "return i;"
    )).intoString(
        "int i = 0;",
        "if (null.nullField[i] == 0) {",
        "  i = 2;",
        "}",
        "return i;"
    );

    EqualityNormalizer.exec(result.getOptimizedProgram());
  }

  public void testInterface() throws Exception {
    runDeadCodeElimination = false;
    addSnippetClassDecl("interface I { int bar(); }");
    addSnippetClassDecl("static class A implements I { public int bar() { return 1; } }");
    Result result =
        optimize("void", "A a = new A(); a.bar();");
    assertNotNull(result.findClass("EntryPoint$I"));
    assertNotNull(result.findClass("EntryPoint$A"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$A"), "bar"));
    assertNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I"), "bar"));
  }

  public void testDefaultInterface() throws Exception {
    runDeadCodeElimination = false;
    addSnippetClassDecl("interface I {default int bar() {return 1;} "
        + "default int foo() {return 1;} }");
    addSnippetClassDecl("static class A implements I { }");
    addSnippetClassDecl("interface I2 {default int foo() {return fun();}"
        + "default int fun() {return 1;}"
        + "default int goo() {return 0;}"
        + "static int s1() { return s2();}"
        + "static int s2() { return 0;}"
        + "static int s3() { return 1;}"
        + "}");
    Result result = optimize("void", "A a = new A(); a.bar(); "
        + "I2 i = new I2() {}; i.foo(); I2.s1();");
    assertNotNull(result.findClass("EntryPoint$A"));
    assertNotNull(result.findClass("EntryPoint$I"));
    assertNotNull(result.findClass("EntryPoint$I2"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I"), "bar"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$A"), "bar"));
    assertNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I"), "foo"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I2"), "foo"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I2"), "fun"));
    assertNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I2"), "goo"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I2"), "s1"));
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I2"), "s2"));
    assertNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$I2"), "s3"));
  }

  public void testPruneParamsAndLocalsInMethodBody() throws Exception {
    runDeadCodeElimination = false;
    addSnippetClassDecl("interface I {default int bar() {int a = 0; return 1;} "
        + "static int fun(int b) {int a = 0; return 1;} }");
    Result result = optimize("void", "I i = new I() {}; i.bar(); I.fun(0);");
    assertNotNull(result.findClass("EntryPoint$I"));
    JMethod bar = OptimizerTestBase.findMethod(result.findClass("EntryPoint$I"), "bar");
    assertNotNull(bar);
    assertEquals("public int bar(){\n" +
        "  0;\n" +
        "  return 1;\n" +
        "}", bar.toSource());
    JMethod fun = OptimizerTestBase.findMethod(result.findClass("EntryPoint$I"), "fun");
    assertNotNull(fun);
    assertEquals("public static int fun(){\n" +
        "  0;\n" +
        "  return 1;\n" +
        "}", fun.toSource());
  }

  public void testJsFunction_notPruneUnusedJsFunction() throws Exception {
    addSnippetImport("jsinterop.annotations.JsFunction");
    addSnippetClassDecl(
        "@JsFunction interface MyJsFunctionInterface {",
        "int foo (int a);",
        "}");
    addSnippetClassDecl(
        "interface MyPlainInterface {",
        "int foo (int a);",
        "}");
    addSnippetClassDecl(
        "@JsFunction interface MyJsFunctionInterfaceUnused {",
        "int foo (int a);",
        "}");
    Result result;
    (result = optimize("void",
        "MyJsFunctionInterface a = new MyJsFunctionInterface() {"
            + "@Override public int foo (int a) { return 1; }"
            + "};"
            + "MyPlainInterface b = new MyPlainInterface() {"
            + "@Override public int foo (int a) { return 1; }"
            + "};"
        )).intoString(
            "new EntryPoint$1();\n" +
            "new EntryPoint$2();"
            );

    assertNotNull(result.findClass("EntryPoint$MyJsFunctionInterface"));
    assertNotNull(result.findClass("EntryPoint$MyPlainInterface"));
    assertNotNull(result.findClass("EntryPoint$MyJsFunctionInterfaceUnused"));

    // Function in JsFunction interface may be implicitly called in JS, should not be pruned.
    assertNotNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$1"), "foo"));
    assertNull(OptimizerTestBase.findMethod(result.findClass("EntryPoint$2"), "foo"));
  }

  public void testJsFunction_unrelatedjsFunctionCast() throws Exception {
    addSnippetImport("jsinterop.annotations.JsFunction");
    addSnippetClassDecl(
        "@JsFunction interface MyJsFunctionInterface {",
        "int foo (int a);",
        "}");
    addSnippetClassDecl(
        "@JsFunction interface MyOtherJsFunctionInterface {",
        "int bar (int a);",
        "}");
    addSnippetClassDecl(
        "interface MyPlainInterface {",
        "int goo (int a);",
        "}");
    Result result;
    (result = optimize("int",
        "MyJsFunctionInterface a = new MyJsFunctionInterface() {"
            + "@Override public int foo (int a) { return 1; }"
            + "};"
            + "return ((MyOtherJsFunctionInterface) a).bar(0) + ((MyPlainInterface) a).goo(0);"
        )).intoString(
            "EntryPoint$MyJsFunctionInterface a = new EntryPoint$1();\n" +
            "return ((EntryPoint$MyOtherJsFunctionInterface) a).bar(0) +" // SAM is not pruned.
            + " ((EntryPoint$MyPlainInterface) a).nullMethod();"
            );

    // JsFunction can be cross casted, or casted from JavaScript function
    // so the JsFunction interface and its SAM function should not be pruned.
    assertNotNull(result.findClass("EntryPoint$MyOtherJsFunctionInterface"));
    assertNotNull(OptimizerTestBase.findMethod(
        result.findClass("EntryPoint$MyOtherJsFunctionInterface"), "bar"));
    assertNull(result.findClass("EntryPoint$MyPlainInterface"));
 }

  @Override
  protected boolean doOptimizeMethod(TreeLogger logger, JProgram program, JMethod method) {
    program.addEntryMethod(findMainMethod(program));
    boolean didChange = false;
    // TODO(jbrosenberg): remove loop when Pruner/CFA interaction is perfect.
    while (Pruner.exec(program, true).didChange()) {
      didChange = true;
    }
    return didChange;
  }
}
