Skip to content

Commit 89639ba

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Add support for set/map disambiguation for pattern elements
Part of #49749 Change-Id: Idb7f8e4bd1537abbe4133e69d2e51ae6b1e96a0d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/283862 Commit-Queue: Chloe Stefantsova <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 0c05e33 commit 89639ba

11 files changed

+512
-2
lines changed

pkg/front_end/lib/src/fasta/kernel/collections.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import '../problems.dart' show getFileUri, unsupported;
1717

1818
import '../type_inference/inference_helper.dart' show InferenceHelper;
1919

20+
import 'internal_ast.dart';
21+
2022
/// Mixin for spread and control-flow elements.
2123
///
2224
/// Spread and control-flow elements are not truly expressions and they cannot
@@ -849,6 +851,11 @@ bool isConvertibleToMapEntry(Expression element) {
849851
(element.otherwise == null ||
850852
isConvertibleToMapEntry(element.otherwise!));
851853
}
854+
if (element is IfCaseElement) {
855+
return isConvertibleToMapEntry(element.then) &&
856+
(element.otherwise == null ||
857+
isConvertibleToMapEntry(element.otherwise!));
858+
}
852859
if (element is ForElement) {
853860
return isConvertibleToMapEntry(element.body);
854861
}
@@ -883,6 +890,18 @@ MapLiteralEntry convertToMapEntry(Expression element, InferenceHelper helper,
883890
onConvertElement(element, result);
884891
return result;
885892
}
893+
if (element is IfCaseElement) {
894+
IfCaseMapEntry result = new IfCaseMapEntry(
895+
element.expression,
896+
element.patternGuard,
897+
convertToMapEntry(element.then, helper, onConvertElement),
898+
element.otherwise == null
899+
? null
900+
: convertToMapEntry(element.otherwise!, helper, onConvertElement))
901+
..fileOffset = element.fileOffset;
902+
onConvertElement(element, result);
903+
return result;
904+
}
886905
if (element is ForElement) {
887906
ForMapEntry result = new ForMapEntry(
888907
element.variables,

pkg/front_end/lib/src/fasta/kernel/internal_ast.dart

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4845,8 +4845,27 @@ class IfCaseElement extends InternalExpression with ControlFlowElement {
48454845
@override
48464846
MapLiteralEntry? toMapLiteralEntry(
48474847
void Function(TreeNode from, TreeNode to) onConvertElement) {
4848-
// TODO(cstefantsova): implement toMapLiteralEntry
4849-
throw new UnimplementedError();
4848+
MapLiteralEntry? thenEntry;
4849+
Expression then = this.then;
4850+
if (then is ControlFlowElement) {
4851+
ControlFlowElement thenElement = then;
4852+
thenEntry = thenElement.toMapLiteralEntry(onConvertElement);
4853+
}
4854+
if (thenEntry == null) return null;
4855+
MapLiteralEntry? otherwiseEntry;
4856+
Expression? otherwise = this.otherwise;
4857+
if (otherwise != null) {
4858+
if (otherwise is ControlFlowElement) {
4859+
ControlFlowElement otherwiseElement = otherwise;
4860+
otherwiseEntry = otherwiseElement.toMapLiteralEntry(onConvertElement);
4861+
}
4862+
if (otherwiseEntry == null) return null;
4863+
}
4864+
IfCaseMapEntry result =
4865+
new IfCaseMapEntry(expression, patternGuard, thenEntry, otherwiseEntry)
4866+
..fileOffset = fileOffset;
4867+
onConvertElement(this, result);
4868+
return result;
48504869
}
48514870

48524871
@override
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
test1(dynamic x, dynamic another) {
6+
return {1: 1, if (x case String y) ...another, 3: 3};
7+
}
8+
9+
test2(bool b, dynamic x, dynamic another) {
10+
return {1: 1, if (b) if (x case String y) ...another, 3: 3};
11+
}
12+
13+
test3(dynamic x, dynamic y, dynamic another) {
14+
return {1: 1, if (x case int x2) 2: x2 else if (y case int y2) ...another, 3: 3};
15+
}
16+
17+
main() {
18+
expectEquals(
19+
mapToString(test1("foo", {2: 2})),
20+
mapToString({1: 1, 2: 2, 3: 3}),
21+
);
22+
expectEquals(
23+
mapToString(test1(false, {2: 2})),
24+
mapToString({1: 1, 3: 3}),
25+
);
26+
27+
expectEquals(
28+
mapToString(test2(true, "foo", {2: 2})),
29+
mapToString({1: 1, 2: 2, 3: 3}),
30+
);
31+
expectEquals(
32+
mapToString(test2(false, "foo", {2: 2})),
33+
mapToString({1: 1, 3: 3}),
34+
);
35+
expectEquals(
36+
mapToString(test2(true, false, {2: 2})),
37+
mapToString({1: 1, 3: 3}),
38+
);
39+
40+
expectEquals(
41+
mapToString(test3(0, 1, {2: 2})),
42+
mapToString({1: 1, 2: 0, 3: 3}),
43+
);
44+
expectEquals(
45+
mapToString(test3("foo", 1, {2: 2})),
46+
mapToString({1: 1, 2: 2, 3: 3}),
47+
);
48+
expectEquals(
49+
mapToString(test3("foo", "bar", {2, 2})),
50+
mapToString({1: 1, 3: 3}),
51+
);
52+
}
53+
54+
expectEquals(x, y) {
55+
if (x != y) {
56+
throw "Expected '${x}' to be equals to '${y}'.";
57+
}
58+
}
59+
60+
mapToString(Map map) {
61+
List<String> entryStrings = [];
62+
for (var entry in map.entries) {
63+
entryStrings.add("${entry.key}:${entry.value}");
64+
}
65+
entryStrings.sort();
66+
return "{${entryStrings.join(',')}}";
67+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:collection" as col;
5+
6+
static method test1(dynamic x, dynamic another) → dynamic {
7+
return block {
8+
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
9+
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
10+
core::String y;
11+
final dynamic #0#0 = x;
12+
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t2 = y = #0#0{core::String} in true))
13+
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
14+
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
15+
} =>#t1;
16+
}
17+
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
18+
return block {
19+
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
20+
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
21+
if(b) {
22+
core::String y;
23+
final dynamic #0#0 = x;
24+
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t4 = y = #0#0{core::String} in true))
25+
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
26+
}
27+
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
28+
} =>#t3;
29+
}
30+
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
31+
return block {
32+
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
33+
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
34+
core::int x2;
35+
final dynamic #1#0 = x;
36+
if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t6 = x2 = #1#0{core::int} in true))
37+
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
38+
else {
39+
core::int y2;
40+
final dynamic #0#0 = y;
41+
if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = y2 = #0#0{core::int} in true))
42+
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
43+
}
44+
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
45+
} =>#t5;
46+
}
47+
static method main() → dynamic {
48+
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
49+
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
50+
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
51+
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
52+
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
53+
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
54+
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
55+
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
56+
final core::Set<core::int> #t8 = col::LinkedHashSet::•<core::int>();
57+
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
58+
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
59+
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
60+
}
61+
static method expectEquals(dynamic x, dynamic y) → dynamic {
62+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
63+
throw "Expected '${x}' to be equals to '${y}'.";
64+
}
65+
}
66+
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
67+
core::List<core::String> entryStrings = <core::String>[];
68+
for (core::MapEntry<dynamic, dynamic> entry in map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}) {
69+
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
70+
}
71+
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
72+
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
73+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:collection" as col;
5+
6+
static method test1(dynamic x, dynamic another) → dynamic {
7+
return block {
8+
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
9+
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
10+
core::String y;
11+
final dynamic #0#0 = x;
12+
if(#0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t2 = y = #0#0{core::String} in true))
13+
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
14+
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
15+
} =>#t1;
16+
}
17+
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
18+
return block {
19+
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
20+
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
21+
if(b) {
22+
core::String y;
23+
final dynamic #0#0 = x;
24+
if(#0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t4 = y = #0#0{core::String} in true))
25+
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
26+
}
27+
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
28+
} =>#t3;
29+
}
30+
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
31+
return block {
32+
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
33+
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
34+
core::int x2;
35+
final dynamic #1#0 = x;
36+
if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t6 = x2 = #1#0{core::int} in true))
37+
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
38+
else {
39+
core::int y2;
40+
final dynamic #0#0 = y;
41+
if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = y2 = #0#0{core::int} in true))
42+
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
43+
}
44+
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
45+
} =>#t5;
46+
}
47+
static method main() → dynamic {
48+
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
49+
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
50+
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
51+
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
52+
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
53+
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
54+
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
55+
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
56+
final core::Set<core::int> #t8 = new col::_Set::•<core::int>();
57+
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
58+
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
59+
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
60+
}
61+
static method expectEquals(dynamic x, dynamic y) → dynamic {
62+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
63+
throw "Expected '${x}' to be equals to '${y}'.";
64+
}
65+
}
66+
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
67+
core::List<core::String> entryStrings = core::_GrowableList::•<core::String>(0);
68+
{
69+
core::Iterator<core::MapEntry<dynamic, dynamic>> :sync-for-iterator = map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}.{core::Iterable::iterator}{core::Iterator<core::MapEntry<dynamic, dynamic>>};
70+
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
71+
core::MapEntry<dynamic, dynamic> entry = :sync-for-iterator.{core::Iterator::current}{core::MapEntry<dynamic, dynamic>};
72+
{
73+
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
74+
}
75+
}
76+
}
77+
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
78+
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
79+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
test1(dynamic x, dynamic another) {}
2+
test2(bool b, dynamic x, dynamic another) {}
3+
test3(dynamic x, dynamic y, dynamic another) {}
4+
main() {}
5+
expectEquals(x, y) {}
6+
mapToString(Map map) {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
expectEquals(x, y) {}
2+
main() {}
3+
mapToString(Map map) {}
4+
test1(dynamic x, dynamic another) {}
5+
test2(bool b, dynamic x, dynamic another) {}
6+
test3(dynamic x, dynamic y, dynamic another) {}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:collection" as col;
5+
6+
static method test1(dynamic x, dynamic another) → dynamic {
7+
return block {
8+
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
9+
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
10+
core::String y;
11+
final dynamic #0#0 = x;
12+
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t2 = y = #0#0{core::String} in true))
13+
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
14+
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
15+
} =>#t1;
16+
}
17+
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
18+
return block {
19+
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
20+
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
21+
if(b) {
22+
core::String y;
23+
final dynamic #0#0 = x;
24+
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t4 = y = #0#0{core::String} in true))
25+
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
26+
}
27+
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
28+
} =>#t3;
29+
}
30+
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
31+
return block {
32+
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
33+
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
34+
core::int x2;
35+
final dynamic #1#0 = x;
36+
if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t6 = x2 = #1#0{core::int} in true))
37+
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
38+
else {
39+
core::int y2;
40+
final dynamic #0#0 = y;
41+
if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = y2 = #0#0{core::int} in true))
42+
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
43+
}
44+
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
45+
} =>#t5;
46+
}
47+
static method main() → dynamic {
48+
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
49+
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
50+
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
51+
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
52+
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
53+
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
54+
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
55+
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
56+
final core::Set<core::int> #t8 = col::LinkedHashSet::•<core::int>();
57+
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
58+
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
59+
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
60+
}
61+
static method expectEquals(dynamic x, dynamic y) → dynamic {
62+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
63+
throw "Expected '${x}' to be equals to '${y}'.";
64+
}
65+
}
66+
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
67+
core::List<core::String> entryStrings = <core::String>[];
68+
for (core::MapEntry<dynamic, dynamic> entry in map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}) {
69+
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
70+
}
71+
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
72+
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
73+
}

0 commit comments

Comments
 (0)