Update language_2/nested_generic_closure_test.dart.

No longer depends on the unspecified `Type.toString`.

Bug: http://dartbug.com/37452
Change-Id: Ie7eeeecdc8970831082e763edc46f195a8bfc7e7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108275
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2019-07-10 09:46:41 +00:00 committed by commit-bot@chromium.org
parent 52858391e6
commit ac41a20081
2 changed files with 156 additions and 31 deletions

View file

@ -0,0 +1,134 @@
// Copyright (c) 2019, 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.
// Testing the behavior of `Type.toString`.
//
// The behavior is *unspecified*, but users may depend on it.
// This test ensures that we do not change the format inadvertently.
// If we decide to change the format, it should be deliberate and consistent.
import "dart:async" show FutureOr;
import "package:expect/expect.dart";
void expectType(Type type, Pattern text) {
var typeString = "$type";
if (typeString.contains("minimized:")) {
return; // No checks for minimized types.
}
if (text is String) {
Expect.equals(text, typeString);
return;
}
var match = text.matchAsPrefix(typeString);
if (match != null && match.end == typeString.length) return;
Expect.fail(
"$typeString was not matched by $text${match == null ? "" : ", match: ${match[0]}"}");
}
void expect<T>(Pattern text) {
expectType(T, text);
}
void main() {
// Simple interface types.
expect<int>("int");
expect<Object>("Object");
expect<Null>("Null");
expect<Base>("Base");
expect<Mixin>("Mixin");
// Named mixin applications use their name.
expect<MixinApplication>("MixinApplication");
// Non-class, non-function types.
expect<void>("void");
expect<dynamic>("dynamic");
expect<Function>("Function");
// TODO: Add Never with NNBD.
// Generic interface types.
expect<List<int>>("List<int>");
expect<Iterable<Object>>("Iterable<Object>");
expect<Map<List<String>, Future<void>>>("Map<List<String>, Future<void>>");
expect<GenericMixin<String>>("GenericMixin<String>");
// Generic non-class, non-function type.
expect<FutureOr<int>>("FutureOr<int>");
expect<FutureOr<Object>>("FutureOr<Object>");
expect<FutureOr<FutureOr<Future<Object>>>>(
"FutureOr<FutureOr<Future<Object>>>");
expect<FutureOr<Null>>("FutureOr<Null>");
// TODO: Add nullable types with NNBD.
// Private names may be mangled.
expect<_Private>(re(r'_Private\b.*$'));
// Function types.
expect<void Function()>("() => void");
expect<String Function()>("() => String");
expect<String Function(String)>("(String) => String");
expect<String Function(int, [String])>("(int, [String]) => String");
expect<String Function(int, {String z})>("(int, {String z}) => String");
expect<int Function(void Function(String))>("((String) => void) => int");
expect<int Function(void) Function(String)>("(String) => (void) => int");
// A type alias is expanded to its type.
expect<Typedef>("(dynamic) => dynamic");
expect<Typedef<int>>("(int) => int");
expectType(Typedef, "(dynamic) => dynamic");
// Generic functions do not promise to preserve type variable names,
// but do keep the structure of `<typevars>(params) => result`.
// Cannot pass a generic type as type argument, so passing the Type object
// derived from evaluating the typedef name.
// Format: <T>() => void
expectType(G0, re(r"<\w+>\(\) => void$"));
// Format: <T>() => T
expectType(G1, re(r"<(\w+)>\(\) => \1$"));
// Format: <T>(T) => T
expectType(G2, re(r"<(\w+)>\(\1\) => \1$"));
// Format: <T>(<S>(S, T) => S) => T
expectType(G3, re(r"<(\w+)>\(<(\w+)>\(\2, \1\) => \2\) => \1$"));
// Format: <S>(S) => <T>(S, T) => S
expectType(G4, re(r"<(\w+)>\(\1\) => <(\w+)>\(\1, \2\) => \1$"));
// Format: <S, T>(S, T) => S
expectType(G5, re(r"<(\w+), (\w+)>\(\1, \2\) => \1$"));
// Format: <T>(<S>(S) => S) => T
expectType(Weird, re(r"<(\w+)>\(<(\w+)>\(\2\) => \2\) => \1$"));
// One with everything.
expect<FutureOr<void Function([T Function<S, T>(Map<dynamic, Typedef<S>>)])>>(
// Format: FutureOr<([<S, T>(Map<dynamic, (S) => S>) => T]) => void>
re(r"FutureOr<\(\[<(\w+), (\w+)>\(Map<dynamic, "
r"\(\1\) => \1>\) => \2\]\) => void>$"));
}
// Types to test against.
class _Private {}
class Base {}
mixin Mixin {}
class MixinApplication = Base with Mixin;
mixin GenericMixin<T> implements List<T> {}
typedef Typedef<T> = T Function(T);
// Generic function types.
typedef G0 = void Function<T>();
typedef G1 = T Function<T>();
typedef G2 = T Function<T>(T);
typedef G3 = T Function<T>(S Function<S>(S, T));
typedef G4 = S Function<T>(S, T) Function<S>(S);
typedef G5 = S Function<S, T>(S, T);
typedef Weird = Function Function<Function>(
Function Function<Function>(Function));
RegExp re(String source) => RegExp(source);

View file

@ -2,8 +2,6 @@
// 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.
// TODO(37452): Avoid using unspecified 'toString' behaviour in language test.
import 'package:expect/expect.dart';
void foo(F f<F>(F f)) {}
@ -11,7 +9,7 @@ void foo(F f<F>(F f)) {}
B bar<B>(B g<F>(F f)) => null;
Function baz<B>() {
B foo<F>(F f) => null;
B foo<F>(B b, F f) => null;
return foo;
}
@ -25,34 +23,27 @@ class C<T> {
}
main() {
expectOne(
foo.runtimeType.toString(),
["(<F>(F) => F) => void", "(<T1>(T1) => T1) => void"],
);
expectOne(
bar.runtimeType.toString(),
["<B>(<F>(F) => B) => B", "<T1>(<T2>(T2) => T1) => T1"],
);
expectOne(
baz<int>().runtimeType.toString(),
["<F>(F) => int", "<T1>(T1) => int"],
);
// Check the run-time type of the functions with generic parameters.
var c = new C<bool>();
expectOne(
c.foo.runtimeType.toString(),
["(<F>(bool, F) => F) => void", "(<T1>(bool, T1) => T1) => void"],
);
expectOne(
c.bar.runtimeType.toString(),
["<B>(<F>(bool, F) => B) => B", "<T1>(<T2>(bool, T2) => T1) => T1"],
);
expectOne(
c.baz<int>().runtimeType.toString(),
["<F>(bool, F) => int", "<T1>(bool, T1) => int"],
);
}
Expect.type<void Function(X Function<X>(X))>(foo);
expectOne(String name, Iterable<String> names) {
Expect.isTrue(names.contains(name), '"$name" should be one of: ${names}');
Expect.isTrue(bar is X1 Function<X1>(X1 Function<X2>(X2)));
Expect.isTrue(baz<int>() is int Function<X1>(int, X1));
Expect.isTrue(baz<Object>() is Object Function<X1>(Object, X1));
Expect.isTrue(baz<Null>() is Null Function<X1>(Null, X1));
void testC<T>() {
var c = new C<T>();
Expect.type<void Function(F Function<F>(T, F))>(c.foo);
Expect.isTrue(c.bar is X1 Function<X1>(X1 Function<X2>(T, X2)));
Expect.isTrue(c.baz<int>() is int Function<X1>(T, X1));
}
testC<bool>();
testC<Object>();
testC<Null>();
}