// Copyright (c) 2021, the Dart 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.

// SharedOptions=--enable-experiment=constructor-tearoffs

import "package:expect/expect.dart";

import "../static_type_helper.dart";

// Tests that generic methods can be torn off with explicit instantiation.

R toplevel<R, T>(T value, [T? other]) => value as R;

class C {
  static R staticMethod<R, T>(T value, [T? other]) => value as R;
  R instanceMethod<R, T>(T value, [T? other]) => value as R;

  void tearOffsOnThis() {
    const staticTearoff = staticMethod<int, String>;
    staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    this.instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

    Expect.identical(staticMethod<int, String>, staticTearOff);

    Expect.equals(
        instanceMethod<int, String>, this.instanceMethod<int, String>);
  }
}

mixin M on C {
  static R staticMethod<R, T>(T value, [T? other]) => value as R;
  R mixinInstanceMethod<R, T>(T value, [T? other]) => value as R;

  void mixinTearOffsOnThis() {
    const staticTearoff = staticMethod<int, String>;
    staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    mixinInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    this.mixinInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

    Expect.identical(staticMethod<int, String>, staticTearOff);

    Expect.equals(
        mixinInstanceMethod<int, String>,
        this.mixinInstanceMethod<int, String>);
  }
}

extension E on C {
  static R staticMethod<R, T>(T value, [T? other]) => value as R;
  R extInstanceMethod<R, T>(T value, [T? other]) => value as R;

  void extenstionTearOffsOnThis() {
    const staticTearoff = staticMethod<int, String>;
    staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    extInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    this.extInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

    Expect.identical(staticMethod<int, String>, staticTearOff);

    Expect.equals(
        extInstanceMethod<int, String>, this.extInstanceMethod<int, String>);
  }
}

class D extends C with M {
  void tearOffsOnSuper() {
    super.instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    Expect.equals(
        super.instanceMethod<int, String>, super.instanceMethod<int, String>);
  }
}

void main() {
  var o = D();
  R local<R, T>(T value, [T? other]) => value as R;

  // Check that some tear-offs are constant.
  const topTearoff = toplevel<int, String>;
  const staticTearoff = C.staticMethod<int, String>;
  const mixinStaticTearoff = M.staticMethod<int, String>;
  const extensionStaticTearoff = E.staticMethod<int, String>;

  // Check that the tear-offs have the correct static type.

  toplevel<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  C
      .staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  M
      .staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  E
      .staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  c
      .instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  c
      .mixinInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  c
      .extInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  local<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

  // Check that the tear-offs are canonicalized where possible.
  Expect.identical(toplevel<int, String>, topTearoff);
  Expect.identical(C.staticMethod<int, String>, staticTearoff);
  Expect.identical(M.staticMethod<int, String>, mixinStaticTearoff);
  Expect.identical(E.staticMethod<int, String>, extensionStaticTearoff);

  // Instantiated local methods may or may not be equal.
  // (Specification makes no promise about equality.).

  // But not for instance method tear-off.
  // Specification requires equality.
  Expect.equals(
      o.instanceMethod<int, String>, o.instanceMethod<int, String>);
  Expect.equals(
      o.mixinInstanceMethod<int, String>, o.mixinInstanceMethod<int, String>);
  Expect.equals(
      o.extInstanceMethod<int, String>, o.extInstanceMethod<int, String>);

  // And not canonicalized where they shouldn't (different types).
  Expect.notEquals(toplevel<int, String>, toplevel<num, String>);
  Expect.notEquals(
      C.staticMethod<int, String>, C.staticMethod<num, String>);
  Expect.notEquals(local<int, String>, local<num, String>);
  Expect.notEquals(
      o.instanceMethod<int, String>, o.instanceMethod<num, String>);

  (<T>() {
    // Not canonicalized if any type is non-constant.
    // Toplevel, static and instance members are still equal
    // if types are "the same".
    // (Current implementations do not implement that).
    Expect.equals(toplevel<T, String>, toplevel<T, String>);
    Expect.equals(C.staticMethod<T, String>, C.staticMethod<T, String>);
    Expect.equals(M.staticMethod<T, String>, M.staticMethod<T, String>);
    Expect.equals(E.staticMethod<T, String>, E.staticMethod<T, String>);
    Expect.notEquals(local<T, String>, local<T, String>);
    Expect.equals(toplevel<int, T>, toplevel<int, T>);
    Expect.equals(C.staticMethod<int, T>, C.staticMethod<int, T>);
    Expect.equals(M.staticMethod<int, T>, M.staticMethod<int, T>);
    Expect.equals(E.staticMethod<int, T>, E.staticMethod<int, T>);
    Expect.notEquals(local<int, T>, local<int, T>);
  }<int>());

  o.tearOffsOnThis();
  o.tearOffOnSuper();
  o.mixinTearOffOnThis();
  o.extensionTearOffOnThis();
}
