blob: e6c75ce2e8989c43ce4e8104ef26bcae7de63990 [file] [log] [blame]
// 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.
// @dart = 2.9
import 'package:expect/expect.dart';
import 'utils.dart';
// Typed as dynamic to also test spreading a value of type dynamic.
const dynamic list = [1, 2, 3];
const dynamic map = {1: 1, 2: 2, 3: 3};
const dynamic set = {1, 2, 3};
const dynamic dynamicTrue = true;
const Object objectTrue = true;
void main() {
testList();
testMap();
testSet();
testShortCircuit();
testDuplicateKeys();
testKeyOrder();
}
void testList() {
// Then if true.
Expect.identical(list, const <int>[1, if (true) 2, 3]);
// Nothing if false and no else.
Expect.identical(list, const <int>[1, if (false) 9, 2, 3]);
// Else if false.
Expect.identical(list, const <int>[1, if (false) 9 else 2, 3]);
// Only if.
Expect.identical(const [1], const <int>[if (true) 1]);
// If at beginning.
Expect.identical(list, const <int>[if (true) 1, 2, 3]);
// If in middle.
Expect.identical(list, const <int>[1, if (true) 2, 3]);
// If at end.
Expect.identical(list, const <int>[1, 2, if (true) 3]);
// Multiple ifs.
Expect.identical(list,
const <int>[if (true) 1, if (false) 9, 2, if (true) 3]);
// Cast condition.
Expect.identical(const [1], const <int>[if (dynamicTrue) 1]);
Expect.identical(const [1], const <int>[if (objectTrue) 1]);
// Does not flatten nested collection literal.
Expect.identical(const [1], const [if (true) [1]].first);
Expect.identical(const {1: 1}, const [if (true) {1: 1}].first);
Expect.identical(const {1}, const [if (true) {1}].first);
// Nested spread.
Expect.identical(list,
const <int>[if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]]);
// Nested if in then.
Expect.identical(const [1],
const <int>[if (true) if (true) 1, if (true) if (false) 9]);
// Nested if in else.
Expect.identical(const [1], const <int>[if (false) 9 else if (true) 1]);
}
void testMap() {
// Then if true.
Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});
// Nothing if false and no else.
Expect.identical(map, const <int, int>{1: 1, if (false) 9: 9, 2: 2, 3: 3});
// Else if false.
Expect.identical(map,
const <int, int>{1: 1, if (false) 9: 9 else 2: 2, 3: 3});
// Only if.
Expect.identical(const {1: 1}, const <int, int>{if (true) 1: 1});
// If at beginning.
Expect.identical(map, const <int, int>{if (true) 1: 1, 2: 2, 3: 3});
// If in middle.
Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});
// If at end.
Expect.identical(map, const <int, int>{1: 1, 2: 2, if (true) 3: 3});
// Multiple ifs.
Expect.identical(map,
const <int, int>{if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3});
// Cast condition.
Expect.identical(const {1: 1}, const <int, int>{if (dynamicTrue) 1: 1});
Expect.identical(const {1: 1}, const <int, int>{if (objectTrue) 1: 1});
// Nested spread.
Expect.identical(map, const <int, int>{
if (true) ...<int, int>{1: 1, 2: 2},
if (false) 9: 9 else ...<int, int>{3: 3}
});
// Nested if in then.
Expect.identical(const {1: 1},
const <int, int>{if (true) if (true) 1: 1, if (true) if (false) 9: 9});
// Nested if in else.
Expect.identical(const {1: 1},
const <int, int>{if (false) 9: 9 else if (true) 1: 1});
}
void testSet() {
// Then if true.
Expect.identical(set, const <int>{1, if (true) 2, 3});
// Nothing if false and no else.
Expect.identical(set, const <int>{1, if (false) 9, 2, 3});
// Else if false.
Expect.identical(set, const <int>{1, if (false) 9 else 2, 3});
// Only if.
Expect.identical(const <int>{1}, const <int>{if (true) 1});
// If at beginning.
Expect.identical(set, const <int>{if (true) 1, 2, 3});
// If in middle.
Expect.identical(set, const <int>{1, if (true) 2, 3});
// If at end.
Expect.identical(set, const <int>{1, 2, if (true) 3});
// Multiple ifs.
Expect.identical(set,
const <int>{if (true) 1, if (false) 9, 2, if (true) 3});
// Cast condition.
Expect.identical(const <int>{1}, const <int>{if (dynamicTrue) 1});
Expect.identical(const <int>{1}, const <int>{if (objectTrue) 1});
// Does not flatten nested collection literal.
Expect.identical(const <int>[1], const <List<int>>{if (true) [1]}.first);
Expect.identical(
const <int, int>{1: 1}, const <Map<int, int>>{if (true) {1: 1}}.first);
Expect.identical(const <int>{1}, const <Set<int>>{if (true) {1}}.first);
// Nested spread.
Expect.identical(set,
const <int>{if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]});
// Nested if in then.
Expect.identical(const <int>{1},
const <int>{if (true) if (true) 1, if (true) if (false) 9});
// Nested if in else.
Expect.identical(const <int>{1}, const <int>{if (false) 9 else if (true) 1});
}
void testShortCircuit() {
// A const expression that throws does not cause a compile error if it occurs
// inside an unchosen branch of an if.
// Store null in a dynamically-typed constant to avoid the type error on "+".
const dynamic nil = null;
Expect.identical(const <int>[1],
const <int>[if (true) 1, if (false) nil + 1]);
Expect.identical(const <int>[1, 2],
const <int>[if (true) 1 else nil + 1, if (false) nil + 1 else 2]);
Expect.identical(const <int, int>{1: 1}, const <int, int>{
if (true) 1: 1,
if (false) nil + 1: 9,
if (false) 9: nil + 1
});
Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
if (true) 1: 1 else nil + 1: 9,
if (false) 9: nil + 1 else 2: 2
});
Expect.identical(const <int>{1},
const <int>{if (true) 1, if (false) nil + 1});
Expect.identical(const <int>{1, 2},
const <int>{if (true) 1 else nil + 1, if (false) nil + 1 else 2});
// A const expression whose value isn't the right type does not cause a
// compile error if it occurs inside an unchosen branch.
const dynamic nonInt = "s";
Expect.identical(const <int>[1], const <int>[if (true) 1, if (false) nonInt]);
Expect.identical(const <int>[1, 2],
const <int>[if (true) 1 else nonInt, if (false) nonInt else 2]);
Expect.identical(const <int, int>{1: 1}, const <int, int>{
if (true) 1: 1,
if (false) nonInt: 9,
if (false) 9: nonInt
});
Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
if (true) 1: 1 else nonInt: 9,
if (false) 9: nonInt else 2: 2
});
Expect.identical(const <int>{1}, const <int>{if (true) 1, if (false) nonInt});
Expect.identical(const <int>{1, 2},
const <int>{if (true) 1 else nonInt, if (false) nonInt else 2});
}
void testDuplicateKeys() {
// Duplicate keys from unchosen branches are not an error.
Expect.mapEquals(map, <int, int>{
1: 1,
if (false) 1: 1,
if (true) 2: 2 else 3: 3,
3: 3
});
Expect.setEquals(set, const <int>{1, if (false) 1, if (true) 2 else 3, 3});
}
void testKeyOrder() {
// Canonicalization isn't affected by which elements are conditional.
Expect.identical(map,
const <int, int>{1: 1, if (true) 2: 2, if (false) 9: 9, 3: 3});
Expect.identical(map,
const <int, int>{if (false) 9: 9 else 1: 1, 2: 2, if (true) 3: 3});
Expect.identical(set, const <int>{1, if (true) 2, if (false) 9, 3});
Expect.identical(set, const <int>{if (false) 9 else 1, 2, if (true) 3});
// Ordering does affect canonicalization.
Expect.notIdentical(map, const <int, int>{1: 1, if (true) 3: 3, 2: 2});
Expect.notIdentical(set, const <int>{1, if (true) 3, 2});
}