mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:01:42 +00:00
Copy subtype tests
The tests are copied from pkg/kernel/test/type_subtype_test.dart Change-Id: I1120aa7ae1928fc20982f24fab14925b9ee851c8 Reviewed-on: https://dart-review.googlesource.com/c/90229 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
219a2fcf66
commit
d025ff5367
|
@ -32,10 +32,11 @@ import "type_parser.dart"
|
|||
ParsedVoidType,
|
||||
Visitor;
|
||||
|
||||
Library parseLibrary(Uri uri, String text, {Uri fileUri}) {
|
||||
Library parseLibrary(Uri uri, String text,
|
||||
{Uri fileUri, KernelEnvironment environment}) {
|
||||
fileUri ??= uri;
|
||||
environment ??= new KernelEnvironment(uri, fileUri);
|
||||
Library library = new Library(uri, fileUri: fileUri);
|
||||
KernelEnvironment environment = new KernelEnvironment(uri, fileUri);
|
||||
for (ParsedType type in type_parser.parse(text)) {
|
||||
Node node = environment.kernelFromParsedType(type);
|
||||
if (node is Class) {
|
||||
|
@ -144,7 +145,14 @@ class KernelFromParsedType implements Visitor<Node, KernelEnvironment> {
|
|||
|
||||
FunctionType visitFunctionType(
|
||||
ParsedFunctionType node, KernelEnvironment environment) {
|
||||
throw "not implemented: $node";
|
||||
DartType returnType =
|
||||
node.returnType?.accept<Node, KernelEnvironment>(this, environment);
|
||||
List<DartType> arguments = <DartType>[];
|
||||
for (ParsedType argument in node.arguments.required) {
|
||||
arguments
|
||||
.add(argument.accept<Node, KernelEnvironment>(this, environment));
|
||||
}
|
||||
return new FunctionType(arguments, returnType);
|
||||
}
|
||||
|
||||
VoidType visitVoidType(ParsedVoidType node, KernelEnvironment environment) {
|
||||
|
|
|
@ -4,13 +4,21 @@
|
|||
|
||||
import "package:expect/expect.dart" show Expect;
|
||||
|
||||
import "package:kernel/ast.dart" show Component, Library;
|
||||
import "package:kernel/ast.dart" show Component, DartType, Library;
|
||||
|
||||
import "package:kernel/class_hierarchy.dart" show ClassHierarchy;
|
||||
|
||||
import "package:kernel/core_types.dart" show CoreTypes;
|
||||
|
||||
import "package:kernel/text/ast_to_text.dart" show Printer;
|
||||
|
||||
import "kernel_type_parser.dart" show parseLibrary;
|
||||
import "package:kernel/type_environment.dart" show TypeEnvironment;
|
||||
|
||||
import "kernel_type_parser.dart" show KernelEnvironment, parseLibrary;
|
||||
|
||||
import "shared_type_tests.dart" show SubtypeTest;
|
||||
|
||||
import "type_parser.dart" as type_parser show parse;
|
||||
|
||||
const String testSdk = """
|
||||
class Object;
|
||||
|
@ -23,6 +31,7 @@ const String testSdk = """
|
|||
class Future<T>;
|
||||
class FutureOr<T>;
|
||||
class Null;
|
||||
class Function;
|
||||
""";
|
||||
|
||||
const String expectedSdk = """
|
||||
|
@ -49,14 +58,39 @@ class FutureOr<T extends self::Object = dynamic> extends self::Object {
|
|||
}
|
||||
class Null extends self::Object {
|
||||
}
|
||||
class Function extends self::Object {
|
||||
}
|
||||
""";
|
||||
|
||||
main() {
|
||||
Library library = parseLibrary(Uri.parse("dart:core"), testSdk);
|
||||
Uri uri = Uri.parse("dart:core");
|
||||
KernelEnvironment environment = new KernelEnvironment(uri, uri);
|
||||
Library library = parseLibrary(uri, testSdk, environment: environment);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Printer printer = new Printer(sb);
|
||||
printer.writeLibraryFile(library);
|
||||
Expect.stringEquals(expectedSdk, "$sb");
|
||||
Component component = new Component(libraries: <Library>[library]);
|
||||
new ClassHierarchy(component);
|
||||
ClassHierarchy hierarchy = new ClassHierarchy(component);
|
||||
CoreTypes coreTypes = new CoreTypes(component);
|
||||
new KernelSubtypeTest(coreTypes, hierarchy, environment).run();
|
||||
}
|
||||
|
||||
class KernelSubtypeTest extends SubtypeTest<DartType> {
|
||||
final CoreTypes coreTypes;
|
||||
|
||||
final ClassHierarchy hierarchy;
|
||||
|
||||
final KernelEnvironment environment;
|
||||
|
||||
KernelSubtypeTest(this.coreTypes, this.hierarchy, this.environment);
|
||||
|
||||
DartType toType(String text) {
|
||||
return environment.kernelFromParsedType(type_parser.parse(text).single);
|
||||
}
|
||||
|
||||
bool isSubtypeImpl(DartType subtype, DartType supertype, bool legacyMode) {
|
||||
return new TypeEnvironment(coreTypes, hierarchy, legacyMode: legacyMode)
|
||||
.isSubtypeOf(subtype, supertype);
|
||||
}
|
||||
}
|
||||
|
|
170
pkg/front_end/test/fasta/types/shared_type_tests.dart
Normal file
170
pkg/front_end/test/fasta/types/shared_type_tests.dart
Normal file
|
@ -0,0 +1,170 @@
|
|||
// 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.
|
||||
|
||||
import "package:expect/expect.dart" show Expect;
|
||||
|
||||
abstract class SubtypeTest<T> {
|
||||
void isSubtype(String subtypeString, String supertypeString,
|
||||
{bool legacyMode: false, String typeParameters}) {
|
||||
T subtype = toType(subtypeString);
|
||||
T supertype = toType(supertypeString);
|
||||
String mode = legacyMode ? " (legacy)" : "";
|
||||
Expect.isTrue(isSubtypeImpl(subtype, supertype, legacyMode),
|
||||
"$subtype should be a subtype of $supertype$mode.");
|
||||
}
|
||||
|
||||
void isNotSubtype(String subtypeString, String supertypeString,
|
||||
{bool legacyMode: false, String typeParameters}) {
|
||||
T subtype = toType(subtypeString);
|
||||
T supertype = toType(supertypeString);
|
||||
String mode = legacyMode ? " (legacy)" : "";
|
||||
Expect.isFalse(isSubtypeImpl(subtype, supertype, legacyMode),
|
||||
"$subtype shouldn't be a subtype of $supertype$mode.");
|
||||
}
|
||||
|
||||
T toType(String text);
|
||||
|
||||
bool isSubtypeImpl(T subtype, T supertype, bool legacyMode);
|
||||
|
||||
void run() {
|
||||
isSubtype('int', 'num', legacyMode: true);
|
||||
isSubtype('int', 'Comparable<num>', legacyMode: true);
|
||||
isSubtype('int', 'Comparable<Object>', legacyMode: true);
|
||||
isSubtype('int', 'Object', legacyMode: true);
|
||||
isSubtype('double', 'num', legacyMode: true);
|
||||
|
||||
isNotSubtype('int', 'double', legacyMode: true);
|
||||
isNotSubtype('int', 'Comparable<int>', legacyMode: true);
|
||||
isNotSubtype('int', 'Iterable<int>', legacyMode: true);
|
||||
isNotSubtype('Comparable<int>', 'Iterable<int>', legacyMode: true);
|
||||
|
||||
isSubtype('List<int>', 'List<int>', legacyMode: true);
|
||||
isSubtype('List<int>', 'Iterable<int>', legacyMode: true);
|
||||
isSubtype('List<int>', 'List<num>', legacyMode: true);
|
||||
isSubtype('List<int>', 'Iterable<num>', legacyMode: true);
|
||||
isSubtype('List<int>', 'List<Object>', legacyMode: true);
|
||||
isSubtype('List<int>', 'Iterable<Object>', legacyMode: true);
|
||||
isSubtype('List<int>', 'Object', legacyMode: true);
|
||||
isSubtype('List<int>', 'List<Comparable<Object>>', legacyMode: true);
|
||||
isSubtype('List<int>', 'List<Comparable<num>>', legacyMode: true);
|
||||
isSubtype('List<int>', 'List<Comparable<Comparable<num>>>',
|
||||
legacyMode: true);
|
||||
|
||||
isNotSubtype('List<int>', 'List<double>', legacyMode: true);
|
||||
isNotSubtype('List<int>', 'Iterable<double>', legacyMode: true);
|
||||
isNotSubtype('List<int>', 'Comparable<int>', legacyMode: true);
|
||||
isNotSubtype('List<int>', 'List<Comparable<int>>', legacyMode: true);
|
||||
isNotSubtype('List<int>', 'List<Comparable<Comparable<int>>>',
|
||||
legacyMode: true);
|
||||
|
||||
isSubtype('(num) -> num', '(int) -> num', legacyMode: true);
|
||||
isSubtype('(num) -> int', '(num) -> num', legacyMode: true);
|
||||
isSubtype('(num) -> int', '(int) -> num', legacyMode: true);
|
||||
isNotSubtype('(int) -> int', '(num) -> num', legacyMode: true);
|
||||
|
||||
isSubtype('(num) -> (num) -> num', '(num) -> (int) -> num',
|
||||
legacyMode: true);
|
||||
isNotSubtype('(num) -> (int) -> int', '(num) -> (num) -> num',
|
||||
legacyMode: true);
|
||||
|
||||
// TODO(ahe): Remove this as the implementation improves.
|
||||
return;
|
||||
|
||||
// ignore: dead_code
|
||||
isSubtype('(x:num) -> num', '(x:int) -> num',
|
||||
legacyMode: true); // named parameters
|
||||
isSubtype('(num,x:num) -> num', '(int,x:int) -> num', legacyMode: true);
|
||||
isSubtype('(x:num) -> int', '(x:num) -> num', legacyMode: true);
|
||||
isNotSubtype('(x:int) -> int', '(x:num) -> num', legacyMode: true);
|
||||
|
||||
isSubtype('<E>(E) -> int', '<E>(E) -> num',
|
||||
legacyMode: true); // type parameters
|
||||
isSubtype('<E>(num) -> E', '<E>(int) -> E', legacyMode: true);
|
||||
isSubtype('<E>(E,num) -> E', '<E>(E,int) -> E', legacyMode: true);
|
||||
isNotSubtype('<E>(E,num) -> E', '<E>(E,E) -> E', legacyMode: true);
|
||||
|
||||
isSubtype('<E>(E) -> (E) -> E', '<F>(F) -> (F) -> F', legacyMode: true);
|
||||
isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (int,E) -> E) -> E',
|
||||
legacyMode: true);
|
||||
isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (num,E) -> E) -> E',
|
||||
legacyMode: true);
|
||||
isNotSubtype('<E,F>(E) -> (F) -> E', '<E>(E) -> <F>(F) -> E',
|
||||
legacyMode: true);
|
||||
isNotSubtype('<E,F>(E) -> (F) -> E', '<F,E>(E) -> (F) -> E',
|
||||
legacyMode: true);
|
||||
|
||||
isNotSubtype('<E>(E,num) -> E', '<E:num>(E,E) -> E', legacyMode: true);
|
||||
isNotSubtype('<E:num>(E) -> int', '<E:int>(E) -> int', legacyMode: true);
|
||||
isNotSubtype('<E:num>(E) -> E', '<E:int>(E) -> E', legacyMode: true);
|
||||
isNotSubtype('<E:num>(int) -> E', '<E:int>(int) -> E', legacyMode: true);
|
||||
isSubtype('<E:num>(E) -> E', '<F:num>(F) -> num', legacyMode: true);
|
||||
isSubtype('<E:int>(E) -> E', '<F:int>(F) -> num', legacyMode: true);
|
||||
isSubtype('<E:int>(E) -> E', '<F:int>(F) -> int', legacyMode: true);
|
||||
isNotSubtype('<E>(int) -> int', '(int) -> int', legacyMode: true);
|
||||
isNotSubtype('<E,F>(int) -> int', '<E>(int) -> int', legacyMode: true);
|
||||
|
||||
isSubtype('<E:List<E>>(E) -> E', '<F:List<F>>(F) -> F', legacyMode: true);
|
||||
isNotSubtype('<E:Iterable<E>>(E) -> E', '<F:List<F>>(F) -> F',
|
||||
legacyMode: true);
|
||||
isNotSubtype('<E>(E,List<Object>) -> E', '<F:List<F>>(F,F) -> F',
|
||||
legacyMode: true);
|
||||
isNotSubtype('<E>(E,List<Object>) -> List<E>', '<F:List<F>>(F,F) -> F',
|
||||
legacyMode: true);
|
||||
isNotSubtype('<E>(E,List<Object>) -> int', '<F:List<F>>(F,F) -> F',
|
||||
legacyMode: true);
|
||||
isNotSubtype('<E>(E,List<Object>) -> E', '<F:List<F>>(F,F) -> void',
|
||||
legacyMode: true);
|
||||
|
||||
isSubtype('int', 'FutureOr<int>');
|
||||
isSubtype('int', 'FutureOr<num>');
|
||||
isSubtype('Future<int>', 'FutureOr<int>');
|
||||
isSubtype('Future<int>', 'FutureOr<num>');
|
||||
isSubtype('Future<int>', 'FutureOr<Object>');
|
||||
isSubtype('FutureOr<int>', 'FutureOr<int>');
|
||||
isSubtype('FutureOr<int>', 'FutureOr<num>');
|
||||
isSubtype('FutureOr<int>', 'Object');
|
||||
isNotSubtype('int', 'FutureOr<double>');
|
||||
isNotSubtype('FutureOr<double>', 'int');
|
||||
isNotSubtype('FutureOr<int>', 'Future<num>');
|
||||
isNotSubtype('FutureOr<int>', 'num');
|
||||
|
||||
// T & B <: T & A if B <: A
|
||||
isSubtype('T & int', 'T & int', legacyMode: true);
|
||||
isSubtype('T & int', 'T & num', legacyMode: true);
|
||||
isSubtype('T & num', 'T & num', legacyMode: true);
|
||||
isNotSubtype('T & num', 'T & int', legacyMode: true);
|
||||
|
||||
// T & B <: T extends A if B <: A
|
||||
// (Trivially satisfied since promoted bounds are always a isSubtype of the
|
||||
// original bound)
|
||||
isSubtype('T & int', 'T', legacyMode: true, typeParameters: 'T: int');
|
||||
isSubtype('T & int', 'T', legacyMode: true, typeParameters: 'T: num');
|
||||
isSubtype('T & num', 'T', legacyMode: true, typeParameters: 'T: num');
|
||||
|
||||
// T extends B <: T & A if B <: A
|
||||
isSubtype('T', 'T & int', legacyMode: true, typeParameters: 'T: int');
|
||||
isSubtype('T', 'T & num', legacyMode: true, typeParameters: 'T: int');
|
||||
isSubtype('T', 'T & num', legacyMode: true, typeParameters: 'T: num');
|
||||
isNotSubtype('T', 'T & int', legacyMode: true, typeParameters: 'T: num');
|
||||
|
||||
// T extends A <: T extends A
|
||||
isSubtype('T', 'T', legacyMode: true, typeParameters: 'T: num');
|
||||
|
||||
// S & B <: A if B <: A, A is not S (or a promotion thereof)
|
||||
isSubtype('S & int', 'int', legacyMode: true);
|
||||
isSubtype('S & int', 'num', legacyMode: true);
|
||||
isSubtype('S & num', 'num', legacyMode: true);
|
||||
isNotSubtype('S & num', 'int', legacyMode: true);
|
||||
isNotSubtype('S & num', 'T', legacyMode: true);
|
||||
isNotSubtype('S & num', 'T & num', legacyMode: true);
|
||||
|
||||
// S extends B <: A if B <: A, A is not S (or a promotion thereof)
|
||||
isSubtype('S', 'int', legacyMode: true, typeParameters: 'S: int');
|
||||
isSubtype('S', 'num', legacyMode: true, typeParameters: 'S: int');
|
||||
isSubtype('S', 'num', legacyMode: true, typeParameters: 'S: num');
|
||||
isNotSubtype('S', 'int', legacyMode: true, typeParameters: 'S: num');
|
||||
isNotSubtype('S', 'T', legacyMode: true, typeParameters: 'S: num');
|
||||
isNotSubtype('S', 'T & num', legacyMode: true, typeParameters: 'S: num');
|
||||
}
|
||||
}
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
import "package:front_end/src/fasta/scanner.dart" show scanString, Token;
|
||||
|
||||
import "package:front_end/src/fasta/parser/type_info_impl.dart"
|
||||
show splitCloser;
|
||||
|
||||
abstract class ParsedType {
|
||||
R accept<R, A>(Visitor<R, A> visitor, [A a]);
|
||||
}
|
||||
|
@ -136,7 +139,14 @@ class ParsedTypeVariable extends ParsedType {
|
|||
|
||||
ParsedTypeVariable(this.name, this.bound);
|
||||
|
||||
String toString() => name;
|
||||
String toString() {
|
||||
if (bound == null) return name;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.write(name);
|
||||
sb.write(" extends ");
|
||||
sb.write(bound);
|
||||
return "$sb";
|
||||
}
|
||||
|
||||
R accept<R, A>(Visitor<R, A> visitor, [A a]) {
|
||||
return visitor.visitTypeVariable(this, a);
|
||||
|
@ -228,6 +238,7 @@ class Parser {
|
|||
advance();
|
||||
arguments.add(parseType());
|
||||
}
|
||||
peek = splitCloser(peek);
|
||||
expect(">");
|
||||
}
|
||||
return new ParsedInterfaceType(name, arguments);
|
||||
|
@ -291,6 +302,7 @@ class Parser {
|
|||
do {
|
||||
typeVariables.add(parseTypeVariable());
|
||||
} while (optionalAdvance(","));
|
||||
peek = splitCloser(peek);
|
||||
expect(">");
|
||||
}
|
||||
return typeVariables;
|
||||
|
|
|
@ -33,5 +33,9 @@ typedef MyList<T> List<T>;
|
|||
typedef StringList List<String>;
|
||||
typedef VoidFunction () -> void;
|
||||
typedef GenericFunction<T> () -> T;
|
||||
List<List<Object>>
|
||||
List<List<List<Object>>>
|
||||
class A<T extends List<Object>>;
|
||||
class B<T extends List<List<Object>>>;
|
||||
""");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue