/*
 * Copyright 2008 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.UnableToCompleteException;
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Tests {@link ControlFlowAnalyzer}.
 */
public class ControlFlowAnalyzerTest extends JJSTestBase {

  /**
   * Answers predicates about an analyzed program.
   */
  private static final class Result {
    private final ControlFlowAnalyzer cfa;
    private final JProgram program;

    public Result(JProgram program, ControlFlowAnalyzer cfa) {
      this.program = program;
      this.cfa = cfa;
    }

    public void assertOnlyFieldsWritten(String... expectedFields) {
      Set<JField> expectedSet = new HashSet<JField>();
      for (String expectedField : expectedFields) {
        JField field = findField(program, expectedField);
        assertNotNull(field);
        expectedSet.add(field);
      }
      assertEquals(expectedSet, cfa.getFieldsWritten());
    }

    public void assertOnlyInstantiatedTypes(String... expectedTypes) {
      Set<JType> expectedSet = Sets.newHashSet();
      for (String expectedType : expectedTypes) {
        JType type = findType(program, expectedType);
        assertNotNull(type);
        expectedSet.add(type);
      }
      assertEquals(expectedSet, cfa.getInstantiatedTypes());
    }

    public void assertOnlyLiveFieldsAndMethods(String... expected) {
      Set<JNode> expectedSet = new HashSet<JNode>();
      for (String expectedRef : expected) {
        JField field = findField(program, expectedRef);
        if (field != null) {
          expectedSet.add(field);
        } else {
          JMethod method = findQualifiedMethod(program, expectedRef);
          assertNotNull(method);
          expectedSet.add(method);
        }
      }
      assertEquals(expectedSet, cfa.getLiveFieldsAndMethods());
    }

    public void assertOnlyLiveStrings(String... expectedStrings) {
      Set<String> expectedSet = new HashSet<String>();
      Collections.addAll(expectedSet, expectedStrings);
      cfa.getLiveStrings();
      assertEquals(expectedSet, cfa.getLiveStrings());
    }
  }

  /**
   * Tests properties of an empty program.
   */
  public void testEmpty() throws Exception {
    Result result = analyzeSnippet("");
    result.assertOnlyFieldsWritten(Empty.STRINGS);
    result.assertOnlyInstantiatedTypes(Empty.STRINGS);
    result.assertOnlyLiveStrings(Empty.STRINGS);
  }

