| // 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'; |
| |
| 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; |
| |
| 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]); |
| |
| // 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}); |
| |
| // 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}); |
| |
| // 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}); |
| } |