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

library type_substitution_test;

import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/types.dart';
import '../helpers/type_test_helper.dart';

DartType getType(ElementEnvironment elementEnvironment, String name) {
  ClassEntity cls =
      elementEnvironment.lookupClass(elementEnvironment.mainLibrary, 'Class');
  FunctionEntity element = elementEnvironment.lookupClassMember(cls, name);
  Expect.isNotNull(element);
  FunctionType type = elementEnvironment.getFunctionType(element);

  // Function signatures are used to be to provide void types (only occurring as
  // as return types) and (inlined) function types (only occurring as method
  // parameter types).
  //
  // Only a single type is used from each signature. That is, it is not the
  // intention to check the whole signatures against eachother.
  if (type.parameterTypes.isEmpty) {
    // If parameters is empty, use return type.
    return type.returnType;
  } else {
    // Otherwise use the first argument type.
    return type.parameterTypes.first;
  }
}

void main() {
  asyncTest(() async {
    await testAsInstanceOf();
    await testTypeSubstitution();
  });
}

testAsInstanceOf() async {
  var env = await TypeEnvironment.create('''
      class A<T> {}
      class B<T> {}
      class C<T> extends A<T> {}
      class D<T> extends A<int> {}
      class E<T> extends A<A<T>> {}
      class F<T, U> extends B<F<T, String>> implements A<F<B<U>, int>> {}

      main() {
        new A();
        new B();
        new C();
        new D();
        new E();
        new F();
      }
      ''');
  var types = env.types;
  ClassEntity A = env.getElement("A");
  ClassEntity B = env.getElement("B");
  ClassEntity C = env.getElement("C");
  ClassEntity D = env.getElement("D");
  ClassEntity E = env.getElement("E");
  ClassEntity F = env.getElement("F");

  DartType intType = env['int'];
  DartType stringType = env['String'];

  InterfaceType C_int = env.instantiate(C, [intType]);
  Expect.equals(env.instantiate(C, [intType]), C_int);
  Expect.equals(env.instantiate(A, [intType]), types.asInstanceOf(C_int, A));

  InterfaceType D_int = env.instantiate(D, [stringType]);
  Expect.equals(env.instantiate(A, [intType]), types.asInstanceOf(D_int, A));

  InterfaceType E_int = env.instantiate(E, [intType]);
  Expect.equals(
      env.instantiate(A, [
        env.instantiate(A, [intType])
      ]),
      types.asInstanceOf(E_int, A));

  InterfaceType F_int_string = env.instantiate(F, [intType, stringType]);
  Expect.equals(
      env.instantiate(B, [
        env.instantiate(F, [intType, stringType])
      ]),
      types.asInstanceOf(F_int_string, B));
  Expect.equals(
      env.instantiate(A, [
        env.instantiate(F, [
          env.instantiate(B, [stringType]),
          intType
        ])
      ]),
      types.asInstanceOf(F_int_string, A));
}

/**
 * Test that substitution of [parameters] by [arguments] in the type found
 * through [name1] is the same as the type found through [name2].
 */
void testSubstitution(
    DartTypes dartTypes,
    ElementEnvironment elementEnvironment,
    List<DartType> arguments,
    List<DartType> parameters,
    DartType type1,
    DartType type2) {
  DartType subst = dartTypes.subst(arguments, parameters, type1);
  Expect.equals(
      type2, subst, "$type1.subst($arguments,$parameters)=$subst != $type2");
}

testTypeSubstitution() async {
  var env = await TypeEnvironment.create(r"""
      class Class<T,S> {}

      main() => new Class();
      """);
  var types = env.types;
  InterfaceType Class_T_S = env["Class"];
  Expect.isNotNull(Class_T_S);
  Expect.isTrue(Class_T_S is InterfaceType);
  Expect.equals(2, Class_T_S.typeArguments.length);

  DartType T = Class_T_S.typeArguments[0];
  Expect.isNotNull(T);
  Expect.isTrue(T is TypeVariableType);

  DartType S = Class_T_S.typeArguments[1];
  Expect.isNotNull(S);
  Expect.isTrue(S is TypeVariableType);

  DartType intType = env['int'];
  Expect.isNotNull(intType);
  Expect.isTrue(intType is InterfaceType);

  DartType StringType = env['String'];
  Expect.isNotNull(StringType);
  Expect.isTrue(StringType is InterfaceType);

  ClassEntity ListClass = env.getElement('List');
  ClassEntity MapClass = env.getElement('Map');

  List<DartType> parameters = <DartType>[T, S];
  List<DartType> arguments = <DartType>[intType, StringType];

  testSubstitution(types, env.elementEnvironment, arguments, parameters,
      types.voidType(), types.voidType());
  testSubstitution(types, env.elementEnvironment, arguments, parameters,
      types.dynamicType(), types.dynamicType());
  testSubstitution(
      types, env.elementEnvironment, arguments, parameters, intType, intType);
  testSubstitution(types, env.elementEnvironment, arguments, parameters,
      StringType, StringType);
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(ListClass, [intType]),
      env.instantiate(ListClass, [intType]));
  testSubstitution(types, env.elementEnvironment, arguments, parameters,
      env.instantiate(ListClass, [T]), env.instantiate(ListClass, [intType]));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(ListClass, [S]),
      env.instantiate(ListClass, [StringType]));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(ListClass, [
        env.instantiate(ListClass, [T])
      ]),
      env.instantiate(ListClass, [
        env.instantiate(ListClass, [intType])
      ]));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(ListClass, [types.dynamicType()]),
      env.instantiate(ListClass, [types.dynamicType()]));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(MapClass, [intType, StringType]),
      env.instantiate(MapClass, [intType, StringType]));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(MapClass, [T, StringType]),
      env.instantiate(MapClass, [intType, StringType]));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      env.instantiate(MapClass, [types.dynamicType(), StringType]),
      env.instantiate(MapClass, [types.dynamicType(), StringType]));
  testSubstitution(
      types, env.elementEnvironment, arguments, parameters, T, intType);
  testSubstitution(
      types, env.elementEnvironment, arguments, parameters, S, StringType);
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      types.functionType(intType, [StringType], [], [], {}, [], []),
      types.functionType(intType, [StringType], [], [], {}, [], []));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      types.functionType(types.voidType(), [T, S], [], [], {}, [], []),
      types.functionType(
          types.voidType(), [intType, StringType], [], [], {}, [], []));
  testSubstitution(
      types,
      env.elementEnvironment,
      arguments,
      parameters,
      types.functionType(
          types.voidType(), [types.dynamicType()], [], [], {}, [], []),
      types.functionType(
          types.voidType(), [types.dynamicType()], [], [], {}, [], []));
}
