// 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 [1, if (true) 2, 3]); // Nothing if false and no else. Expect.identical(list, const [1, if (false) 9, 2, 3]); // Else if false. Expect.identical(list, const [1, if (false) 9 else 2, 3]); // Only if. Expect.identical(const [1], const [if (true) 1]); // If at beginning. Expect.identical(list, const [if (true) 1, 2, 3]); // If in middle. Expect.identical(list, const [1, if (true) 2, 3]); // If at end. Expect.identical(list, const [1, 2, if (true) 3]); // Multiple ifs. Expect.identical(list, const [if (true) 1, if (false) 9, 2, if (true) 3]); // Cast condition. Expect.identical(const [1], const [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 [if (true) ...[1, 2], if (false) 9 else ...[3]]); // Nested if in then. Expect.identical(const [1], const [if (true) if (true) 1, if (true) if (false) 9]); // Nested if in else. Expect.identical(const [1], const [if (false) 9 else if (true) 1]); } void testMap() { // Then if true. Expect.identical(map, const {1: 1, if (true) 2: 2, 3: 3}); // Nothing if false and no else. Expect.identical(map, const {1: 1, if (false) 9: 9, 2: 2, 3: 3}); // Else if false. Expect.identical(map, const {1: 1, if (false) 9: 9 else 2: 2, 3: 3}); // Only if. Expect.identical(const {1: 1}, const {if (true) 1: 1}); // If at beginning. Expect.identical(map, const {if (true) 1: 1, 2: 2, 3: 3}); // If in middle. Expect.identical(map, const {1: 1, if (true) 2: 2, 3: 3}); // If at end. Expect.identical(map, const {1: 1, 2: 2, if (true) 3: 3}); // Multiple ifs. Expect.identical(map, const {if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3}); // Cast condition. Expect.identical(const {1: 1}, const {if (dynamicTrue) 1: 1}); // Nested spread. Expect.identical(map, const { if (true) ...{1: 1, 2: 2}, if (false) 9: 9 else ...{3: 3} }); // Nested if in then. Expect.identical(const {1: 1}, const {if (true) if (true) 1: 1, if (true) if (false) 9: 9}); // Nested if in else. Expect.identical(const {1: 1}, const {if (false) 9: 9 else if (true) 1: 1}); } void testSet() { // Then if true. Expect.identical(set, const {1, if (true) 2, 3}); // Nothing if false and no else. Expect.identical(set, const {1, if (false) 9, 2, 3}); // Else if false. Expect.identical(set, const {1, if (false) 9 else 2, 3}); // Only if. Expect.identical(const {1}, const {if (true) 1}); // If at beginning. Expect.identical(set, const {if (true) 1, 2, 3}); // If in middle. Expect.identical(set, const {1, if (true) 2, 3}); // If at end. Expect.identical(set, const {1, 2, if (true) 3}); // Multiple ifs. Expect.identical(set, const {if (true) 1, if (false) 9, 2, if (true) 3}); // Cast condition. Expect.identical(const {1}, const {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(set, const {if (true) ...[1, 2], if (false) 9 else ...[3]}); // Nested if in then. Expect.identical(const {1}, const {if (true) if (true) 1, if (true) if (false) 9}); // Nested if in else. Expect.identical(const {1}, const {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 [1], const [if (true) 1, if (false) nil + 1]); Expect.identical(const [1, 2], const [if (true) 1 else nil + 1, if (false) nil + 1 else 2]); Expect.identical(const {1: 1}, const { if (true) 1: 1, if (false) nil + 1: 9, if (false) 9: nil + 1 }); Expect.identical(const {1: 1, 2: 2}, const { if (true) 1: 1 else nil + 1: 9, if (false) 9: nil + 1 else 2: 2 }); Expect.identical(const {1}, const {if (true) 1, if (false) nil + 1}); Expect.identical(const {1, 2}, const {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 [1], const [if (true) 1, if (false) nonInt]); Expect.identical(const [1, 2], const [if (true) 1 else nonInt, if (false) nonInt else 2]); Expect.identical(const {1: 1}, const { if (true) 1: 1, if (false) nonInt: 9, if (false) 9: nonInt }); Expect.identical(const {1: 1, 2: 2}, const { if (true) 1: 1 else nonInt: 9, if (false) 9: nonInt else 2: 2 }); Expect.identical(const {1}, const {if (true) 1, if (false) nonInt}); Expect.identical(const {1, 2}, const {if (true) 1 else nonInt, if (false) nonInt else 2}); } void testDuplicateKeys() { // Duplicate keys from unchosen branches are not an error. Expect.mapEquals(map, { 1: 1, if (false) 1: 1, if (true) 2: 2 else 3: 3, 3: 3 }); Expect.setEquals(set, const {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 {1: 1, if (true) 2: 2, if (false) 9: 9, 3: 3}); Expect.identical(map, const {if (false) 9: 9 else 1: 1, 2: 2, if (true) 3: 3}); Expect.identical(set, const {1, if (true) 2, if (false) 9, 3}); Expect.identical(set, const {if (false) 9 else 1, 2, if (true) 3}); // Ordering does affect canonicalization. Expect.notIdentical(map, const {1: 1, if (true) 3: 3, 2: 2}); Expect.notIdentical(set, const {1, if (true) 3, 2}); }