Chromium Code Reviews

Unified Diff: tests/language/if_null_assignment_behavior_test.dart

Issue 1052243002: Implement the new '??=' operator in analyzer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Index: tests/language/if_null_assignment_behavior_test.dart
diff --git a/tests/language/if_null_assignment_behavior_test.dart b/tests/language/if_null_assignment_behavior_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1f52dab0a5186686c1ae8132e6038c2bcd8ac31f
--- /dev/null
+++ b/tests/language/if_null_assignment_behavior_test.dart
@@ -0,0 +1,203 @@
+// Copyright (c) 2015, 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.
+
+// Verify semantics of the ??= operator, including order of operations, by
+// keeping track of the operations performed.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+import "if_null_assignment_helper.dart" as h;
+
+bad() {
+ Expect.fail('Should not be executed');
+}
+
+var xGetValue = null;
+
+get x {
+ h.operations.add('x');
+ var tmp = xGetValue;
+ xGetValue = null;
+ return tmp;
+}
+
+void set x(value) {
+ h.operations.add('x=$value');
+}
+
+var yGetValue = null;
+
+get y {
+ h.operations.add('y');
+ var tmp = yGetValue;
+ yGetValue = null;
+ return tmp;
+}
+
+void set y(value) {
+ h.operations.add('y=$value');
+}
+
+var zGetValue = null;
+
+get z {
+ h.operations.add('z');
+ var tmp = zGetValue;
+ zGetValue = null;
+ return tmp;
+}
+
+void set z(value) {
+ h.operations.add('z=$value');
+}
+
+var fValue = null;
+
+f() {
+ h.operations.add('f()');
+ var tmp = fValue;
+ fValue = null;
+ return tmp;
+}
+
+void check(expectedValue, f(), expectedOperations) {
+ Expect.equals(expectedValue, f());
+ Expect.listEquals(expectedOperations, h.operations);
+ h.operations = [];
+}
+
+void checkThrows(expectedException, f(), expectedOperations) {
+ Expect.throws(f, expectedException);
+ Expect.listEquals(expectedOperations, h.operations);
+ h.operations = [];
+}
+
+noMethod(e) => e is NoSuchMethodError;
+
+class C {
+ final String s;
+
+ C(this.s);
+
+ @override
+ String toString() => s;
+
+ static var xGetValue = null;
+
+ static get x {
+ h.operations.add('C.x');
+ var tmp = xGetValue;
+ xGetValue = null;
+ return tmp;
+ }
+
+ static void set x(value) {
+ h.operations.add('C.x=$value');
+ }
+
+ var vGetValue = null;
+
+ get v {
+ h.operations.add('$s.v');
+ var tmp = vGetValue;
+ vGetValue = null;
+ return tmp;
+ }
+
+ void set v(value) {
+ h.operations.add('$s.v=$value');
+ }
+
+ var indexGetValue = null;
+
+ operator[](index) {
+ h.operations.add('$s[$index]');
+ var tmp = indexGetValue;
+ indexGetValue = null;
+ return tmp;
+ }
+
+ void operator[]=(index, value) {
+ h.operations.add('$s[$index]=$value');
+ }
+
+ final finalOne = 1;
+ final finalNull = null;
+
+ void instanceTest() {
+ // v ??= e is equivalent to ((x) => x == null ? v = e : x)(v)
+ vGetValue = 1; check(1, () => v ??= bad(), ['$s.v']); /// 01: ok
+ yGetValue = 1; check(1, () => v ??= y, ['$s.v', 'y', '$s.v=1']); /// 02: ok
+ check(1, () => finalOne ??= bad(), []); /// 03: static type warning
+ yGetValue = 1; checkThrows(noMethod, () => finalNull ??= y, ['y']); /// 04: static type warning
+ }
+}
+
+class D extends C {
+ D(String s) : super(s);
+
+ get v => bad();
+
+ void set v(value) {
+ bad();
+ }
+
+ void derivedInstanceTest() {
+ // super.v ??= e is equivalent to
+ // ((x) => x == null ? super.v = e : x)(super.v)
+ vGetValue = 1; check(1, () => super.v ??= bad(), ['$s.v']); /// 05: ok
+ yGetValue = 1; check(1, () => super.v ??= y, ['$s.v', 'y', '$s.v=1']); /// 06: ok
+ }
+}
+
+main() {
+ // Make sure the "none" test fails if "??=" is not implemented. This makes
+ // status files easier to maintain.
+ var _; _ ??= null;
+
+ new C('c').instanceTest();
+ new D('d').derivedInstanceTest();
+
+ // v ??= e is equivalent to ((x) => x == null ? v = e : x)(v)
+ //
+ // TODO(paulberry): I'm assuming that this rule is intended to apply in the
+ // case where v is a prefixed identifier. Confirm this with Gilad.
+ xGetValue = 1; check(1, () => x ??= bad(), ['x']); /// 07: ok
+ yGetValue = 1; check(1, () => x ??= y, ['x', 'y', 'x=1']); /// 08: ok
+ h.xGetValue = 1; check(1, () => h.x ??= bad(), ['h.x']); /// 09: ok
+ yGetValue = 1; check(1, () => h.x ??= y, ['h.x', 'y', 'h.x=1']); /// 10: ok
+ { var l = 1; check(1, () => l ??= bad(), []); } /// 11: ok
+ { var l; yGetValue = 1; check(1, () => l ??= y, ['y']); Expect.equals(1, l); } /// 12: ok
+ { final l = 1; check(1, () => l ??= bad(), []); } /// 13: static type warning
+ { final l = null; yGetValue = 1; checkThrows(noMethod, () => l ??= y, ['y']); } /// 14: static type warning
+ check(C, () => C ??= bad(), []); /// 15: static type warning
+
+ // C.v ??= e is equivalent to ((x) => x == null ? C.v = e : x)(C.v)
+ //
+ // TODO(paulberry): I'm assuming that this rule is intended to apply in the
+ // case where v is a prefixed identifier. Confirm this with Gilad.
+ C.xGetValue = 1; check(1, () => C.x ??= bad(), ['C.x']); /// 16: ok
+ yGetValue = 1; check(1, () => C.x ??= y, ['C.x', 'y', 'C.x=1']); /// 17: ok
+ h.C.xGetValue = 1; check(1, () => h.C.x ??= bad(), ['h.C.x']); /// 18: ok
+ yGetValue = 1; check(1, () => h.C.x ??= y, ['h.C.x', 'y', 'h.C.x=1']); /// 19: ok
+
+ // e1.v ??= e2 is equivalent to
+ // ((x) => ((y) => y == null ? x.v = e2 : y)(x.v))(e1)
+ xGetValue = new C('x'); xGetValue.vGetValue = 1; /// 20: ok
+ check(1, () => x.v ??= bad(), ['x', 'x.v']); /// 20: continued
+ xGetValue = new C('x'); yGetValue = 1; /// 21: ok
+ check(1, () => x.v ??= y, ['x', 'x.v', 'y', 'x.v=1']); /// 21: continued
+ fValue = new C('f()'); fValue.vGetValue = 1; /// 22: ok
+ check(1, () => f().v ??= bad(), ['f()', 'f().v']); /// 22: continued
+ fValue = new C('f()'); yGetValue = 1; /// 23: ok
+ check(1, () => f().v ??= y, ['f()', 'f().v', 'y', 'f().v=1']); /// 23: continued
+
+ // e1[e2] ??= e3 is equivalent to
+ // ((a, i) => ((x) => x == null ? a[i] = e3 : x)(a[i]))(e1, e2)
+ xGetValue = new C('x'); yGetValue = 1; xGetValue.indexGetValue = 2; /// 24: ok
+ check(2, () => x[y] ??= bad(), ['x', 'y', 'x[1]']); /// 24: continued
+ xGetValue = new C('x'); yGetValue = 1; zGetValue = 2; /// 25: ok
+ check(2, () => x[y] ??= z, ['x', 'y', 'x[1]', 'z', 'x[1]=2']); /// 25: continued
+}
« no previous file with comments | « pkg/analyzer/test/generated/static_type_warning_code_test.dart ('k') | tests/language/if_null_assignment_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine