// Copyright (c) 2017, 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.

// @dart = 2.9
import 'package:expect/expect.dart';

class Fields<T> {
  T x;
  T _y;
  T _z;

  m() {
    _y = x;
  }

  n(Fields<T> c) {
    c._z = x;
  }
}

testField() {
  Fields<Object> c = new Fields<int>();
  Expect.throwsTypeError(() => c.x = 'hello');

  Fields<dynamic> d = new Fields<int>();
  Expect.throwsTypeError(() => c.x = 'hello');
}

testPrivateFields() {
  Fields<Object> c = new Fields<int>()..x = 42;
  c.m();
  Expect.equals(c._y, 42);

  Fields<Object> c2 = new Fields<String>()..x = 'hi';
  c2.n(c2);
  Expect.equals(c2._z, 'hi');
  Expect.throwsTypeError(() => c.n(c2));
  Expect.equals(c2._z, 'hi');
}

class NumBounds<T extends num> {
  bool m(T t) => t.isNegative;
}

class MethodTakesNum extends NumBounds<int> {
  bool m(num obj) => obj.isNegative; // does not need check
}

class MethodTakesInt extends NumBounds<int> {
  bool m(int obj) => obj.isNegative; // needs a check
}

testClassBounds() {
  NumBounds<num> d = new MethodTakesNum();
  Expect.equals(d.m(-1.1), true);
  d = new MethodTakesInt();
  Expect.throwsTypeError(() => d.m(-1.1));
}

typedef void F<T>(T t);
typedef G<T> = void Function<S extends T>(S s);

class FnChecks<T> {
  F<T> f;
  G<T> g;
  T _t;
  T getT() => _t;
  F<T> setterForT() {
    return (T t) {
      _t = t;
    };
  }
}

testReturnOfFunctionType() {
  FnChecks<int> cInt = new FnChecks<int>();
  FnChecks<Object> cObj = cInt;
  Expect.throwsTypeError(() => cObj.setterForT());
  Expect.throwsTypeError(() => (cObj.setterForT() as F<Object>));
  FnChecks<dynamic> cDyn = cInt;
  Expect.throwsTypeError(() => cDyn.setterForT());
  Expect.throwsTypeError(
      () => (cDyn as dynamic).setterForT()('hi')); // dcall throws
  cInt.setterForT()(42);
  Expect.equals(cObj.getT(), 42);
}

testTearoffReturningFunctionType() {
  FnChecks<int> cInt = new FnChecks<int>();
  FnChecks<Object> cObj = cInt;

  Expect.throwsTypeError(
      () => cObj.setterForT, 'unsound tear-off throws at runtime');
  Expect.equals(cInt.setterForT, cInt.setterForT, 'sound tear-off works');
}

testFieldOfFunctionType() {
  FnChecks<Object> c = new FnChecks<String>()..f = (String b) {};
  Expect.throwsTypeError(() {
    F<Object> f = c.f;
  });
  Expect.throwsTypeError(() {
    Object f = c.f;
  });
  Expect.throwsTypeError(() => c.f);
  Expect.throwsTypeError(() => c.f(42));
  Expect.throwsTypeError(() => c.f('hi'));
  FnChecks<String> cStr = c;
  cStr.f('hi');
  FnChecks<dynamic> cDyn = c;
  Expect.throwsTypeError(() => cDyn.f);
  Expect.throwsTypeError(() => (cDyn as dynamic).f(42)); // dcall throws
}

testFieldOfGenericFunctionType() {
  FnChecks<Object> c = new FnChecks<num>()
    ..g = <S extends num>(S s) => s.isNegative;

  Expect.throwsTypeError(() {
    G<Object> g = c.g;
  });
  Expect.throwsTypeError(() {
    var g = c.g;
  });
  Expect.throwsTypeError(() => c.g<String>('hi'));
  Expect.throwsTypeError(() => c.g<int>(42));
  FnChecks<num> cNum = c;
  cNum.g(42);
}

class Base {
  int _t = 0;
  add(int t) {
    _t += t;
  }
}

abstract class I<T> {
  add(T t);
}

