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

/*element: A.:[subclass=B]*/
abstract class A {
  /*element: A.noSuchMethod:[exact=JSUInt31]*/
  noSuchMethod(
          /*strong.[null|subclass=Object]*/
          /*omit.[null|exact=JSInvocationMirror]*/
          im) =>
      42;
}

/*element: B.:[exact=B]*/
class B extends A {
  /*element: B.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
  foo() => {};
}

/*element: C.:[exact=C]*/
class C extends B {
  /*element: C.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
  foo() => {};
}

/*element: D.:[exact=D]*/
class D implements A {
  /*element: D.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
  foo() => {};

  /*element: D.noSuchMethod:[exact=JSDouble]*/
  noSuchMethod(
          /*strong.[null|subclass=Object]*/
          /*omit.[null|exact=JSInvocationMirror]*/
          im) =>
      42.5;
}

/*element: a:Union([exact=D], [null|subclass=B])*/
dynamic a = [new B(), new C(), new D()]
    /*Container([exact=JSExtendableArray], element: Union([exact=D], [subclass=B]), length: 3)*/
    [0];

/*element: test1:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test1() => a. /*invoke: Union([exact=D], [null|subclass=B])*/ foo();

/*element: test2:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test2() => new B(). /*invoke: [exact=B]*/ foo();

/*element: test3:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test3() => new C(). /*invoke: [exact=C]*/ foo();

/*element: test4:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test4() => (a ? new B() : new C()). /*invoke: [subclass=B]*/ foo();

/*element: test5:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test5() {
  dynamic e = (a ? new B() : new D());
  return e. /*invoke: Union([exact=B], [exact=D])*/ foo();
}

// Can hit A.noSuchMethod, D.noSuchMethod and Object.noSuchMethod.
/*element: test6:Union([exact=JSDouble], [exact=JSUInt31])*/
test6() => a. /*invoke: Union([exact=D], [null|subclass=B])*/ bar();

// Can hit A.noSuchMethod.
/*element: test7:[exact=JSUInt31]*/
test7() {
  dynamic e = new B();
  return e. /*invoke: [exact=B]*/ bar();
}

/*element: test8:[exact=JSUInt31]*/
test8() {
  dynamic e = new C();
  return e. /*invoke: [exact=C]*/ bar();
}

/*element: test9:[exact=JSUInt31]*/
test9() {
  dynamic e = (a ? new B() : new C());
  return e. /*invoke: [subclass=B]*/ bar();
}

// Can hit A.noSuchMethod and D.noSuchMethod.
/*element: test10:Union([exact=JSDouble], [exact=JSUInt31])*/
test10() {
  dynamic e = (a ? new B() : new D());
  return e. /*invoke: Union([exact=B], [exact=D])*/ bar();
}

// Can hit D.noSuchMethod.
/*element: test11:[exact=JSDouble]*/
test11() {
  dynamic e = new D();
  return e. /*invoke: [exact=D]*/ bar();
}

/*element: main:[null]*/
main() {
  test1();
  test2();
  test3();
  test4();
  test5();
  test6();
  test7();
  test8();
  test9();
  test10();
  test11();
}
