| // Copyright (c) 2022, 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"; |
| |
| main() { |
| Expect.equals('0: int', differentFinalityNotUsedInBody(0, 0)); |
| Expect.equals('1: final int', differentFinalityNotUsedInBody(1, 1)); |
| Expect.equals('2: var', differentFinalityNotUsedInBody(2, 2)); |
| Expect.equals('3: final', differentFinalityNotUsedInBody(3, 3)); |
| |
| Expect.equals('0: int', differentTypeNotUsedInBody(0, 0)); |
| Expect.equals('true: bool', differentTypeNotUsedInBody(1, true)); |
| Expect.equals('s: var', differentTypeNotUsedInBody(2, 's')); |
| |
| Expect.equals('unique: unique', differentVariableNotUsedInBody(0, 'unique')); |
| Expect.equals('in: inTwo', differentVariableNotUsedInBody(1, 'in')); |
| Expect.equals('two: inTwo', differentVariableNotUsedInBody(2, 'two')); |
| |
| Expect.equals('one: var', sharedAnnotatedAndUnannotated(0, 'one')); |
| Expect.equals('two: Object', sharedAnnotatedAndUnannotated(1, 'two')); |
| |
| Expect.equals('one: var', sharedAnnotatedAndPromotionInferred(0, 'one')); |
| Expect.equals('two: String', sharedAnnotatedAndPromotionInferred(1, 'two')); |
| |
| Expect.equals('0: 0: list', sharedDifferentContext([0, true])); |
| Expect.equals('1: 1: map', sharedDifferentContext({'a': 1, 'b': true})); |
| Expect.equals('2: 2: record', sharedDifferentContext((a: 2, b: true))); |
| Expect.equals('3: 3: nested', sharedDifferentContext((a: 3, b: [true]))); |
| } |
| |
| /// OK if variables in different cases have different finality if not used in |
| /// the body. |
| Object? differentFinalityNotUsedInBody(int caseKey, Object value) { |
| switch ((caseKey, value)) { |
| case (0, int x) when _guard(x, 'int'): |
| case (1, final int x) when _guard(x, 'final int'): |
| case (2, var x) when _guard(x, 'var'): |
| case (3, final x) when _guard(x, 'final'): |
| return _matchedCase(); |
| default: |
| Expect.fail('Should not reach this.'); |
| } |
| } |
| |
| /// OK if variables in different cases have different types if not used in the |
| /// body. |
| Object? differentTypeNotUsedInBody(int caseKey, Object value) { |
| switch ((caseKey, value)) { |
| case (0, int x) when _guard(x, 'int'): |
| case (1, bool x) when _guard(x, 'bool'): |
| case (2, var x) when _guard(x, 'var'): // Infer Object. |
| return _matchedCase(); |
| default: |
| Expect.fail('Should not reach this.'); |
| } |
| } |
| |
| /// OK if some variables only exist in some cases if they aren't used in the |
| /// body. |
| Object? differentVariableNotUsedInBody(int caseKey, Object value) { |
| switch ((caseKey, value)) { |
| case (0, var unique) when _guard(unique, 'unique'): |
| case (1, var inTwo) when _guard(inTwo, 'inTwo'): |
| case (2, var inTwo) when _guard(inTwo, 'inTwo'): |
| return _matchedCase(); |
| default: |
| Expect.fail('Should not reach this.'); |
| } |
| } |
| |
| /// Variables can be shared if not all are annotated as long as the inferred |
| /// type matches. |
| Object? sharedAnnotatedAndUnannotated(int caseKey, Object value) { |
| switch ((caseKey, value)) { |
| case (0, var a) when _guard(a, 'var'): |
| case (1, Object a) when _guard(a, 'Object'): |
| // Use pattern variable in body: |
| Expect.equals(value, a); |
| return _matchedCase(); |
| default: |
| Expect.fail('Should not reach this.'); |
| } |
| } |
| |
| /// Variables can be shared if not all are annotated as long as the type |
| /// inferred using promotion matches. |
| Object? sharedAnnotatedAndPromotionInferred(int caseKey, Object value) { |
| // Promote value to String. |
| if (value is String) { |
| switch ((caseKey, value)) { |
| case (0, var a) when _guard(a, 'var'): |
| case (1, String a) when _guard(a, 'String'): |
| // Use pattern variable in body: |
| Expect.equals(value, a); |
| return _matchedCase(); |
| default: |
| Expect.fail('Should not reach this.'); |
| } |
| } |
| } |
| |
| /// Variables can be shared even when they occur in different contexts in their |
| /// respective patterns. |
| Object? sharedDifferentContext(Object value) { |
| // OK, since inferred type is same as annotated. |
| switch (value) { |
| case [int a, bool b] when _guard(a, 'list'): |
| case {'b': bool b, 'a': int a} when _guard(a, 'map'): |
| case (a: int a, b: bool b) when _guard(a, 'record'): |
| case (a: int a, b: [bool b]) when _guard(a, 'nested'): |
| // Use pattern variables in body: |
| return '$a: ${_matchedCase()}'; |
| default: |
| Expect.fail('Should not reach this.'); |
| } |
| } |
| |
| String _lastMatch = 'none'; |
| |
| bool _guard(Object guardVariable, String label) { |
| _lastMatch = '$guardVariable: $label'; |
| return true; |
| } |
| |
| String _matchedCase() { |
| var result = _lastMatch; |
| _lastMatch = 'none'; |
| return result; |
| } |