class ExtendsBase extends Base implements I<int> {}

class MixinBase extends Object with Base implements I<int> {}

class MixinBase2 = Object with Base implements I<int>;

testMixinApplication() {
  I<Object> i = new ExtendsBase();
  I<Object> j = new MixinBase();
  I<Object> k = new MixinBase2();
  Expect.throwsTypeError(() => i.add('hi'));
  Expect.throwsTypeError(() => j.add('hi'));
  Expect.throwsTypeError(() => k.add('hi'));
}

class GenericMethodBounds<T> {
  Type get t => T;
  GenericMethodBounds<E> foo<E extends T>() => new GenericMethodBounds<E>();
  GenericMethodBounds<E> bar<E extends void Function(T)>() =>
      new GenericMethodBounds<E>();
}

class GenericMethodBoundsDerived extends GenericMethodBounds<num> {
  GenericMethodBounds<E> foo<E extends num>() => new GenericMethodBounds<E>();
  GenericMethodBounds<E> bar<E extends void Function(num)>() =>
      new GenericMethodBounds<E>();
}

GenericMethodBounds<E> Function<E extends T>() genericFunctionWithBounds<T>() {
  inner<E extends T>() => new GenericMethodBounds<E>();
  return inner;
}

testGenericMethodBounds() {
  test(GenericMethodBounds<Object> g) {
    Expect.throwsTypeError(() => g.foo<String>());
    Expect.throwsTypeError(() => g.foo());
    Expect.equals(g.foo<Null>().t, Null);
    Expect.equals(g.foo<int>().t, int);
    Expect.isFalse(g.foo<int>() is GenericMethodBounds<double>);
    g.bar<Function(Object)>();
    dynamic d = g;
    d.bar<Function(num)>();
    Expect.throwsTypeError(() => d.bar<Function(String)>());
    Expect.throwsTypeError(() => d.bar<Function(Null)>());
  }

  test(new GenericMethodBounds<num>());
  test(new GenericMethodBounds<int>());
  test(new GenericMethodBoundsDerived());
  test(genericFunctionWithBounds<num>()<int>());
}

class ClassF<T> {
  T x;
  void call(T t) {
    x = t;
  }
}

testCallMethod() {
  ClassF<int> cc = new ClassF<int>();
  ClassF<Object> ca = cc; // An upcast, per covariance.
  F<Object> f = ca;
  void f2(Object x) {}
  Expect.equals(f.runtimeType, f2.runtimeType);
  Expect.throwsTypeError(() => f(new Object()));
}

class TearOff<T> {
  method1(T t) => null; // needs check
  method2(Function(T) takesT) => null;
  method3(T Function() returnsT) => null; // needs check
  method4(Function(Function(T)) takesTakesT) => null; // needs check
  method5(Function(T Function()) takesReturnsT) => null;
  method6(Function(T) Function() returnsTakesT) => null;
  method7(T Function() Function() returnsReturnsT) => null; // needs check
}

typedef F1 = dynamic Function(Object);
typedef F2 = dynamic Function(dynamic Function(int));
typedef F3 = dynamic Function(dynamic Function(int Function()));
typedef F4 = dynamic Function(dynamic Function(int) Function());

testTearOffRuntimeType() {
  expectRTTI(tearoff, type) => Expect.equals(tearoff.runtimeType, type,
      'covariant params should reify with Object as their type');

  TearOff<num> t = new TearOff<int>();
  expectRTTI(t.method1, F1);

  expectRTTI(t.method2, F2);
  expectRTTI(t.method3, F1);

  expectRTTI(t.method4, F1);
  expectRTTI(t.method5, F3);
  expectRTTI(t.method6, F4);
  expectRTTI(t.method7, F1);
}

main() {
  testField();
  testPrivateFields();
  testClassBounds();
  testReturnOfFunctionType();
  testTearoffReturningFunctionType();
  testFieldOfFunctionType();
  testFieldOfGenericFunctionType();
  testMixinApplication();
  testGenericMethodBounds();
  testCallMethod();
  testTearOffRuntimeType();
}