  /**
   * Tests that the JavaScriptObject type gets rescued in the three specific
   * circumstances where values can pass from JS into Java.
   */
  public void testRescueJavaScriptObjectFromJsni() throws Exception {
    addJsoResources();
    addOrReplaceResource("test.VirtualUpRef",
        "package test;",
        "import com.google.gwt.core.client.JavaScriptObject;",
        "final public class VirtualUpRef extends NonImplementor implements UpRefIntf {",
        "  protected VirtualUpRef() {}",
        "  public static native VirtualUpRef create() /*-{ return  {}; }-*/;",
        "}");
    addOrReplaceResource("test.Foo",
        "package test;",
        "import com.google.gwt.core.client.JavaScriptObject;",
        "public class Foo {",
        "  public static native JavaScriptObject returnsJso() /*-{ return {}; }-*/;",
        "  public static native void assignsJsoField() /*-{ @test.Foo::jsoField = {}; }-*/;",
        "  public static native void readsJsoField() /*-{ var x = @test.Foo::jsoField; }-*/;",
        "  public static native void passesJsoParam() /*-{ @test.Foo::calledFromJsni(Lcom/google/gwt/core/client/JavaScriptObject;)({}); }-*/;",
        "  private static JavaScriptObject jsoField = null;",
        "  private static void calledFromJsni(JavaScriptObject arg) { }",
        "  public static native JsoIntf returnsJsoIntf() /*-{ return {}; }-*/;",
        "  public static native SingleJso returnsSingleJso() /*-{ return {}; }-*/;",
        "}");
    addSnippetImport("test.Foo");

    analyzeSnippet("").assertOnlyInstantiatedTypes(Empty.STRINGS);

    // Returning a JSO from a JSNI method rescues.
    analyzeSnippet("Foo.returnsJso();").assertOnlyInstantiatedTypes(
        "JavaScriptObject", "Object");

    // Assigning into a JSO field from a JSNI method rescues.
    analyzeSnippet("Foo.assignsJsoField();").assertOnlyInstantiatedTypes(
        "JavaScriptObject", "Object");

    // Passing from Java to JS via a JSNI field read should NOT rescue.
    analyzeSnippet("Foo.readsJsoField();").assertOnlyInstantiatedTypes(
        Empty.STRINGS);

    // Passing a parameter from JS to Java rescues.
    analyzeSnippet("Foo.passesJsoParam();").assertOnlyInstantiatedTypes(
        "JavaScriptObject", "Object");

    // Returning a JSO subType instantiates it
    analyzeSnippet("Foo.returnsSingleJso();").assertOnlyInstantiatedTypes(
        "SingleJso", "JavaScriptObject", "Object", "JsoIntf");

    // Returning a JSO SingleJsoImpl instantiates it and the implementor
    analyzeSnippet("Foo.returnsJsoIntf();").assertOnlyInstantiatedTypes(
        "SingleJso", "JavaScriptObject", "Object", "JsoIntf");

    // A virtual upref should still be rescued
    analyzeSnippet("VirtualUpRef.create().getFoo();").assertOnlyInstantiatedTypes(
        "VirtualUpRef", "NonImplementor", "JavaScriptObject", "Object", "UpRefIntf");

    // and its methods
    analyzeSnippet("VirtualUpRef.create().getFoo();").assertOnlyLiveFieldsAndMethods(
        "VirtualUpRef.$clinit", "VirtualUpRef.create", "VirtualUpRef.getFoo",
        "NonImplementor.$clinit","NonImplementor.getFoo",
        "UpRefIntf.$clinit",
        "JavaScriptObject.$clinit",
        "EntryPoint.$clinit",
        "EntryPoint.onModuleLoad",
        "Object.$clinit");
  }

  /**
   * Tests that certain Java arrays are rescued if returned from JSNI code. Arrays that are rescued
   * if returned from JSNI: code whose leaf types are either primitive or types that might be
   * instantiated in JSNI.
   */
  public void testRescueArraysFromJSNI() throws Exception {
    addOrReplaceResource("test.Foo",
        "package test;", "public class Foo {",
        "  public static native int[] create_array() /*-{ return {}; }-*/;",
        "  public static native int[][] create_2d_array() /*-{ return {}; }-*/;",
        "}");
    addSnippetImport("test.Foo");

    analyzeSnippet("").assertOnlyInstantiatedTypes(Empty.STRINGS);

    // Returning a JSO from a JSNI method rescues.
    analyzeSnippet("Foo.create_array();").assertOnlyInstantiatedTypes(
        "int[]", "Object");

    // Returning a JSO from a JSNI method rescues.
    analyzeSnippet("Foo.create_2d_array();").assertOnlyInstantiatedTypes(
        "int[][]", "Object[]", "Object");
  }

  public void testRescueJavaScriptObjectReturnedFromExternallyImplementedMethod() throws Exception {
    addJsoResources();
    addSnippetImport("test.Test");

    addOrReplaceResource("test.Test",
        "package test;",
        "import jsinterop.annotations.JsMethod;",
        "public class Test {",
        "  @JsMethod",
        "  public static native JsoIntf returnsJsoInterface();",
        "}"
    );
    analyzeSnippet("Test.returnsJsoInterface();").assertOnlyInstantiatedTypes(
        "JsoIntf", "SingleJso", "JavaScriptObject", "Object");

    addOrReplaceResource("test.Test",
        "package test;",
        "import jsinterop.annotations.JsMethod;",
        "public class Test {",
        "  @JsMethod",
        "  public static native SingleJso returnsJso();",
        "}"
    );
    analyzeSnippet("Test.returnsJso();").assertOnlyInstantiatedTypes(
        "JsoIntf", "SingleJso", "JavaScriptObject", "Object");
  }

