blob: bae1b681f19151cc1f24db0c9ca91a322592fe72 [file] [log] [blame]
// Copyright (c) 2016, 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 test.reflected_type_generics_test;
@MirrorsUsed(targets: "test.reflected_type_generics_test")
import 'dart:mirrors';
import 'package:expect/expect.dart';
import 'reflected_type_helper.dart';
class A<T> {}
class P {}
class B extends A<P> {}
class C<K, V> {}
class D<T> extends A<T> {}
class E<K> extends C<K, int> {}
class F<G> {}
typedef bool Predicate<T>(T arg);
class FBounded<S extends FBounded> {}
class Helper<T> {
Type get param => T;
}
class Mixin<T extends P> {}
class Composite<K extends P, V> extends Object with Mixin<K> {}
main() {
// "Happy" paths:
expectReflectedType(reflectType(A, [P]), new A<P>().runtimeType);
expectReflectedType(reflectType(C, [B, P]), new C<B, P>().runtimeType);
expectReflectedType(reflectType(D, [P]), new D<P>().runtimeType);
expectReflectedType(reflectType(E, [P]), new E<P>().runtimeType);
expectReflectedType(
reflectType(FBounded, [FBounded]), new FBounded<FBounded>().runtimeType);
var predicateHelper = new Helper<Predicate<P>>();
expectReflectedType(reflectType(Predicate, [P]), predicateHelper.param); //# 01: ok
var composite = new Composite<P, int>();
expectReflectedType(reflectType(Composite, [P, int]), composite.runtimeType);
// Edge cases:
Expect.throws(
() => reflectType(P, []),
(e) => e is ArgumentError && e.invalidValue is List,
"Should throw an ArgumentError if reflecting not a generic class with "
"empty list of type arguments");
Expect.throws( // //# 03: ok
() => reflectType(P, [B]), // //# 03: continued
(e) => e is Error, // //# 03: continued
"Should throw an ArgumentError if reflecting not a generic class with " //# 03: continued
"some type arguments"); // //# 03: continued
Expect.throws(
() => reflectType(A, []),
(e) => e is ArgumentError && e.invalidValue is List,
"Should throw an ArgumentError if type argument list is empty for a "
"generic class");
Expect.throws( // //# 04: ok
() => reflectType(A, [P, B]), // //# 04: continued
(e) => e is ArgumentError && e.invalidValue is List, // //# 04: continued
"Should throw an ArgumentError if number of type arguments is not " // //# 04: continued
"correct"); // //# 04: continued
Expect.throws(() => reflectType(B, [P]), (e) => e is Error, // //# 05: ok
"Should throw an ArgumentError for non-generic class extending " // //# 05: continued
"generic one"); // //# 05: continued
Expect.throws(
() => reflectType(A, ["non-type"]),
(e) => e is ArgumentError && e.invalidValue is List,
"Should throw an ArgumentError when any of type arguments is not a Type");
Expect.throws( // //# 06: ok
() => reflectType(A, [P, B]), // //# 06: continued
(e) => e is ArgumentError && e.invalidValue is List, // //# 06: continued
"Should throw an ArgumentError if number of type arguments is not correct " //# 06: continued
"for generic extending another generic"); // //# 06: continued
Expect.throws(
() => reflectType(reflectType(F).typeVariables[0].reflectedType, [int]));
Expect.throws(() => reflectType(FBounded, [int])); //# 02: ok
var boundedType =
reflectType(FBounded).typeVariables[0].upperBound.reflectedType;
Expect.throws(() => reflectType(boundedType, [int])); //# 02: ok
Expect.throws(() => reflectType(Composite, [int, int])); //# 02: ok
// Instantiation of a generic class preserves type information:
ClassMirror m = reflectType(A, [P]) as ClassMirror;
var instance = m.newInstance(const Symbol(""), []).reflectee;
Expect.equals(new A<P>().runtimeType, instance.runtimeType);
}