blob: e92126bef0b15df33b9f0c6792226f36c26edf21 [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.
// @dart = 2.9
library 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<S>> {}
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, [new FBounded<Never>().runtimeType]), new FBounded<FBounded<Never>>().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(Symbol.empty, []).reflectee;
Expect.equals(new A<P>().runtimeType, instance.runtimeType);
}