Add of constructors to collections.

Change-Id: Ic9a180cbb758cf8fe51369d904fa4b51fd1b8e27
Reviewed-on: https://dart-review.googlesource.com/44480
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Kevin Moore <kevmoo@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
Reviewed-by: Leaf Petersen <leafp@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2018-03-13 12:57:49 +00:00 committed by commit-bot@chromium.org
parent 019dae1904
commit 00dae36b47
16 changed files with 416 additions and 49 deletions

View file

@ -75,6 +75,9 @@ the assignment to `y`.
* `MapBase`: added `mapToString`.
* `LinkedHashMap` no longer implements `HashMap`
* `LinkedHashSet` no longer implements `HashSet`.
* Added `of` constructor to `Queue`, `ListQueue`,
`DoubleLinkedQueue`, `HashSet`, `LinkedHashSet`, `SplayTreeSet`,
`Map`, `HashMap`, `LinkedHashMap`, `SplayTreeMap`.
* `dart:convert`
@ -114,6 +117,7 @@ the assignment to `y`.
* *Note*: if a class extends `IterableBase`, `ListBase`, `SetBase` or
`MapBase` (or uses the corresponding mixins) from `dart:collection`, the
new members are implemented automatically.
* Added `of` constructor to `List`, `Set`, `Map`.
* Renamed `double.INFINITY`, `double.NEGATIVE_INFINITY`, `double.NAN`,
`double.MAX_FINITE` and `double.MIN_POSITIVE`
to `double.infinity`, `double.negativeInfinity`, `double.nan`,

View file

