// 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.

// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections

// Test how control flow interacts with inference.
import 'package:expect/expect.dart';

import 'utils.dart';

void main() {
  testBottomUpInference();
  testTopDownInference();
}

void testBottomUpInference() {
  // Lists.
  expectListOf<int>([if (true) 1]);
  expectListOf<int>([if (true) 1 else 2]);
  expectListOf<num>([if (true) 1 else 0.2]);
  expectListOf<int>([if (true) 1, 2]);
  expectListOf<num>([if (true) 1, 0.2]);
  expectListOf<dynamic>([if (true) ...[]]);
  expectListOf<int>([if (true) ...<int>[]]);

  // Maps.
  expectMapOf<int, int>({if (true) 1: 1});
  expectMapOf<int, int>({if (true) 1: 1 else 2: 2});
  expectMapOf<num, num>({if (true) 1: 0.1 else 0.2: 2});
  expectMapOf<int, int>({if (true) 1: 1, 2: 2});
  expectMapOf<num, num>({if (true) 1: 0.1, 0.2: 2});
  expectMapOf<dynamic, dynamic>({if (true) ...{}});
  expectMapOf<int, int>({if (true) ...<int, int>{}});

  // Sets.
  expectSetOf<int>({if (true) 1});
  expectSetOf<int>({if (true) 1 else 2});
  expectSetOf<num>({if (true) 1 else 0.2});
  expectSetOf<int>({if (true) 1, 2});
  expectSetOf<num>({if (true) 1, 0.2});
  expectSetOf<dynamic>({if (true) ...[]});
  expectSetOf<int>({if (true) ...<int>[]});

  // If a nested iterable's type is dynamic, the element type is dynamic.
  expectListOf<dynamic>([if (true) ...([] as dynamic)]);
  expectSetOf<dynamic>({1, if (true) ...([] as dynamic)});

  // If a nested maps's type is dynamic, the key and value types are dynamic.
  expectMapOf<dynamic, dynamic>({1: 1, if (true) ...({} as dynamic)});
}

void testTopDownInference() {
  // Lists.

  // The context element type is pushed into the branches.
  Expect.listEquals(<int>[1], <int>[if (true) expectInt(1)]);
  Expect.listEquals(<int>[1], <int>[if (false) 9 else expectInt(1)]);

  // Bottom up-inference from elements is not pushed back down into branches.
  Expect.listEquals(<int>[1, 2], [1, if (true) expectDynamic(2)]);
  Expect.listEquals(<int>[1, 2], [1, if (false) 9 else expectDynamic(2)]);

  // Maps.

  // The context element type is pushed into the branches.
  Expect.mapEquals(<int, String>{1: "s"},
      <int, String>{if (true) expectInt(1): expectString("s")});

  // Bottom up-inference from elements is not pushed back down into branches.
  Expect.mapEquals(<int, String>{1: "s", 2: "t"},
      {1: "s", if (true) expectDynamic(2): expectDynamic("t")});

  // Sets.

  // The context element type is pushed into the branches.
  Expect.setEquals(<int>{1}, <int>{if (true) expectInt(1)});
  Expect.setEquals(<int>{1}, <int>{if (false) 9 else expectInt(1)});

  // Bottom up-inference from elements is not pushed back down into branches.
  Expect.setEquals(<int>{1, 2}, {1, if (true) expectDynamic(2)});
  Expect.setEquals(<int>{1, 2}, {1, if (false) 9 else expectDynamic(2)});
}
