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

library type_mask2_test;

import 'dart:async';
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/types/masks.dart';
import 'package:compiler/src/world.dart' show ClosedWorld;
import '../type_test_helper.dart';

isCheckedMode() {
  try {
    dynamic i = 1;
    // ignore: UNUSED_LOCAL_VARIABLE
    String s = i;
    return false;
  } catch (e) {
    return true;
  }
}

void main() {
  runTests() async {
    await testUnionTypeMaskFlatten();
    await testStringSubtypes();
  }

  asyncTest(() async {
    print('--test from kernel------------------------------------------------');
    await runTests();
  });
}

checkMasks(ClosedWorld closedWorld, List<ClassEntity> allClasses,
    List<FlatTypeMask> masks,
    {FlatTypeMask result,
    List<FlatTypeMask> disjointMasks,
    FlatTypeMask flattened,
    List<ClassEntity> containedClasses}) {
  List<FlatTypeMask> disjoint = <FlatTypeMask>[];
  UnionTypeMask.unionOfHelper(masks, disjoint, closedWorld);
  Expect.listEquals(disjointMasks, disjoint,
      'Unexpected disjoint masks: $disjoint, expected $disjointMasks.');
  if (flattened == null) {
    // We only do the invalid call to flatten in checked mode, as flatten's
    // behaviour in unchecked mode is not defined and thus cannot be
    // reliably tested.
    if (isCheckedMode()) {
      Expect.throws(
          () => UnionTypeMask.flatten(disjoint, closedWorld),
          (e) => e is AssertionError,
          'Expect assertion failure on flattening of $disjoint.');
    }
  } else {
    TypeMask flattenResult = UnionTypeMask.flatten(disjoint, closedWorld);
    Expect.equals(
        flattened,
        flattenResult,
        'Unexpected flattening of $disjoint: '
        '$flattenResult, expected $flattened.');
  }
  dynamic union = UnionTypeMask.unionOf(masks, closedWorld);
  if (result == null) {
    Expect.isTrue(union is UnionTypeMask,
        'Expected union of $masks to be a union-type: $union.');
    Expect.listEquals(
        disjointMasks,
        union.disjointMasks,
        'Unexpected union masks: '
        '${union.disjointMasks}, expected $disjointMasks.');
  } else {
    Expect.equals(
        result, union, 'Unexpected union of $masks: $union, expected $result.');
  }
  if (containedClasses != null) {
    for (ClassEntity cls in allClasses) {
      if (containedClasses.contains(cls)) {
        Expect.isTrue(union.contains(cls, closedWorld),
            'Expected $union to contain $cls.');
      } else {
        Expect.isFalse(union.contains(cls, closedWorld),
            '$union not expected to contain $cls.');
      }
    }
  }
  return union;
}

