library test;
import self as self;
import "dart:core" as core;

typedef Asserter<T extends core::Object = dynamic> = (T) → void;
typedef AsserterBuilder<S extends core::Object = dynamic, T extends core::Object = dynamic> = (S) → (T) → void;
class DartType extends core::Object {
  synthetic constructor •() → void
    : super core::Object::•()
    ;
}
abstract class C extends core::Object {
  static field (core::List<(self::DartType) → void>) → (self::DartType) → void assertBOf = null;
  field (core::List<(self::DartType) → void>) → (self::DartType) → void assertAOf = null;
  synthetic constructor •() → void
    : super core::Object::•()
    ;
  static get assertCOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void
    return null;
  abstract get assertDOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void;
  method method((core::List<(self::DartType) → void>) → (self::DartType) → void assertEOf) → dynamic {
    this.assertAOf(<dynamic>[self::_isInt, self::_isString]);
    self::C::assertBOf.call(<dynamic>[self::_isInt, self::_isString]);
    self::C::assertCOf.call(<dynamic>[self::_isInt, self::_isString]);
    this.{self::C::assertDOf}(<dynamic>[self::_isInt, self::_isString]);
    assertEOf.call(<dynamic>[self::_isInt, self::_isString]);
  }
}
abstract class G<T extends core::Object = dynamic> extends core::Object {
  field (core::List<(self::DartType) → void>) → (self::DartType) → void assertAOf = null;
  synthetic constructor •() → void
    : super core::Object::•()
    ;
  abstract get assertDOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void;
  method method((core::List<(self::DartType) → void>) → (self::DartType) → void assertEOf) → dynamic {
    this.assertAOf(<dynamic>[self::_isInt, self::_isString]);
    this.{self::G::assertAOf}(<dynamic>[self::_isInt, self::_isString]);
    this.{self::G::assertDOf}(<dynamic>[self::_isInt, self::_isString]);
    assertEOf.call(<dynamic>[self::_isInt, self::_isString]);
  }
}
static field (self::DartType) → void _isInt;
static field (self::DartType) → void _isString;
static field (core::List<(self::DartType) → void>) → (self::DartType) → void assertBOf;
static get assertCOf() → (core::List<(self::DartType) → void>) → (self::DartType) → void
  return null;
static method test() → dynamic {
  (core::List<(self::DartType) → void>) → (self::DartType) → void assertAOf;
  assertAOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::assertBOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::assertCOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::C::assertBOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::C::assertCOf.call(<dynamic>[self::_isInt, self::_isString]);
  self::C c;
  c.assertAOf(<dynamic>[self::_isInt, self::_isString]);
  c.assertDOf(<dynamic>[self::_isInt, self::_isString]);
  self::G<core::int> g;
  g.assertAOf(<dynamic>[self::_isInt, self::_isString]);
  g.assertDOf(<dynamic>[self::_isInt, self::_isString]);
}
static method main() → dynamic {}