  public void testRescueJavaScriptObjectParameterToJsInteropEntryPoint() throws Exception {
    addJsoResources();
    addSnippetImport("test.Test");

    addOrReplaceResource("test.Test",
        "package test;",
        "import jsinterop.annotations.JsMethod;",
        "public class Test {",
        "  public static void receivesJsoInterface(JsoIntf i) {};",
        "}"
    );
    analyzeSnippet("Test.receivesJsoInterface(null);").assertOnlyInstantiatedTypes(
        Empty.STRINGS);

    addOrReplaceResource("test.Test",
        "package test;",
        "import jsinterop.annotations.JsMethod;",
        "public class Test {",
        "  @JsMethod",
        "  public static void receivesJsoInterface(JsoIntf i) {};",
        "}"
    );
    analyzeSnippet("Test.receivesJsoInterface(null);").assertOnlyInstantiatedTypes(
        "JsoIntf", "SingleJso", "JavaScriptObject", "Object");
  }

    /**
     * Tests that the JavaScriptObject type gets rescued in the three specific
     * circumstances where values can pass from JS into Java.
     */
  public void testRescueJavaScriptObjectReturnedFromFieldReference() throws Exception {
    addJsoResources();
    addSnippetImport("test.Test");

    addOrReplaceResource("test.Test",
        "package test;",
        "import jsinterop.annotations.JsType;",
        "@JsType(isNative = true)",
        "public class Test {",
        "  public static JsoIntf field;",
        "}"
    );
    analyzeSnippet("Test.field.hashCode();").assertOnlyInstantiatedTypes(
        "JsoIntf", "SingleJso", "JavaScriptObject", "Object",
        // These are all live because of the method Test.toString can be referenced externally.
        "String", "Comparable", "CharSequence", "Serializable");

    addOrReplaceResource("test.Test",
        "package test;",
        "import jsinterop.annotations.JsType;",
        "@JsType(isNative = true)",
        "public class Test {",
        "  public static SingleJso field;",
        "}"
    );
    analyzeSnippet("Test.field.hashCode();").assertOnlyInstantiatedTypes(
        "JsoIntf", "SingleJso", "JavaScriptObject", "Object",
        // These are all live because of the method Test.toString can be referenced externally.
        "String", "Comparable", "CharSequence", "Serializable");
  }

  private void addOrReplaceResource(String qualifiedTypeName, final String... source) {
    sourceOracle.addOrReplace(
        new MockJavaResource(qualifiedTypeName) {
          @Override
          public CharSequence getContent() {
            return Joiner.on("\n").join(source);
          }
        });
    }

  private void addJsoResources() {
    addOrReplaceResource("test.JsoIntf",
        "package test;",
        "import com.google.gwt.core.client.JavaScriptObject;",
        "public interface JsoIntf {",
        "  public int getAny();",
        "}");
    addOrReplaceResource("test.UpRefIntf",
        "package test;",
        "import com.google.gwt.core.client.JavaScriptObject;",
        "public interface UpRefIntf {",
        "  public int getFoo();",
        "}");
    addOrReplaceResource("test.NonImplementor",
        "package test;",
        "import com.google.gwt.core.client.JavaScriptObject;",
        "public class NonImplementor extends JavaScriptObject {",
        "  protected NonImplementor() {}",
        "  final public native int getFoo() /*-{ return 0; }-*/;",
        "}");
    addOrReplaceResource("test.SingleJso",
        "package test;",
        "import com.google.gwt.core.client.JavaScriptObject;",
        "final public class SingleJso extends JavaScriptObject implements JsoIntf {",
        "  protected SingleJso() {}",
        "  public native int getAny() /*-{ return 1; }-*/;",
        "}");
  }

  private Result analyzeSnippet(String codeSnippet)
      throws UnableToCompleteException {
    JProgram program = compileSnippet("void", codeSnippet, true);
    ControlFlowAnalyzer cfa = new ControlFlowAnalyzer(program);
    cfa.traverseFrom(findMainMethod(program));
    return new Result(program, cfa);
  }

}