Future testUnionTypeMaskFlatten() async {
  TypeEnvironment env = await TypeEnvironment.create(r"""
      class A {}
      class B {}
      class C extends A {}
      class D implements A {}
      class E extends B implements A {}
      """, mainSource: r"""
      main() {
        new A();
        new B();
        new C();
        new D();
        new E();
      }
      """);

  ClosedWorld closedWorld = env.closedWorld;

  ClassEntity Object_ = env.getElement("Object");
  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");

  List<ClassEntity> allClasses = <ClassEntity>[Object_, A, B, C, D, E];

  check(List<FlatTypeMask> masks,
      {FlatTypeMask result,
      List<FlatTypeMask> disjointMasks,
      FlatTypeMask flattened,
      List<ClassEntity> containedClasses}) {
    return checkMasks(closedWorld, allClasses, masks,
        result: result,
        disjointMasks: disjointMasks,
        flattened: flattened,
        containedClasses: containedClasses);
  }

  TypeMask empty = const TypeMask.nonNullEmpty();
  TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, closedWorld);
  TypeMask exactA = new TypeMask.nonNullExact(A, closedWorld);
  TypeMask subclassA = new TypeMask.nonNullSubclass(A, closedWorld);
  TypeMask subtypeA = new TypeMask.nonNullSubtype(A, closedWorld);
  TypeMask exactB = new TypeMask.nonNullExact(B, closedWorld);
  TypeMask subclassB = new TypeMask.nonNullSubclass(B, closedWorld);
  TypeMask exactC = new TypeMask.nonNullExact(C, closedWorld);
  TypeMask exactD = new TypeMask.nonNullExact(D, closedWorld);
  TypeMask exactE = new TypeMask.nonNullExact(E, closedWorld);

  check([], result: empty, disjointMasks: [], containedClasses: []);

  check([exactA],
      result: exactA, disjointMasks: [exactA], containedClasses: [A]);

  check([exactA, exactA],
      result: exactA, disjointMasks: [exactA], containedClasses: [A]);

  check([exactA, exactB],
      disjointMasks: [exactA, exactB],
      flattened: subclassObject,
      containedClasses: [A, B]);

  check([subclassObject],
      result: subclassObject,
      disjointMasks: [subclassObject],
      containedClasses: [Object_, A, B, C, D, E]);

  check([subclassObject, exactA],
      disjointMasks: [subclassObject],
      result: subclassObject,
      containedClasses: [Object_, A, B, C, D, E]);

  check([exactA, exactC],
      disjointMasks: [subclassA], result: subclassA, containedClasses: [A, C]);

  check([exactA, exactB, exactC],
      disjointMasks: [subclassA, exactB],
      flattened: subclassObject,
      containedClasses: [A, B, C]);

  check([exactA, exactD],
      disjointMasks: [subtypeA],
      result: subtypeA,
      containedClasses: [A, C, D, E]);

  check([exactA, exactB, exactD],
      disjointMasks: [subtypeA, exactB],
      flattened: subclassObject,
      containedClasses: [A, B, C, D, E]);

  check([exactA, exactE],
      disjointMasks: [subtypeA],
      result: subtypeA,
      containedClasses: [A, C, D, E]);

  check([exactA, exactB, exactE],
      disjointMasks: [subtypeA, exactB],
      flattened: subclassObject,
      containedClasses: [A, B, C, D, E]);

  check([exactB, exactE, exactA],
      disjointMasks: [subclassB, exactA],
      flattened: subclassObject,
      containedClasses: [A, B, E]);

  check([exactE, exactA, exactB],
      disjointMasks: [subtypeA, exactB],
      flattened: subclassObject,
      containedClasses: [A, B, C, D, E]);

  check([exactE, exactB, exactA],
      disjointMasks: [subclassB, exactA],
      flattened: subclassObject,
      containedClasses: [A, B, E]);
}

Future testStringSubtypes() async {
  TypeEnvironment env = await TypeEnvironment.create('', mainSource: r"""
      main() {
        '' is String;
      }
      """);
  ClosedWorld closedWorld = env.closedWorld;

  ClassEntity Object_ = env.getElement("Object");
  ClassEntity String_ = env.getElement("String");
  ClassEntity JSString = closedWorld.commonElements.jsStringClass;

  Expect.isFalse(closedWorld.isDirectlyInstantiated(Object_));
  Expect.isTrue(closedWorld.isIndirectlyInstantiated(Object_));
  Expect.isTrue(closedWorld.isInstantiated(Object_));

  Expect.isFalse(closedWorld.isDirectlyInstantiated(String_));
  Expect.isFalse(closedWorld.isIndirectlyInstantiated(String_));
  Expect.isFalse(closedWorld.isInstantiated(String_));

  Expect.isTrue(closedWorld.isDirectlyInstantiated(JSString));
  Expect.isFalse(closedWorld.isIndirectlyInstantiated(JSString));
  Expect.isTrue(closedWorld.isInstantiated(JSString));

  TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, closedWorld);
  TypeMask exactJSString = new TypeMask.nonNullExact(JSString, closedWorld);
  TypeMask subtypeJSString = new TypeMask.nonNullSubtype(JSString, closedWorld);
  TypeMask subclassJSString =
      new TypeMask.nonNullSubclass(JSString, closedWorld);

  Expect.equals(exactJSString, subtypeString);
  Expect.equals(exactJSString, subtypeJSString);
  Expect.equals(exactJSString, subclassJSString);
}
