/*
 * Copyright 2019 The Closure Compiler Authors.
 *
 * 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.javascript.jscomp;

import static com.google.javascript.jscomp.Es6ToEs3Util.CANNOT_CONVERT_YET;

import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link RewriteNewDotTarget}. */
@RunWith(JUnit4.class)
@SuppressWarnings("RhinoNodeGetFirstFirstChild")
public class RewriteNewDotTargetTest extends CompilerTestCase {

  @Before
  public void enableTypeCheckBeforePass() {
    enableTypeCheck();
    enableTypeInfoValidation();
  }

  @Override
  protected CompilerPass getProcessor(Compiler compiler) {
    return new RewriteNewDotTarget(compiler);
  }

  @Override
  protected CompilerOptions getOptions() {
    CompilerOptions options = super.getOptions();
    options.setLanguageIn(LanguageMode.ECMASCRIPT_NEXT_IN);
    options.setLanguageOut(LanguageMode.ECMASCRIPT5_STRICT);
    return options;
  }

  @Test
  public void testNewTargetInNonConstructorMethod() {
    testError(
        lines(
            "", //
            "/** @constructor */",
            "function Foo() { new.target; }", // not an ES6 class constructor
            ""),
        CANNOT_CONVERT_YET);

    testError(
        "function foo() { new.target; }", // not a constructor at all
        CANNOT_CONVERT_YET);

    testError(
        lines(
            "", //
            "class Foo {",
            "  method() {", // not a constructor
            "    new.target;",
            "  }",
            "}",
            ""),
        CANNOT_CONVERT_YET);
  }

  @Test
  public void testNewTargetInEs6Constructor() {
    test(
        lines(
            "", //
            "class Foo {",
            "  constructor() {",
            "    new.target;",
            "    () => new.target;", // works in arrow functions, too
            "  }",
            "}",
            ""),
        lines(
            "", //
            "class Foo {",
            "  constructor() {",
            "    this.constructor;",
            "    () => this.constructor;", // works in arrow functions, too
            "  }",
            "}",
            ""));
  }
}

@@ -2780,11 +2780,1314 @@
 %22));%0A  %7D
+%0A%0A  @Test%0A  public void testNewTargetInEs6Constructor_superCtorReturnsObject() %7B%0A    // TODO(b/157140030): This is an unexpected behaviour change.%0A    test(%0A        lines(%0A            %22/** @constructor */%22,%0A            %22function Base() %7B%22,%0A            %22  return %7B%7D;%22,%0A            %22%7D%22,%0A            %22%22,%0A            %22class Child extends Base %7B%22,%0A            %22  constructor() %7B%22,%0A            %22    super();%22,%0A            %22    new.target;%22, // Child%0A            %22  %7D%22,%0A            %22%7D%22),%0A        lines(%0A            %22/** @constructor */%22,%0A            %22function Base() %7B%22,%0A            %22  return %7B%7D;%22,%0A            %22%7D%22,%0A            %22%22,%0A            %22class Child extends Base %7B%22,%0A            %22  constructor() %7B%22,%0A            %22    super();%22,%0A            %22    this.constructor;%22, // Object%0A            %22  %7D%22,%0A            %22%7D%22));%0A  %7D%0A%0A  @Test%0A  public void testNewTargetInEs6Constructor_beforeSuper() %7B%0A    test(%0A        lines(%0A            %22class Foo extends Object %7B%22,%0A            %22  constructor() %7B%22,%0A            %22    new.target;%22,%0A            %22    super();%22,%0A            %22  %7D%22,%0A            %22%7D%22),%0A        lines(%0A            %22class Foo extends Object %7B%22,%0A            %22  constructor() %7B%22,%0A            %22    this.constructor;%22, // %60this%60 before %60super%60%0A            %22    super();%22,%0A            %22  %7D%22,%0A            %22%7D%22));%0A  %7D
 %0A%7D%0A

Add more tests for `RewriteNewTarget` documenting some issues.