@ -22,7 +22,7 @@ class Map<K, V> {
@patch
factory Map.unmodifiable(Map other) {
return new UnmodifiableMapView<K, V>(new Map.from(other));
return new UnmodifiableMapView<K, V>(new Map<K, V>.from(other));
}
@patch

View file

@ -299,7 +299,7 @@ class JsLinkedHashMap<K, V> extends MapBase<K, V>
return -1;
}
String toString() => Maps.mapToString(this);
String toString() => MapBase.mapToString(this);
LinkedHashMapCell _getTableCell(var table, var key) {
return JS('var', '#[#]', table, key);

View file

@ -100,6 +100,9 @@ abstract class HashMap<K, V> implements Map<K, V> {
/**
* Creates a [HashMap] that contains all key/value pairs of [other].
*
* The keys must all be instances of [K] and the values of [V].
* The [other] map itself can have any type.
*/
factory HashMap.from(Map other) {
Map<K, V> result = new HashMap<K, V>();
@ -109,6 +112,11 @@ abstract class HashMap<K, V> implements Map<K, V> {
return result;
}
/**
* Creates a [HashMap] that contains all key/value pairs of [other].
*/
factory HashMap.of(Map<K, V> other) => new HashMap<K, V>()..addAll(other);
/**
* Creates a [HashMap] where the keys and values are computed from the
* [iterable].

View file

@ -129,13 +129,14 @@ abstract class HashSet<E> implements Set<E> {
* two entries that are equal, but not identical, then the first one is
* the one in the resulting set.
*
* All the [elements] should be assignable to [E].
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `Set`, for example as:
*
* Set<SuperType> superSet = ...;
* Set<SubType> subSet =
* new HashSet<SubType>.from(superSet.where((e) => e is SubType));
* ```dart
* Set<SuperType> superSet = ...;
* Set<SubType> subSet =
* new HashSet<SubType>.from(superSet.whereType<SubType>());
* ```
*/
factory HashSet.from(Iterable elements) {
HashSet<E> result = new HashSet<E>();
@ -145,6 +146,17 @@ abstract class HashSet<E> implements Set<E> {
return result;
}
/**
* Create a hash set containing all [elements].
*
* Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
* to the set. The elements are added in order. If [elements] contains
* two entries that are equal, but not identical, then the first one is
* the one in the resulting set.
*/
factory HashSet.of(Iterable<E> elements) =>
new HashSet<E>()..addAll(elements);
/**
* Provides an iterator that iterates over the elements of this set.
*

View file

@ -87,6 +87,9 @@ abstract class LinkedHashMap<K, V> implements Map<K, V> {
/**
* Creates a [LinkedHashMap] that contains all key value pairs of [other].
*
* The keys must all be instances of [K] and the values to [V].
* The [other] map itself can have any type.
*/
factory LinkedHashMap.from(Map other) {
LinkedHashMap<K, V> result = new LinkedHashMap<K, V>();
@ -96,6 +99,12 @@ abstract class LinkedHashMap<K, V> implements Map<K, V> {
return result;
}
/**
* Creates a [LinkedHashMap] that contains all key value pairs of [other].
*/
factory LinkedHashMap.of(Map<K, V> other) =>
new LinkedHashMap<K, V>()..addAll(other);
/**
* Creates a [LinkedHashMap] where the keys and values are computed from the
* [iterable].

View file

@ -95,7 +95,7 @@ abstract class LinkedHashSet<E> implements Set<E> {
* Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
* element of `elements` to this set in the order they are iterated.
*
* All the [elements] should be assignable to [E].
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type,
* so this constructor can be used to down-cast a `Set`, for example as:
*
@ -111,6 +111,15 @@ abstract class LinkedHashSet<E> implements Set<E> {
return result;
}
/**
* Create a linked hash set from [elements].
*
* Creates a linked hash set as by `new LinkedHashSet<E>()` and adds each
* element of `elements` to this set in the order they are iterated.
*/
factory LinkedHashSet.of(Iterable<E> elements) =>
new LinkedHashSet<E>()..addAll(elements);
/**
* Executes a function on each element of the set.
*

View file

@ -28,9 +28,26 @@ abstract class Queue<E> implements EfficientLengthIterable<E> {
*
* The element order in the queue is as if the elements were added using
* [addLast] in the order provided by [elements.iterator].
*
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `Queue`, for example as:
* ```dart
* Queue<SuperType> superQueue = ...;
* Queue<SubType> subQueue =
* new Queue<SubType>.from(superSet.whereType<SubType>());
* ```
*/
factory Queue.from(Iterable elements) = ListQueue<E>.from;
/**
* Creates a queue from [elements].
*
* The element order in the queue is as if the elements were added using
* [addLast] in the order provided by [elements.iterator].
*/
factory Queue.of(Iterable<E> elements) = ListQueue<E>.of;
/**
* Adapts [source] to be a `Queue<T>`.
*
@ -312,6 +329,15 @@ class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> {
*
* The element order in the queue is as if the elements were added using
* [addLast] in the order provided by [elements.iterator].
*
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `Queue`, for example as:
* ```dart
* Queue<SuperType> superQueue = ...;
* Queue<SubType> subQueue =
* new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
* ```
*/
factory DoubleLinkedQueue.from(Iterable elements) {
Queue<E> list = new DoubleLinkedQueue<E>();
@ -321,6 +347,15 @@ class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> {
return list;
}
/**
* Creates a double-linked queue from [elements].
*
* The element order in the queue is as if the elements were added using
* [addLast] in the order provided by [elements.iterator].
*/
factory DoubleLinkedQueue.of(Iterable<E> elements) =>
new DoubleLinkedQueue<E>()..addAll(elements);
Queue<R> cast<R>() {
Queue<Object> self = this;
return self is Queue<R> ? self : Queue.castFrom<E, R>(this);
@ -579,7 +614,14 @@ class ListQueue<E> extends ListIterable<E> implements Queue<E> {
* The elements are added to the queue, as by [addLast], in the order given by
* `elements.iterator`.
*
* All `elements` should be assignable to [E].
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `Queue`, for example as:
* ```dart
* Queue<SuperType> superQueue = ...;
* Queue<SubType> subQueue =
* new ListQueue<SubType>.from(superQueue.whereType<SubType>());
* ```
*/
factory ListQueue.from(Iterable elements) {
if (elements is List) {
@ -604,6 +646,15 @@ class ListQueue<E> extends ListIterable<E> implements Queue<E> {
}
}
/**
* Create a `ListQueue` from [elements].
*
* The elements are added to the queue, as by [addLast], in the order given by
* `elements.iterator`.
*/
factory ListQueue.of(Iterable<E> elements) =>
new ListQueue<E>()..addAll(elements);
// Iterable interface.
Queue<R> cast<R>() {

View file

@ -295,6 +295,9 @@ class SplayTreeMap<K, V> extends _SplayTree<K, _SplayTreeMapNode<K, V>>
/**
* Creates a [SplayTreeMap] that contains all key/value pairs of [other].
*
* The keys must all be instances of [K] and the values of [V].
* The [other] map itself can have any type.
*/
factory SplayTreeMap.from(Map other,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
@ -305,6 +308,13 @@ class SplayTreeMap<K, V> extends _SplayTree<K, _SplayTreeMapNode<K, V>>
return result;
}
/**
* Creates a [SplayTreeMap] that contains all key/value pairs of [other].
*/
factory SplayTreeMap.of(Map<K, V> other,
[int compare(K key1, K key2), bool isValidKey(potentialKey)]) =>
new SplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
/**
* Creates a [SplayTreeMap] where the keys and values are computed from the
* [iterable].
@ -721,7 +731,15 @@ class SplayTreeSet<E> extends _SplayTree<E, _SplayTreeNode<E>>
*
* The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
*
* All the [elements] should be valid as arguments to the [compare] function.
* All the [elements] should be instances of [E] and valid arguments to
* [compare].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `Set`, for example as:
* ```dart
* Set<SuperType> superSet = ...;
* Set<SubType> subSet =
* new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
* ```
*/
factory SplayTreeSet.from(Iterable elements,
[int compare(E key1, E key2), bool isValidKey(potentialKey)]) {
@ -733,6 +751,17 @@ class SplayTreeSet<E> extends _SplayTree<E, _SplayTreeNode<E>>
return result;
}
/**
* Creates a [SplayTreeSet] from [elements].
*
* The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
*
* All the [elements] should be valid as arguments to the [compare] function.
*/
factory SplayTreeSet.of(Iterable<E> elements,
[int compare(E key1, E key2), bool isValidKey(potentialKey)]) =>
new SplayTreeSet(compare, isValidKey)..addAll(elements);
Set<T> _newSet<T>() =>
new SplayTreeSet<T>((T a, T b) => _comparator(a as E, b as E), _validKey);

View file

@ -114,11 +114,31 @@ abstract class List<E> implements EfficientLengthIterable<E> {
*
* The [Iterator] of [elements] provides the order of the elements.
*
* This constructor returns a growable list when [growable] is true;
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `List`, for example as:
* ```dart
* List<SuperType> superList = ...;
* List<SubType> subList =
* new List<SubType>.from(superList.whereType<SubType>());
* ```
*
* This constructor creates a growable list when [growable] is true;
* otherwise, it returns a fixed-length list.
*/
external factory List.from(Iterable elements, {bool growable: true});
/**
* Creates a list from [elements].
*
* The [Iterator] of [elements] provides the order of the elements.
*
* This constructor creates a growable list when [growable] is true;
* otherwise, it returns a fixed-length list.
*/
factory List.of(Iterable<E> elements, {bool growable: true}) =>
new List<E>.from(elements, growable: growable);
/**
* Generates a list of values.
*

View file

@ -45,7 +45,7 @@ abstract class Map<K, V> {
* Creates a [LinkedHashMap] instance that contains all key/value pairs of
* [other].
*
* The keys must all be assignable to [K] and the values to [V].
* The keys must all be instances of [K] and the values of [V].
* The [other] map itself can have any type.
*
* A `LinkedHashMap` requires the keys to implement compatible
@ -54,10 +54,19 @@ abstract class Map<K, V> {
*/
factory Map.from(Map other) = LinkedHashMap<K, V>.from;
/**
* Creates a [LinkedHashMap] with the same keys and values as [other].
*
* A `LinkedHashMap` requires the keys to implement compatible
* `operator==` and `hashCode`, and it allows `null` as a key.
* It iterates in key insertion order.
*/
factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;
/**
* Creates an unmodifiable hash based map containing the entries of [other].
*
* The keys must all be assignable to [K] and the values to [V].
* The keys must all be instances of [K] and the values of [V].
* The [other] map itself can have any type.
*
* The map requires the keys to implement compatible

View file

@ -61,7 +61,7 @@ abstract class Set<E> extends EfficientLengthIterable<E> {
/**
* Creates a [Set] that contains all [elements].
*
* All the [elements] should be assignable to [E].
* All the [elements] should be instances of [E].
* The `elements` iterable itself can have any type,
* so this constructor can be used to down-cast a `Set`, for example as:
*
@ -78,6 +78,18 @@ abstract class Set<E> extends EfficientLengthIterable<E> {
*/
factory Set.from(Iterable elements) = LinkedHashSet<E>.from;
/**
* Creates a [Set] from [elements].
*
* The created [Set] is a [LinkedHashSet]. As such, it considers elements that
* are equal (using [==]) to be indistinguishable, and requires them to
* have a compatible [Object.hashCode] implementation.
*
* The set is equivalent to one created by
* `new LinkedHashSet<E>.of(elements)`.
*/
factory Set.of(Iterable<E> elements) = LinkedHashSet<E>.of;
/**
* Adapts [source] to be a `Set<T>`.
*

View file

@ -5,40 +5,89 @@
library collection.from.test;
import "package:expect/expect.dart";
import 'dart:collection' show Queue;
class CollectionFromTest {
static testMain() {
var set = new Set<int>();
set.add(1);
set.add(2);
set.add(4);
check(set, new List<int>.from(set));
check(set, new List.from(set));
check(set, new Queue<int>.from(set));
check(set, new Queue.from(set));
check(set, new Set<int>.from(set));
check(set, new Set.from(set));
}
static check(Iterable initial, Iterable other) {
Expect.equals(3, initial.length);
Expect.equals(initial.length, other.length);
int initialSum = 0;
int otherSum = 0;
initial.forEach((e) {
initialSum += e;
});
other.forEach((e) {
otherSum += e;
});
Expect.equals(4 + 2 + 1, otherSum);
Expect.equals(otherSum, initialSum);
}
}
import 'dart:collection';
main() {
CollectionFromTest.testMain();
for (Iterable<num> elements in [
new Set<num>(),
<num>[],
const <num>[],
const <num, int>{}.keys,
const <int, num>{}.values,
new Iterable<num>.generate(0),
new Set<num>()..add(1)..add(2)..add(4),
<num>[1, 2, 4],
new Iterable<num>.generate(3, (i) => [1, 2, 4][i]),
const <num>[1, 2, 4],
const <num, int>{1: 0, 2: 0, 4: 0}.keys,
const <int, num>{1: 1, 2: 2, 4: 4}.values,
]) {
int elementCount = elements.length;
check(elements, new List<num>.from(elements));
check(elements, new List<int>.from(elements));
check(elements, new List<Object>.from(elements));
check(elements, new List<num>.from(elements, growable: true));
check(elements, new List<int>.from(elements, growable: true));
check(elements, new List<Object>.from(elements, growable: true));
check(elements, new List<num>.from(elements, growable: false));
check(elements, new List<int>.from(elements, growable: false));
check(elements, new List<Object>.from(elements, growable: false));
check(elements, new Queue<num>.from(elements));
check(elements, new Queue<int>.from(elements));
check(elements, new Queue<Object>.from(elements));
check(elements, new ListQueue<num>.from(elements));
check(elements, new ListQueue<int>.from(elements));
check(elements, new ListQueue<Object>.from(elements));
check(elements, new DoubleLinkedQueue<num>.from(elements));
check(elements, new DoubleLinkedQueue<int>.from(elements));
check(elements, new DoubleLinkedQueue<Object>.from(elements));
check(elements, new Set<num>.from(elements));
check(elements, new Set<int>.from(elements));
check(elements, new Set<Object>.from(elements));
check(elements, new HashSet<num>.from(elements));
check(elements, new HashSet<int>.from(elements));
check(elements, new HashSet<Object>.from(elements));
check(elements, new LinkedHashSet<num>.from(elements));
check(elements, new LinkedHashSet<int>.from(elements));
check(elements, new LinkedHashSet<Object>.from(elements));
check(elements, new SplayTreeSet<num>.from(elements));
check(elements, new SplayTreeSet<int>.from(elements));
check(elements, new SplayTreeSet<Object>.from(elements));
// Sanity check that elements didn't change.
Expect.equals(elementCount, elements.length);
// Lists may be growable or not growable.
{
var list = new List<num>.from(elements, growable: true);
Expect.equals(elementCount, list.length);
list.add(42);
Expect.equals(elementCount + 1, list.length);
}
{
var list = new List<num>.from(elements);
Expect.equals(elementCount, list.length);
list.add(42);
Expect.equals(elementCount + 1, list.length);
}
{
var list = new List<num>.from(elements, growable: false);
Expect.equals(elementCount, list.length);
Expect.throwsUnsupportedError(() {
list.add(42);
});
Expect.equals(elementCount, list.length);
}
}
}
void check(Iterable<num> initial, Iterable other) {
Expect.equals(initial.length, other.length);
for (var element in other) {
initial.contains(element);
}
for (var element in initial) {
other.contains(element);
}
}

View file

@ -0,0 +1,84 @@
// Copyright (c) 2018, 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.
library collection.from.test;
import "package:expect/expect.dart";
import 'dart:collection';
main() {
for (Iterable<num> elements in [
new Set<num>(),
<num>[],
const <num>[],
const <num, int>{}.keys,
const <int, num>{}.values,
new Iterable<num>.generate(0),
new Set<num>()..add(1)..add(2)..add(4),
<num>[1, 2, 4],
new Iterable<num>.generate(3, (i) => [1, 2, 4][i]),
const <num>[1, 2, 4],
const <num, int>{1: 0, 2: 0, 4: 0}.keys,
const <int, num>{1: 1, 2: 2, 4: 4}.values,
]) {
String sourceType = elements.runtimeType.toString();
check(sourceType, elements, new List<num>.of(elements));
Expect.throwsTypeError(() => new List<int>.of(elements));
check(sourceType, elements, new List<Object>.of(elements));
check(sourceType, elements, new Queue<num>.of(elements));
Expect.throwsTypeError(() => new Queue<int>.of(elements));
check(sourceType, elements, new Queue<Object>.of(elements));
check(sourceType, elements, new ListQueue<num>.of(elements));
Expect.throwsTypeError(() => new ListQueue<int>.of(elements));
check(sourceType, elements, new ListQueue<Object>.of(elements));
check(sourceType, elements, new DoubleLinkedQueue<num>.of(elements));
Expect.throwsTypeError(() => new DoubleLinkedQueue<int>.of(elements));
check(sourceType, elements, new DoubleLinkedQueue<Object>.of(elements));
check(sourceType, elements, new Set<num>.of(elements));
Expect.throwsTypeError(() => new Set<int>.of(elements));
check(sourceType, elements, new Set<Object>.of(elements));
check(sourceType, elements, new HashSet<num>.of(elements));
Expect.throwsTypeError(() => new HashSet<int>.of(elements));
check(sourceType, elements, new HashSet<Object>.of(elements));
check(sourceType, elements, new LinkedHashSet<num>.of(elements));
Expect.throwsTypeError(() => new LinkedHashSet<int>.of(elements));
check(sourceType, elements, new LinkedHashSet<Object>.of(elements));
check(sourceType, elements, new SplayTreeSet<num>.of(elements));
Expect.throwsTypeError(() => new SplayTreeSet<int>.of(elements));
check(sourceType, elements, new SplayTreeSet<Object>.of(elements));
// Inference applies to the `of` constructor, unlike the `from` constructor.
Expect.isTrue(new List.of(elements) is Iterable<num>);
Expect.isTrue(new Queue.of(elements) is Iterable<num>);
Expect.isTrue(new ListQueue.of(elements) is Iterable<num>);
Expect.isTrue(new DoubleLinkedQueue.of(elements) is Iterable<num>);
Expect.isTrue(new Set.of(elements) is Iterable<num>);
Expect.isTrue(new HashSet.of(elements) is Iterable<num>);
Expect.isTrue(new LinkedHashSet.of(elements) is Iterable<num>);
Expect.isTrue(new SplayTreeSet.of(elements) is Iterable<num>);
Expect.isTrue(new List.of(elements) is! Iterable<int>);
Expect.isTrue(new Queue.of(elements) is! Iterable<int>);
Expect.isTrue(new ListQueue.of(elements) is! Iterable<int>);
Expect.isTrue(new DoubleLinkedQueue.of(elements) is! Iterable<int>);
Expect.isTrue(new Set.of(elements) is! Iterable<int>);
Expect.isTrue(new HashSet.of(elements) is! Iterable<int>);
Expect.isTrue(new LinkedHashSet.of(elements) is! Iterable<int>);
Expect.isTrue(new SplayTreeSet.of(elements) is! Iterable<int>);
}
}
void check(String sourceType, Iterable<num> source, Iterable target) {
String targetType = target.runtimeType.toString();
String name = "$sourceType->$targetType";
Expect.equals(source.length, target.length, "$name.length");
for (var element in target) {
Expect.isTrue(source.contains(element), "$name:$element in source");
}
for (var element in source) {
Expect.isTrue(target.contains(element), "$name:$element in target");
}
}

View file

@ -1,7 +1,6 @@
# Copyright (c) 2017, 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.
iterable_where_type_test: RuntimeError # Disabled. Issue 32463
[ $compiler == dart2analyzer ]
@ -323,6 +322,9 @@ shuffle_test: RuntimeError
[ $compiler == dart2js && !$fasta ]
*: SkipByDesign
[ $compiler == dart2js && $strong ]
collection_of_test: RuntimeError
[ $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta ]
iterable_element_at_test/static: MissingCompileTimeError
@ -524,6 +526,9 @@ symbol_reserved_word_test/12: RuntimeError # Issue 29921
symbol_test/none: RuntimeError # Issue 29921
typed_data_with_limited_ints_test: Skip # dartdevc doesn't know about --limit-ints-to-64-bits
[ $runtime == vm && !$strong ]
collection_of_test: RuntimeError
[ !$checked && !$strong ]
core_runtime_types_static_test: MissingCompileTimeError
splay_tree_test/01: MissingCompileTimeError

View file

@ -0,0 +1,66 @@
// Copyright (c) 2011, 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.
library map.from.test;
import "package:expect/expect.dart";
import 'dart:collection';
main() {
for (Map<num, num> map in [
<num, num>{},
const <num, num>{},
new HashMap<num, num>(),
new LinkedHashMap<num, num>(),
new SplayTreeMap<num, num>(),
<num, num>{1: 11, 2: 12, 4: 14},
const <num, num>{1: 11, 2: 12, 4: 14},
new Map<num, num>()
..[1] = 11
..[2] = 12
..[3] = 13,
new HashMap<num, num>()
..[1] = 11
..[2] = 12
..[3] = 13,
new LinkedHashMap<num, num>()
..[1] = 11
..[2] = 12
..[3] = 13,
new SplayTreeMap<num, num>()
..[1] = 11
..[2] = 12
..[3] = 13,
]) {
expectThrows(void operation()) {
// Allow CastError as well as TypeError. Dart2js creates a CastError
// here for some reason, and it's not wront.
Expect.throws(operation, (e) => e is TypeError || e is CastError);
}
var sourceType = map.runtimeType.toString();
check(sourceType, map, new Map<Object, Object>.of(map));
check(sourceType, map, new Map<num, num>.of(map));
expectThrows(() => new Map<int, int>.of(map));
check(sourceType, map, new HashMap<Object, Object>.of(map));
check(sourceType, map, new HashMap<num, num>.of(map));
expectThrows(() => new HashMap<int, int>.of(map));
check(sourceType, map, new LinkedHashMap<Object, Object>.of(map));
check(sourceType, map, new LinkedHashMap<num, num>.of(map));
expectThrows(() => new LinkedHashMap<int, int>.of(map));
check(sourceType, map, new SplayTreeMap<Object, Object>.of(map));
check(sourceType, map, new SplayTreeMap<num, num>.of(map));
expectThrows(() => new SplayTreeMap<int, int>.of(map));
}
}
check(String sourceType, Map<num, num> expect, Map actual) {
var targetType = actual.runtimeType.toString();
var name = "$sourceType->$targetType";
Expect.equals(expect.length, actual.length, "$name.length");
for (var key in expect.keys) {
Expect.isTrue(actual.containsKey(key), "$name?[$key]");
Expect.equals(expect[key], actual[key], "$name[$key]");
}
}