blob: eb347891c47971987538cf50f9100173aacd8a8b [file] [log] [blame]
// Copyright (c) 2017, 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:front_end/src/fasta/type_inference/type_schema.dart';
import 'package:kernel/ast.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(UnknownTypeTest);
});
}
typedef U _UnaryFunction<T, U>(T t);
@reflectiveTest
class UnknownTypeTest {
static const unknownType = const UnknownType();
void test_equality() {
expect(unknownType, equals(unknownType));
expect(unknownType, equals(new UnknownType()));
expect(unknownType, isNot(equals(const DynamicType())));
}
void test_isKnown() {
expect(isKnown(unknownType), isFalse);
expect(isKnown(const DynamicType()), isTrue);
var classA = new Class(name: 'A', fileUri: dummyUri);
var A = new InterfaceType(classA, Nullability.legacy);
var typedefF = new Typedef('F', A, fileUri: dummyUri);
expect(isKnown(A), isTrue);
expect(isKnown(new InterfaceType(classA, Nullability.legacy, [A])), isTrue);
expect(
isKnown(new InterfaceType(classA, Nullability.legacy, [unknownType])),
isFalse);
expect(isKnown(new FunctionType([], const VoidType(), Nullability.legacy)),
isTrue);
expect(isKnown(new FunctionType([], unknownType, Nullability.legacy)),
isFalse);
expect(isKnown(new FunctionType([A], const VoidType(), Nullability.legacy)),
isTrue);
expect(
isKnown(new FunctionType(
[unknownType], const VoidType(), Nullability.legacy)),
isFalse);
expect(
isKnown(new FunctionType([], const VoidType(), Nullability.legacy,
namedParameters: [new NamedType('x', A)])),
isTrue);
expect(
isKnown(new FunctionType([], const VoidType(), Nullability.legacy,
namedParameters: [new NamedType('x', unknownType)])),
isFalse);
expect(isKnown(new TypedefType(typedefF, Nullability.legacy)), isTrue);
expect(isKnown(new TypedefType(typedefF, Nullability.legacy, [A])), isTrue);
expect(
isKnown(new TypedefType(typedefF, Nullability.legacy, [unknownType])),
isFalse);
}
void test_ordinary_visitor_noOverrides() {
expect(unknownType.accept(new _OrdinaryVisitor()), isNull);
}
void test_ordinary_visitor_overrideDefault() {
expect(unknownType
.accept(new _OrdinaryVisitor<String>(defaultDartType: (DartType node) {
expect(node, same(unknownType));
return 'defaultDartType';
})), 'defaultDartType');
}
void test_type_schema_visitor_noOverrides() {
expect(unknownType.accept(new _TypeSchemaVisitor()), isNull);
}
void test_type_schema_visitor_overrideDefault() {
expect(unknownType.accept(
new _TypeSchemaVisitor<String>(defaultDartType: (DartType node) {
expect(node, same(unknownType));
return 'defaultDartType';
})), 'defaultDartType');
}
void test_type_schema_visitor_overrideVisitUnknownType() {
expect(unknownType.accept(
new _TypeSchemaVisitor<String>(visitUnknownType: (UnknownType node) {
expect(node, same(unknownType));
return 'visitUnknownType';
})), 'visitUnknownType');
}
void test_typeSchemaToString() {
expect(unknownType.toString(), isNot('?'));
expect(typeSchemaToString(unknownType), '?');
expect(
typeSchemaToString(new FunctionType(
[unknownType, unknownType], unknownType, Nullability.legacy)),
'(?, ?) →* ?');
}
void test_visitChildren() {
unknownType
.visitChildren(new _TypeSchemaVisitor(defaultDartType: (DartType node) {
fail('Should not have visited anything');
}));
}
}
class _OrdinaryVisitor<R> extends Visitor<R?> with VisitorNullMixin<R> {
final _UnaryFunction<DartType, R>? _defaultDartType;
_OrdinaryVisitor({_UnaryFunction<DartType, R>? defaultDartType})
: _defaultDartType = defaultDartType;
@override
R? defaultDartType(DartType node) {
if (_defaultDartType != null) {
return _defaultDartType!(node);
} else {
return super.defaultDartType(node);
}
}
}
class _TypeSchemaVisitor<R> extends Visitor<R?> with VisitorNullMixin<R> {
final _UnaryFunction<DartType, R>? _defaultDartType;
final _UnaryFunction<UnknownType, R>? _visitUnknownType;
_TypeSchemaVisitor(
{_UnaryFunction<DartType, R>? defaultDartType,
_UnaryFunction<UnknownType, R>? visitUnknownType})
: _defaultDartType = defaultDartType,
_visitUnknownType = visitUnknownType;
@override
R? defaultDartType(DartType node) {
if (node is UnknownType && _visitUnknownType != null) {
return _visitUnknownType!(node);
} else if (_defaultDartType != null) {
return _defaultDartType!(node);
} else {
return super.defaultDartType(node);
}
}
}