blob: e127979c20f039aaca3ab53c24c4670d6b8a3787 [file] [log] [blame]
// Copyright (c) 2022, 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:_fe_analyzer_shared/src/exhaustiveness/static_type.dart';
import 'package:test/test.dart';
import 'utils.dart';
void main() {
group('sealed subtypes', () {
// (A)
// / \
// B C
var a = StaticType('A', isSealed: true);
var b = StaticType('B', inherits: [a]);
var c = StaticType('C', inherits: [a]);
var t = StaticType('T', fields: {'x': a, 'y': a});
expectExhaustiveOnlyAll(t, [
{'x': b, 'y': b},
{'x': b, 'y': c},
{'x': c, 'y': b},
{'x': c, 'y': c},
]);
});
group('sealed subtypes medium', () {
// (A)
// /|\
// B C D
var a = StaticType('A', isSealed: true);
var b = StaticType('B', inherits: [a]);
var c = StaticType('C', inherits: [a]);
var d = StaticType('D', inherits: [a]);
var t = StaticType('T', fields: {'y': a, 'z': a});
expectExhaustiveOnlyAll(t, [
{'y': b, 'z': b},
{'y': b, 'z': c},
{'y': b, 'z': d},
{'y': c, 'z': b},
{'y': c, 'z': c},
{'y': c, 'z': d},
{'y': d, 'z': b},
{'y': d, 'z': c},
{'y': d, 'z': d},
]);
});
group('sealed subtypes large', () {
// (A)
// /|\
// B C D
var a = StaticType('A', isSealed: true);
var b = StaticType('B', inherits: [a]);
var c = StaticType('C', inherits: [a]);
var d = StaticType('D', inherits: [a]);
var t = StaticType('T', fields: {'w': a, 'x': a, 'y': a, 'z': a});
expectExhaustiveOnlyAll(t, [
{'w': b, 'x': b, 'y': b, 'z': b},
{'w': b, 'x': b, 'y': b, 'z': c},
{'w': b, 'x': b, 'y': b, 'z': d},
{'w': b, 'x': b, 'y': c, 'z': b},
{'w': b, 'x': b, 'y': c, 'z': c},
{'w': b, 'x': b, 'y': c, 'z': d},
{'w': b, 'x': b, 'y': d, 'z': b},
{'w': b, 'x': b, 'y': d, 'z': c},
{'w': b, 'x': b, 'y': d, 'z': d},
{'w': b, 'x': c, 'y': b, 'z': b},
{'w': b, 'x': c, 'y': b, 'z': c},
{'w': b, 'x': c, 'y': b, 'z': d},
{'w': b, 'x': c, 'y': c, 'z': b},
{'w': b, 'x': c, 'y': c, 'z': c},
{'w': b, 'x': c, 'y': c, 'z': d},
{'w': b, 'x': c, 'y': d, 'z': b},
{'w': b, 'x': c, 'y': d, 'z': c},
{'w': b, 'x': c, 'y': d, 'z': d},
{'w': b, 'x': d, 'y': b, 'z': b},
{'w': b, 'x': d, 'y': b, 'z': c},
{'w': b, 'x': d, 'y': b, 'z': d},
{'w': b, 'x': d, 'y': c, 'z': b},
{'w': b, 'x': d, 'y': c, 'z': c},
{'w': b, 'x': d, 'y': c, 'z': d},
{'w': b, 'x': d, 'y': d, 'z': b},
{'w': b, 'x': d, 'y': d, 'z': c},
{'w': b, 'x': d, 'y': d, 'z': d},
{'w': c, 'x': b, 'y': b, 'z': b},
{'w': c, 'x': b, 'y': b, 'z': c},
{'w': c, 'x': b, 'y': b, 'z': d},
{'w': c, 'x': b, 'y': c, 'z': b},
{'w': c, 'x': b, 'y': c, 'z': c},
{'w': c, 'x': b, 'y': c, 'z': d},
{'w': c, 'x': b, 'y': d, 'z': b},
{'w': c, 'x': b, 'y': d, 'z': c},
{'w': c, 'x': b, 'y': d, 'z': d},
{'w': c, 'x': c, 'y': b, 'z': b},
{'w': c, 'x': c, 'y': b, 'z': c},
{'w': c, 'x': c, 'y': b, 'z': d},
{'w': c, 'x': c, 'y': c, 'z': b},
{'w': c, 'x': c, 'y': c, 'z': c},
{'w': c, 'x': c, 'y': c, 'z': d},
{'w': c, 'x': c, 'y': d, 'z': b},
{'w': c, 'x': c, 'y': d, 'z': c},
{'w': c, 'x': c, 'y': d, 'z': d},
{'w': c, 'x': d, 'y': b, 'z': b},
{'w': c, 'x': d, 'y': b, 'z': c},
{'w': c, 'x': d, 'y': b, 'z': d},
{'w': c, 'x': d, 'y': c, 'z': b},
{'w': c, 'x': d, 'y': c, 'z': c},
{'w': c, 'x': d, 'y': c, 'z': d},
{'w': c, 'x': d, 'y': d, 'z': b},
{'w': c, 'x': d, 'y': d, 'z': c},
{'w': c, 'x': d, 'y': d, 'z': d},
{'w': d, 'x': b, 'y': b, 'z': b},
{'w': d, 'x': b, 'y': b, 'z': c},
{'w': d, 'x': b, 'y': b, 'z': d},
{'w': d, 'x': b, 'y': c, 'z': b},
{'w': d, 'x': b, 'y': c, 'z': c},
{'w': d, 'x': b, 'y': c, 'z': d},
{'w': d, 'x': b, 'y': d, 'z': b},
{'w': d, 'x': b, 'y': d, 'z': c},
{'w': d, 'x': b, 'y': d, 'z': d},
{'w': d, 'x': c, 'y': b, 'z': b},
{'w': d, 'x': c, 'y': b, 'z': c},
{'w': d, 'x': c, 'y': b, 'z': d},
{'w': d, 'x': c, 'y': c, 'z': b},
{'w': d, 'x': c, 'y': c, 'z': c},
{'w': d, 'x': c, 'y': c, 'z': d},
{'w': d, 'x': c, 'y': d, 'z': b},
{'w': d, 'x': c, 'y': d, 'z': c},
{'w': d, 'x': c, 'y': d, 'z': d},
{'w': d, 'x': d, 'y': b, 'z': b},
{'w': d, 'x': d, 'y': b, 'z': c},
{'w': d, 'x': d, 'y': b, 'z': d},
{'w': d, 'x': d, 'y': c, 'z': b},
{'w': d, 'x': d, 'y': c, 'z': c},
{'w': d, 'x': d, 'y': c, 'z': d},
{'w': d, 'x': d, 'y': d, 'z': b},
{'w': d, 'x': d, 'y': d, 'z': c},
{'w': d, 'x': d, 'y': d, 'z': d},
]);
});
group('sealed transitive subtypes', () {
// (A)
// / \
// (B) (C)
// / \ \
// D E F
var a = StaticType('A', isSealed: true);
var b = StaticType('B', isSealed: true, inherits: [a]);
var c = StaticType('C', isSealed: true, inherits: [a]);
var d = StaticType('D', inherits: [b]);
var e = StaticType('E', inherits: [b]);
var f = StaticType('F', inherits: [c]);
var t = StaticType('T', fields: {'x': a, 'y': a});
expectExhaustiveOnlyAll(t, [
{'x': a, 'y': a},
]);
expectExhaustiveOnlyAll(t, [
{'x': b, 'y': b},
{'x': b, 'y': c},
{'x': c, 'y': b},
{'x': c, 'y': c},
]);
expectExhaustiveOnlyAll(t, [
{'x': b, 'y': d},
{'x': b, 'y': e},
{'x': b, 'y': f},
{'x': c, 'y': d},
{'x': c, 'y': e},
{'x': c, 'y': f},
]);
});
group('unsealed subtypes', () {
// A
// / \
// B C
var a = StaticType('A');
var b = StaticType('B', inherits: [a]);
var c = StaticType('C', inherits: [a]);
// Not exhaustive even when known subtypes covered.
var t = StaticType('T', fields: {'x': a, 'y': a});
expectNeverExhaustive(t, [
{'x': b, 'y': b},
{'x': b, 'y': c},
{'x': c, 'y': b},
{'x': c, 'y': c},
]);
// Exhaustive if field static type is a covered subtype.
var u = StaticType('T', fields: {'x': b, 'y': c});
expectExhaustiveOnlyAll(u, [
{'x': b, 'y': c},
]);
});
group('different fields', () {
// (A)
// / \
// B C
var a = StaticType('A', isSealed: true);
var b = StaticType('B', inherits: [a]);
var c = StaticType('C', inherits: [a]);
var t = StaticType('T', fields: {'x': a, 'y': a, 'z': a});
expectNeverExhaustive(t, [
{'x': b},
{'y': b},
{'z': b},
]);
expectExhaustiveOnlyAll(t, [
{'x': b, 'y': a},
{'x': c, 'z': a},
]);
expectExhaustiveOnlyAll(t, [
{'x': b, 'y': b},
{'x': b, 'y': c},
{'x': c, 'y': b},
{'x': c, 'y': c},
]);
});
group('field types', () {
// (A)
// / \
// B C
var a = StaticType('A', isSealed: true);
var b = StaticType('B', inherits: [a]);
var c = StaticType('C', inherits: [a]);
var t = StaticType('T', fields: {'x': a, 'y': b, 'z': c});
expectExhaustiveOnlyAll(t, [
{'x': a, 'y': b, 'z': c},
]);
expectExhaustiveOnlyAll(t, [
{'x': b},
{'x': c},
]);
expectExhaustiveOnlyAll(t, [
{'y': b},
]);
expectExhaustiveOnlyAll(t, [
{'z': c},
]);
});
}