blob: f57b3bddad9e3fc9fb0efe502257fb396155fd79 [file] [log] [blame]
// 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:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../src/dart/resolution/node_text_expectations.dart';
import '../src/diagnostics/parser_diagnostics.dart';
import 'test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PatternsTest);
defineReflectiveTests(UpdateNodeTextExpectations);
});
}
@reflectiveTest
class PatternsTest extends ParserDiagnosticsTest {
late FindNode findNode;
test_assignedVariable_namedAs() {
_parse(
'''
void f(x) {
dynamic as;
(as) = x;
}
''',
errors: [
error(ParserErrorCode.illegalPatternAssignmentVariableName, 29, 2),
],
);
var node = findNode.singlePatternAssignment.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: AssignedVariablePattern
name: as
rightParenthesis: )
''');
}
test_assignedVariable_namedWhen() {
_parse(
'''
void f(x) {
dynamic when;
(when) = x;
}
''',
errors: [
error(ParserErrorCode.illegalPatternAssignmentVariableName, 31, 4),
],
);
var node = findNode.singlePatternAssignment.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: AssignedVariablePattern
name: when
rightParenthesis: )
''');
}
test_case_identifier_dot_incomplete() {
// Based on the repro from
// https://github.com/Dart-Code/Dart-Code/issues/4407.
_parse(
'''
void f(x) {
switch (x) {
case A.
}
}
''',
errors: [
error(ParserErrorCode.missingIdentifier, 41, 1),
error(ParserErrorCode.expectedToken, 41, 1),
],
);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: A
period: .
identifier: SimpleIdentifier
token: <empty> <synthetic>
colon: : <synthetic>
''');
}
test_caseHead_withClassicPattern_guarded_insideIfElement() {
_parse('''
void f(x) {
<int>[if (x case 0 when true) 1];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
''');
}
test_caseHead_withClassicPattern_guarded_insideIfElement_hasElse() {
_parse('''
void f(x) {
<int>[if (x case 0 when true) 1 else 2];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
elseKeyword: else
elseElement: IntegerLiteral
literal: 2
''');
}
test_caseHead_withClassicPattern_guarded_insideIfStatement() {
_parse('''
void f(x) {
if (x case 0 when true) {}
}
''');
var node = findNode.ifStatement('if');
assertParsedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_caseHead_withClassicPattern_guarded_insideIfStatement_hasElse() {
_parse('''
void f(x) {
if (x case 0 when true) {} else {}
}
''');
var node = findNode.ifStatement('if');
assertParsedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
elseKeyword: else
elseStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_caseHead_withClassicPattern_guarded_insideSwitchStatement() {
_parse('''
void f(x) {
switch (x) {
case 0 when true:
break;
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_caseHead_withClassicPattern_unguarded_insideIfElement() {
_parse('''
void f(x) {
<int>[if (x case 0) 1];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
''');
}
test_caseHead_withClassicPattern_unguarded_insideIfElement_hasElse() {
_parse('''
void f(x) {
<int>[if (x case 0) 1 else 2];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
elseKeyword: else
elseElement: IntegerLiteral
literal: 2
''');
}
test_caseHead_withClassicPattern_unguarded_insideIfStatement() {
_parse('''
void f(x) {
if (x case 0) {}
}
''');
var node = findNode.ifStatement('if');
assertParsedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_caseHead_withClassicPattern_unguarded_insideSwitchStatement() {
_parse('''
void f(x) {
switch (x) {
case 0:
break;
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_caseHead_withNewPattern_guarded_insideIfElement() {
_parse('''
void f(x) {
<int>[if (x case 0 as int when true) 1];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
''');
}
test_caseHead_withNewPattern_guarded_insideIfElement_hasElse() {
_parse('''
void f(x) {
<int>[if (x case 0 as int when true) 1 else 2];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
elseKeyword: else
elseElement: IntegerLiteral
literal: 2
''');
}
test_caseHead_withNewPattern_guarded_insideIfStatement() {
_parse('''
void f(x) {
if (x case 0 as int when true) {}
}
''');
var node = findNode.ifStatement('if');
assertParsedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_caseHead_withNewPattern_guarded_insideSwitchStatement() {
_parse('''
void f(x) {
switch (x) {
case 0 as int when true:
break;
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_caseHead_withNewPattern_unguarded_insideIfElement() {
_parse('''
void f(x) {
<int>[if (x case 0 as int) 1];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
''');
}
test_caseHead_withNewPattern_unguarded_insideIfElement_hasElse() {
_parse('''
void f(x) {
<int>[if (x case 0 as int) 1 else 2];
}
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
elseKeyword: else
elseElement: IntegerLiteral
literal: 2
''');
}
test_caseHead_withNewPattern_unguarded_insideIfStatement() {
_parse('''
void f(x) {
if (x case 0 as int) {}
}
''');
var node = findNode.ifStatement('if');
assertParsedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_caseHead_withNewPattern_unguarded_insideSwitchStatement() {
_parse('''
void f(x) {
switch (x) {
case 0 as int:
break;
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
asToken: as
type: NamedType
name: int
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_cast_insideCase() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y as int:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
asToken: as
type: NamedType
name: int
''');
}
test_cast_insideCast() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y as int as num:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 8)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
asToken: as
type: NamedType
name: int
asToken: as
type: NamedType
name: num
''');
}
test_cast_insideCast_parenthesized() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case (y as int) as num:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
asToken: as
type: NamedType
name: int
rightParenthesis: )
asToken: as
type: NamedType
name: num
''');
}
test_cast_insideIfCase() {
_parse('''
void f(x) {
if (x case var y as int) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
asToken: as
type: NamedType
name: int
''');
}
test_cast_insideList() {
_parse('''
void f(x) {
switch (x) {
case [1 as int]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: int
rightBracket: ]
''');
}
test_cast_insideLogicalAnd_lhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ as double? && Object? _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: CastPattern
pattern: WildcardPattern
type: NamedType
name: int
question: ?
name: _
asToken: as
type: NamedType
name: double
question: ?
operator: &&
rightOperand: WildcardPattern
type: NamedType
name: Object
question: ?
name: _
''');
}
test_cast_insideLogicalAnd_rhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ && double? _ as Object?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: &&
rightOperand: CastPattern
pattern: WildcardPattern
type: NamedType
name: double
question: ?
name: _
asToken: as
type: NamedType
name: Object
question: ?
''');
}
test_cast_insideLogicalOr_lhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ as double? || Object? _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: CastPattern
pattern: WildcardPattern
type: NamedType
name: int
question: ?
name: _
asToken: as
type: NamedType
name: double
question: ?
operator: ||
rightOperand: WildcardPattern
type: NamedType
name: Object
question: ?
name: _
''');
}
test_cast_insideLogicalOr_rhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ || double? _ as Object?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: ||
rightOperand: CastPattern
pattern: WildcardPattern
type: NamedType
name: double
question: ?
name: _
asToken: as
type: NamedType
name: Object
question: ?
''');
}
test_cast_insideMap() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1 as int}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: int
rightBracket: }
''');
}
test_cast_insideNullAssert() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y as int!:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 8)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
asToken: as
type: NamedType
name: int
operator: !
''');
}
test_cast_insideNullCheck() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y as int? ?:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 9)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
asToken: as
type: NamedType
name: int
question: ?
operator: ?
''');
}
test_cast_insideObject_explicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: 1 as int):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: int
rightParenthesis: )
''');
}
test_cast_insideObject_implicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(: var f as int):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: CastPattern
pattern: DeclaredVariablePattern
keyword: var
name: f
asToken: as
type: NamedType
name: int
rightParenthesis: )
''');
}
test_cast_insideParenthesized() {
_parse('''
void f(x) {
switch (x) {
case (1 as int):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: int
rightParenthesis: )
''');
}
test_cast_insideRecord_explicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (n: 1 as int, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: n
colon: :
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: int
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_cast_insideRecord_implicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (: var n as int, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: CastPattern
pattern: DeclaredVariablePattern
keyword: var
name: n
asToken: as
type: NamedType
name: int
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_cast_insideRecord_unnamed() {
_parse('''
void f(x) {
switch (x) {
case (1 as int, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: int
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_constant_identifier_doublyPrefixed_builtin() {
_parse('''
void f(x) {
const y = abstract.as.get; // verify that this works
switch (x) {
case abstract.as.get:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: abstract
period: .
identifier: SimpleIdentifier
token: as
operator: .
propertyName: SimpleIdentifier
token: get
''');
}
test_constant_identifier_doublyPrefixed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case a.b.c:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: .
propertyName: SimpleIdentifier
token: c
''');
}
test_constant_identifier_doublyPrefixed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case a.b.c as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: .
propertyName: SimpleIdentifier
token: c
asToken: as
type: NamedType
name: Object
''');
}
test_constant_identifier_doublyPrefixed_insideIfCase() {
_parse('''
void f(x) {
if (x case a.b.c) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: .
propertyName: SimpleIdentifier
token: c
''');
}
test_constant_identifier_doublyPrefixed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case a.b.c!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: .
propertyName: SimpleIdentifier
token: c
operator: !
''');
}
test_constant_identifier_doublyPrefixed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case a.b.c?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: .
propertyName: SimpleIdentifier
token: c
operator: ?
''');
}
test_constant_identifier_doublyPrefixed_pseudoKeyword() {
_parse('''
void f(x) {
const y = show.hide.when; // verify that this works
switch (x) {
case show.hide.when:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: show
period: .
identifier: SimpleIdentifier
token: hide
operator: .
propertyName: SimpleIdentifier
token: when
''');
}
test_constant_identifier_namedAs() {
_parse(
'''
void f(x) {
switch (x) {
case as:
}
}
''',
errors: [error(ParserErrorCode.illegalPatternIdentifierName, 36, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleIdentifier
token: as
''');
}
test_constant_identifier_namedWhen() {
_parse(
'''
void f(x) {
switch (x) {
case when:
}
}
''',
errors: [error(ParserErrorCode.illegalPatternIdentifierName, 36, 4)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleIdentifier
token: when
''');
}
test_constant_identifier_prefixed_builtin() {
_parse('''
void f(x) {
const y = abstract.as; // verify that this works
switch (x) {
case abstract.as:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: abstract
period: .
identifier: SimpleIdentifier
token: as
''');
}
test_constant_identifier_prefixed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case a.b:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
''');
}
test_constant_identifier_prefixed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case a.b as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
asToken: as
type: NamedType
name: Object
''');
}
test_constant_identifier_prefixed_insideIfCase() {
_parse('''
void f(x) {
if (x case a.b) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
''');
}
test_constant_identifier_prefixed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case a.b!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: !
''');
}
test_constant_identifier_prefixed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case a.b?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
operator: ?
''');
}
test_constant_identifier_prefixed_pseudoKeyword() {
_parse('''
void f(x) {
const y = show.hide; // verify that this works
switch (x) {
case show.hide:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: show
period: .
identifier: SimpleIdentifier
token: hide
''');
}
test_constant_identifier_prefixedWithUnderscore_insideCase() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
switch (x) {
case _.b:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: _
period: .
identifier: SimpleIdentifier
token: b
''');
}
test_constant_identifier_unprefixed_beforeWhen() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y when true:
break;
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_constant_identifier_unprefixed_builtin() {
_parse('''
void f(x) {
const y = abstract; // verify that this works
switch (x) {
case abstract:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleIdentifier
token: abstract
''');
}
test_constant_identifier_unprefixed_insideCase() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleIdentifier
token: y
''');
}
test_constant_identifier_unprefixed_insideCast() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
asToken: as
type: NamedType
name: Object
''');
}
test_constant_identifier_unprefixed_insideIfCase() {
_parse('''
void f(x) {
const y = 1;
if (x case y) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
''');
}
test_constant_identifier_unprefixed_insideNullAssert() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: !
''');
}
test_constant_identifier_unprefixed_insideNullCheck() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: ?
''');
}
test_constant_identifier_unprefixed_insideSwitchExpression() {
_parse('''
f(x) => switch (x) {
y => 0
};
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleIdentifier
token: y
''');
}
test_constant_identifier_unprefixed_pseudoKeyword() {
_parse('''
void f(x) {
const y = show; // verify that this works
switch (x) {
case show:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleIdentifier
token: show
''');
}
test_constant_list_typed_empty_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const <int>[]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
rightBracket: ]
''');
}
test_constant_list_typed_empty_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const <int>[] as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
rightBracket: ]
asToken: as
type: NamedType
name: Object
''');
}
test_constant_list_typed_empty_insideIfCase() {
_parse('''
void f(x) {
if (x case const <int>[]) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
rightBracket: ]
''');
}
test_constant_list_typed_empty_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const <int>[]!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
rightBracket: ]
operator: !
''');
}
test_constant_list_typed_empty_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const <int>[]?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
rightBracket: ]
operator: ?
''');
}
test_constant_list_typed_nonEmpty_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const <int>[1]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
''');
}
test_constant_list_typed_nonEmpty_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const <int>[1] as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
asToken: as
type: NamedType
name: Object
''');
}
test_constant_list_typed_nonEmpty_insideIfCase() {
_parse('''
void f(x) {
if (x case const <int>[1]) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
''');
}
test_constant_list_typed_nonEmpty_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const <int>[1]!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
operator: !
''');
}
test_constant_list_typed_nonEmpty_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const <int>[1]?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
operator: ?
''');
}
test_constant_list_untyped_empty_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const []:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
rightBracket: ]
''');
}
test_constant_list_untyped_empty_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const [] as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
rightBracket: ]
asToken: as
type: NamedType
name: Object
''');
}
test_constant_list_untyped_empty_insideIfCase() {
_parse('''
void f(x) {
if (x case const []) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
rightBracket: ]
''');
}
test_constant_list_untyped_empty_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const []!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
rightBracket: ]
operator: !
''');
}
test_constant_list_untyped_empty_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const []?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
rightBracket: ]
operator: ?
''');
}
test_constant_list_untyped_nonEmpty_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const [1]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
''');
}
test_constant_list_untyped_nonEmpty_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const [1] as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
asToken: as
type: NamedType
name: Object
''');
}
test_constant_list_untyped_nonEmpty_insideIfCase() {
_parse('''
void f(x) {
if (x case const [1]) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
''');
}
test_constant_list_untyped_nonEmpty_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const [1]!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
operator: !
''');
}
test_constant_list_untyped_nonEmpty_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const [1]?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: ListLiteral
leftBracket: [
elements
IntegerLiteral
literal: 1
rightBracket: ]
operator: ?
''');
}
test_constant_map_typed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const <int, int>{1: 2}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
''');
}
test_constant_map_typed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const <int, int>{1: 2} as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
asToken: as
type: NamedType
name: Object
''');
}
test_constant_map_typed_insideIfCase() {
_parse('''
void f(x) {
if (x case const <int, int>{1: 2}) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
''');
}
test_constant_map_typed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const <int, int>{1: 2}!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
operator: !
''');
}
test_constant_map_typed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const <int, int>{1: 2}?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
operator: ?
''');
}
test_constant_map_untyped_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const {1: 2}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
''');
}
test_constant_map_untyped_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const {1: 2} as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
asToken: as
type: NamedType
name: Object
''');
}
test_constant_map_untyped_insideIfCase() {
_parse('''
void f(x) {
if (x case const {1: 2}) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
''');
}
test_constant_map_untyped_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const {1: 2}!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
operator: !
''');
}
test_constant_map_untyped_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const {1: 2}?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
MapLiteralEntry
key: IntegerLiteral
literal: 1
separator: :
value: IntegerLiteral
literal: 2
rightBracket: }
isMap: false
operator: ?
''');
}
test_constant_objectExpression_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const Foo(1):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: MethodInvocation
methodName: SimpleIdentifier
token: Foo
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_constant_objectExpression_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const Foo(1) as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: MethodInvocation
methodName: SimpleIdentifier
token: Foo
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 1
rightParenthesis: )
asToken: as
type: NamedType
name: Object
''');
}
test_constant_objectExpression_insideIfCase() {
_parse('''
void f(x) {
if (x case const Foo(1)) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: MethodInvocation
methodName: SimpleIdentifier
token: Foo
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_constant_objectExpression_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const Foo(1)!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: MethodInvocation
methodName: SimpleIdentifier
token: Foo
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 1
rightParenthesis: )
operator: !
''');
}
test_constant_objectExpression_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const Foo(1)?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: MethodInvocation
methodName: SimpleIdentifier
token: Foo
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 1
rightParenthesis: )
operator: ?
''');
}
test_constant_parenthesized_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const (1):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: ParenthesizedExpression
leftParenthesis: (
expression: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_constant_parenthesized_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const (1) as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: ParenthesizedExpression
leftParenthesis: (
expression: IntegerLiteral
literal: 1
rightParenthesis: )
asToken: as
type: NamedType
name: Object
''');
}
test_constant_parenthesized_insideIfCase() {
_parse('''
void f(x) {
if (x case const (1)) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: ParenthesizedExpression
leftParenthesis: (
expression: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_constant_parenthesized_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const (1)!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: ParenthesizedExpression
leftParenthesis: (
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: !
''');
}
test_constant_parenthesized_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const (1)?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: ParenthesizedExpression
leftParenthesis: (
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: ?
''');
}
test_constant_set_typed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const <int>{1}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
''');
}
test_constant_set_typed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const <int>{1} as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
asToken: as
type: NamedType
name: Object
''');
}
test_constant_set_typed_insideIfCase() {
_parse('''
void f(x) {
if (x case const <int>{1}) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
''');
}
test_constant_set_typed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const <int>{1}!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
operator: !
''');
}
test_constant_set_typed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const <int>{1}?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
operator: ?
''');
}
test_constant_set_untyped_insideCase() {
_parse('''
void f(x) {
switch (x) {
case const {1}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
''');
}
test_constant_set_untyped_insideCast() {
_parse('''
void f(x) {
switch (x) {
case const {1} as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
asToken: as
type: NamedType
name: Object
''');
}
test_constant_set_untyped_insideIfCase() {
_parse('''
void f(x) {
if (x case const {1}) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
''');
}
test_constant_set_untyped_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case const {1}!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
operator: !
''');
}
test_constant_set_untyped_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case const {1}?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
constKeyword: const
expression: SetOrMapLiteral
leftBracket: {
elements
IntegerLiteral
literal: 1
rightBracket: }
isMap: false
operator: ?
''');
}
test_declaredVariable_inPatternAssignment_usingFinal() {
_parse(
'''
void f() {
[a, final d] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 23, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
DeclaredVariablePattern
keyword: final
name: d
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_declaredVariable_inPatternAssignment_usingFinalAndType() {
_parse(
'''
void f() {
[a, final int d] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 27, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
DeclaredVariablePattern
keyword: final
type: NamedType
name: int
name: d
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_declaredVariable_inPatternAssignment_usingType() {
_parse(
'''
void f() {
[a, int d] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 21, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
DeclaredVariablePattern
type: NamedType
name: int
name: d
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_declaredVariable_inPatternAssignment_usingVar() {
_parse(
'''
void f() {
[a, var d] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 21, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
DeclaredVariablePattern
keyword: var
name: d
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_declaredVariable_inPatternAssignment_usingVarAndType() {
_parse(
'''
void f() {
[a, var int d] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 25, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
DeclaredVariablePattern
keyword: var
type: NamedType
name: int
name: d
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_errorRecovery_afterQuestionSuffixInExpression() {
// Based on co19 test `Language/Expressions/Conditional/syntax_t06.dart`.
// Even though we now support suffix `?` in patterns, we need to make sure
// that a suffix `?` in an expression still causes the appropriate syntax
// error.
_parse(
'''
f() {
try {
true ? : 2;
} catch (e) {}
}
''',
errors: [error(ParserErrorCode.missingIdentifier, 26, 1)],
);
}
test_functionExpression_allowed_afterSwitchExpression() {
_parse('''
f(x) => switch(x) {} + () => 0;
''');
var node = findNode.functionDeclaration('f');
assertParsedNodeText(node, r'''
FunctionDeclaration
name: f
functionExpression: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
parameter: SimpleFormalParameter
name: x
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: BinaryExpression
leftOperand: SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
rightBracket: }
operator: +
rightOperand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
semicolon: ;
''');
}
test_functionExpression_allowed_insideIfCaseWhenClause_element() {
_parse('''
f(x, y) => [if (x case _ when y + () => 0) 0];
''');
var node = findNode.ifElement('if');
assertParsedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: +
rightOperand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightParenthesis: )
thenElement: IntegerLiteral
literal: 0
''');
}
test_functionExpression_allowed_insideIfCaseWhenClause_statement() {
_parse('''
f(x, y) {
if (x case _ when y + () => 0) {}
}
''');
var node = findNode.ifStatement('if');
assertParsedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: +
rightOperand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_functionExpression_allowed_insideListPattern() {
_parse('''
f(x) => switch(x) { [== () => 0] => 0 };
''');
var node = findNode.switchExpressionCase('() => 0').guardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
RelationalPattern
operator: ==
operand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightBracket: ]
''');
}
test_functionExpression_allowed_insideMapPattern() {
_parse('''
f(x) => switch(x) { {'x': == () => 0} => 0 };
''');
var node = findNode.switchExpressionCase('() => 0').guardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'x'
separator: :
value: RelationalPattern
operator: ==
operand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_functionExpression_allowed_insideObjectPattern() {
_parse('''
f(x) => switch(x) { Foo(bar: == () => 0) => 0 };
''');
var node = findNode.switchExpressionCase('() => 0').guardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: Foo
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: bar
colon: :
pattern: RelationalPattern
operator: ==
operand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightParenthesis: )
''');
}
test_functionExpression_allowed_insideParenthesizedConstPattern() {
_parse('''
f(x) => switch(x) { const (() => 0) => 0 };
''');
var node = findNode.switchExpressionCase('() => 0').guardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
constKeyword: const
expression: ParenthesizedExpression
leftParenthesis: (
expression: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightParenthesis: )
''');
}
test_functionExpression_allowed_insideParenthesizedPattern() {
_parse('''
f(x) => switch(x) { (== () => 0) => 0 };
''');
var node = findNode.switchExpressionCase('() => 0').guardedPattern.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: RelationalPattern
operator: ==
operand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightParenthesis: )
''');
}
test_functionExpression_allowed_insideSwitchExpressionCase_guarded() {
_parse('''
f(x) => switch(x) { _ when switch(x) { _ when true => () => 0 } => 0 };
''');
var node = findNode.switchExpressionCase('() => 0');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
arrow: =>
expression: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_allowed_insideSwitchExpressionCase_unguarded() {
_parse('''
f(x) => switch(x) { _ when switch(x) { _ => () => 0 } => 0 };
''');
var node = findNode.switchExpressionCase('() => 0');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_allowed_insideSwitchExpressionScrutinee() {
_parse('''
f() => switch(() => 0) {};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
rightParenthesis: )
leftBracket: {
rightBracket: }
''');
}
test_functionExpression_allowed_insideSwitchStatementInWhenClause() {
_parse('''
f(x, y) {
switch(x) {
case _ when y + () => 0:
break;
}
}
''');
var node = findNode.switchPatternCase('when');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: +
rightOperand: FunctionExpression
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_functionExpression_disallowed_afterListPattern() {
_parse('''
f(x) => switch(x) { [_] when () => 0 };
''');
var node = findNode.switchExpressionCase('when');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ListPattern
leftBracket: [
elements
WildcardPattern
name: _
rightBracket: ]
whenClause: WhenClause
whenKeyword: when
expression: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_disallowed_afterMapPattern() {
_parse('''
f(x) => switch(x) { {'x': _} when () => 0 };
''');
var node = findNode.switchExpressionCase('when');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'x'
separator: :
value: WildcardPattern
name: _
rightBracket: }
whenClause: WhenClause
whenKeyword: when
expression: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_disallowed_afterObjectPattern() {
_parse('''
f(x) => switch(x) { Foo(bar: _) when () => 0 };
''');
var node = findNode.switchExpressionCase('when');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: Foo
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: bar
colon: :
pattern: WildcardPattern
name: _
rightParenthesis: )
whenClause: WhenClause
whenKeyword: when
expression: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_disallowed_afterParenthesizedPattern() {
_parse('''
f(x) => switch(x) { (_) when () => 0 };
''');
var node = findNode.switchExpressionCase('when');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: WildcardPattern
name: _
rightParenthesis: )
whenClause: WhenClause
whenKeyword: when
expression: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_disallowed_afterSwitchExpressionInWhenClause() {
_parse('''
f(x) => switch(x) { _ when switch(x) {} + () => 0 };
''');
var node = findNode.switchExpressionCase('when');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
rightBracket: }
operator: +
rightOperand: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
''');
}
test_functionExpression_disallowed_insideSwitchExpressionInWhenClause() {
_parse('''
f(x, y) => switch(x) { _ when y + () => 0 };
''');
var node = findNode.switchExpressionCase('when');
assertParsedNodeText(node, r'''
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: +
rightOperand: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
''');
}
test_identifier_as_when() {
// Based on the discussion at https://github.com/dart-lang/sdk/issues/52199.
_parse('''
void f(x) {
switch (x) {
case foo as when:
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: foo
asToken: as
type: NamedType
name: when
colon: :
''');
}
test_identifier_when_as() {
// Based on the discussion at https://github.com/dart-lang/sdk/issues/52199.
_parse('''
void f(x) {
switch (x) {
case foo when as:
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: foo
whenClause: WhenClause
whenKeyword: when
expression: SimpleIdentifier
token: as
colon: :
''');
}
test_identifier_when_not() {
// Based on the repro from https://github.com/dart-lang/sdk/issues/52199.
_parse('''
void f(x) {
switch (x) {
case foo when !flag:
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: foo
whenClause: WhenClause
whenKeyword: when
expression: PrefixExpression
operator: !
operand: SimpleIdentifier
token: flag
colon: :
''');
}
test_identifier_when_when() {
// Based on the discussion at https://github.com/dart-lang/sdk/issues/52199.
_parse('''
void f(x) {
switch (x) {
case foo when when:
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: foo
whenClause: WhenClause
whenKeyword: when
expression: SimpleIdentifier
token: when
colon: :
''');
}
test_issue50591_example1() {
_parse('''
f(x, bool Function() a) => switch(x) {
_ when a() => 0
};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: MethodInvocation
methodName: SimpleIdentifier
token: a
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_issue50591_example2() {
_parse('''
void f(Object? x) {
(switch (x) {
const A() => 0,
_ => 1,
});
}''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
constKeyword: const
expression: MethodInvocation
methodName: SimpleIdentifier
token: A
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: IntegerLiteral
literal: 1
rightBracket: }
''');
}
test_list_insideAssignment_typed_nonEmpty() {
_parse('''
void f(x) {
<int>[a, b] = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
AssignedVariablePattern
name: a
AssignedVariablePattern
name: b
rightBracket: ]
''');
}
test_list_insideAssignment_untyped_empty() {
_parse('''
void f(x) {
[] = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
rightBracket: ]
''');
}
test_list_insideAssignment_untyped_emptyWithWhitespace() {
_parse('''
void f(x) {
[ ] = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
rightBracket: ]
''');
}
test_list_insideAssignment_untyped_nonEmpty() {
_parse('''
void f(x) {
[a, b] = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
AssignedVariablePattern
name: b
rightBracket: ]
''');
}
test_list_insideCase_typed_nonEmpty() {
_parse('''
void f(x) {
switch (x) {
case <int>[1, 2]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
ConstantPattern
expression: IntegerLiteral
literal: 1
ConstantPattern
expression: IntegerLiteral
literal: 2
rightBracket: ]
''');
}
test_list_insideCase_untyped_empty() {
_parse('''
void f(x) {
switch (x) {
case []:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
rightBracket: ]
''');
}
test_list_insideCase_untyped_emptyWithWhitespace() {
_parse('''
void f(x) {
switch (x) {
case [ ]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
rightBracket: ]
''');
}
test_list_insideCase_untyped_nonEmpty() {
_parse('''
void f(x) {
switch (x) {
case [1, 2]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
ConstantPattern
expression: IntegerLiteral
literal: 1
ConstantPattern
expression: IntegerLiteral
literal: 2
rightBracket: ]
''');
}
test_list_insideCast() {
_parse('''
void f(x) {
switch (x) {
case [1] as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ListPattern
leftBracket: [
elements
ConstantPattern
expression: IntegerLiteral
literal: 1
rightBracket: ]
asToken: as
type: NamedType
name: Object
''');
}
test_list_insideDeclaration_typed_nonEmpty() {
_parse('''
void f(x) {
var <int>[a, b] = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftBracket: [
elements
DeclaredVariablePattern
name: a
DeclaredVariablePattern
name: b
rightBracket: ]
''');
}
test_list_insideDeclaration_untyped_empty() {
_parse('''
void f(x) {
var [] = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
rightBracket: ]
''');
}
test_list_insideDeclaration_untyped_emptyWithWhitespace() {
_parse('''
void f(x) {
var [ ] = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
rightBracket: ]
''');
}
test_list_insideDeclaration_untyped_nonEmpty() {
_parse('''
void f(x) {
var [a, b] = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
DeclaredVariablePattern
name: a
DeclaredVariablePattern
name: b
rightBracket: ]
''');
}
test_list_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case [1]!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ListPattern
leftBracket: [
elements
ConstantPattern
expression: IntegerLiteral
literal: 1
rightBracket: ]
operator: !
''');
}
test_list_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case [1]?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ListPattern
leftBracket: [
elements
ConstantPattern
expression: IntegerLiteral
literal: 1
rightBracket: ]
operator: ?
''');
}
test_list_recovery_bogusTokensAfterListElement() {
// If the extra tokens after a list element don't look like they could be a
// pattern, the parser skips to the end of the list to avoid a large number
// of parse errors.
_parse(
'''
void f(x) {
switch (x) {
case [int() * 2]:
break;
}
}
''',
errors: [error(ParserErrorCode.expectedToken, 43, 1)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightBracket: ]
''');
}
test_list_recovery_missingClosingBracket() {
// If the extra tokens after a list element don't look like they could be a
// pattern, and the pattern doesn't have a matching `]`, the parser assumes
// it's the `]` that is missing.
_parse(
'''
void f(x) {
switch (x) {
case [int():
break;
}
}
''',
errors: [error(ScannerErrorCode.expectedToken, 59, 1)],
);
var node = findNode.switchStatement('switch').members.single;
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ListPattern
leftBracket: [
elements
ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightBracket: ] <synthetic>
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_list_recovery_missingComma() {
// If the extra tokens after a list element look like they could be a
// pattern, the parser assumes there's a missing comma.
_parse(
'''
void f(x) {
switch (x) {
case [int() int()]:
break;
}
}
''',
errors: [error(ParserErrorCode.expectedToken, 43, 3)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightBracket: ]
''');
}
test_literal_boolean_insideCase() {
_parse('''
void f(x) {
switch (x) {
case true:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: BooleanLiteral
literal: true
''');
}
test_literal_boolean_insideCast() {
_parse('''
void f(x) {
switch (x) {
case true as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: BooleanLiteral
literal: true
asToken: as
type: NamedType
name: Object
''');
}
test_literal_boolean_insideIfCase() {
_parse('''
void f(x) {
if (x case true) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: BooleanLiteral
literal: true
''');
}
test_literal_boolean_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case true!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: BooleanLiteral
literal: true
operator: !
''');
}
test_literal_boolean_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case true?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: BooleanLiteral
literal: true
operator: ?
''');
}
test_literal_double_insideCase() {
_parse('''
void f(x) {
switch (x) {
case 1.0:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: DoubleLiteral
literal: 1.0
''');
}
test_literal_double_insideCast() {
_parse('''
void f(x) {
switch (x) {
case 1.0 as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: DoubleLiteral
literal: 1.0
asToken: as
type: NamedType
name: Object
''');
}
test_literal_double_insideIfCase() {
_parse('''
void f(x) {
if (x case 1.0) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: DoubleLiteral
literal: 1.0
''');
}
test_literal_double_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case 1.0!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: DoubleLiteral
literal: 1.0
operator: !
''');
}
test_literal_double_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case 1.0?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: DoubleLiteral
literal: 1.0
operator: ?
''');
}
test_literal_integer_insideCase() {
_parse('''
void f(x) {
switch (x) {
case 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: IntegerLiteral
literal: 1
''');
}
test_literal_integer_insideCast() {
_parse('''
void f(x) {
switch (x) {
case 1 as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
asToken: as
type: NamedType
name: Object
''');
}
test_literal_integer_insideIfCase() {
_parse('''
void f(x) {
if (x case 1) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
''');
}
test_literal_integer_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case 1!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
''');
}
test_literal_integer_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case 1?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
''');
}
test_literal_null_insideCase() {
_parse('''
void f(x) {
switch (x) {
case null:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: NullLiteral
literal: null
''');
}
test_literal_null_insideCast() {
_parse('''
void f(x) {
switch (x) {
case null as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: NullLiteral
literal: null
asToken: as
type: NamedType
name: Object
''');
}
test_literal_null_insideIfCase() {
_parse('''
void f(x) {
if (x case null) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: NullLiteral
literal: null
''');
}
test_literal_null_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case null!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: NullLiteral
literal: null
operator: !
''');
}
test_literal_null_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case null?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: NullLiteral
literal: null
operator: ?
''');
}
test_literal_string_insideCase() {
_parse('''
void f(x) {
switch (x) {
case "x":
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ConstantPattern
expression: SimpleStringLiteral
literal: "x"
''');
}
test_literal_string_insideCast() {
_parse('''
void f(x) {
switch (x) {
case "x" as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ConstantPattern
expression: SimpleStringLiteral
literal: "x"
asToken: as
type: NamedType
name: Object
''');
}
test_literal_string_insideIfCase() {
_parse('''
void f(x) {
if (x case "x") {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleStringLiteral
literal: "x"
''');
}
test_literal_string_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case "x"!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: SimpleStringLiteral
literal: "x"
operator: !
''');
}
test_literal_string_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case "x"?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: SimpleStringLiteral
literal: "x"
operator: ?
''');
}
test_logicalAnd_insideIfCase() {
_parse('''
void f(x) {
if (x case int? _ && double? _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: LogicalAndPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: &&
rightOperand: WildcardPattern
type: NamedType
name: double
question: ?
name: _
''');
}
test_logicalAnd_insideLogicalAnd_lhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ && double? _ && Object? _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: LogicalAndPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: &&
rightOperand: WildcardPattern
type: NamedType
name: double
question: ?
name: _
operator: &&
rightOperand: WildcardPattern
type: NamedType
name: Object
question: ?
name: _
''');
}
test_logicalAnd_insideLogicalOr_lhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ && double? _ || Object? _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: LogicalAndPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: &&
rightOperand: WildcardPattern
type: NamedType
name: double
question: ?
name: _
operator: ||
rightOperand: WildcardPattern
type: NamedType
name: Object
question: ?
name: _
''');
}
test_logicalAnd_insideLogicalOr_rhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ || double? _ && Object? _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: ||
rightOperand: LogicalAndPattern
leftOperand: WildcardPattern
type: NamedType
name: double
question: ?
name: _
operator: &&
rightOperand: WildcardPattern
type: NamedType
name: Object
question: ?
name: _
''');
}
test_logicalOr_insideIfCase() {
_parse('''
void f(x) {
if (x case int? _ || double? _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: LogicalOrPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: ||
rightOperand: WildcardPattern
type: NamedType
name: double
question: ?
name: _
''');
}
test_logicalOr_insideLogicalOr_lhs() {
_parse('''
void f(x) {
switch (x) {
case int? _ || double? _ || Object? _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: LogicalOrPattern
leftOperand: WildcardPattern
type: NamedType
name: int
question: ?
name: _
operator: ||
rightOperand: WildcardPattern
type: NamedType
name: double
question: ?
name: _
operator: ||
rightOperand: WildcardPattern
type: NamedType
name: Object
question: ?
name: _
''');
}
test_map_insideAssignment_typed_nonEmpty() {
_parse('''
void f(x) {
<String, int>{'a': a, 'b': b} = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: String
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: AssignedVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: AssignedVariablePattern
name: b
rightBracket: }
''');
}
test_map_insideAssignment_untyped_empty() {
// Note: statements aren't allowed to start with `{` so we need parens
// around the assignment. See
// https://github.com/dart-lang/language/issues/2662.
_parse('''
void f(x) {
({} = x);
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
rightBracket: }
''');
}
test_map_insideAssignment_untyped_empty_beginningOfStatement() {
_parse('''
void f(x) {
{} = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
rightBracket: }
''');
}
test_map_insideAssignment_untyped_nonEmpty() {
// Note: statements aren't allowed to start with `{` so we need parens
// around the assignment. See
// https://github.com/dart-lang/language/issues/2662.
_parse('''
void f(x) {
({'a': a, 'b': b} = x);
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: AssignedVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: AssignedVariablePattern
name: b
rightBracket: }
''');
}
test_map_insideAssignment_untyped_nonEmpty_beginningOfStatement() {
_parse('''
void f(x) {
{'a': a, 'b': b} = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: AssignedVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: AssignedVariablePattern
name: b
rightBracket: }
''');
}
test_map_insideCase_typed_nonEmpty() {
_parse('''
void f(x) {
switch (x) {
case <String, int>{'a': 1, 'b': 2}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: String
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 1
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 2
rightBracket: }
''');
}
test_map_insideCase_untyped_empty() {
_parse('''
void f(x) {
switch (x) {
case {}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
rightBracket: }
''');
}
test_map_insideCase_untyped_nonEmpty() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1, 'b': 2}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 1
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 2
rightBracket: }
''');
}
test_map_insideCast() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1} as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 1
rightBracket: }
asToken: as
type: NamedType
name: Object
''');
}
test_map_insideDeclaration_typed_nonEmpty() {
_parse('''
void f(x) {
var <String, int>{'a': a, 'b': b} = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: String
NamedType
name: int
rightBracket: >
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: DeclaredVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: DeclaredVariablePattern
name: b
rightBracket: }
''');
}
test_map_insideDeclaration_untyped_empty() {
_parse('''
void f(x) {
var {} = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
rightBracket: }
''');
}
test_map_insideDeclaration_untyped_nonEmpty() {
_parse('''
void f(x) {
var {'a': a, 'b': b} = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: DeclaredVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
value: DeclaredVariablePattern
name: b
rightBracket: }
''');
}
test_map_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1}!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 1
rightBracket: }
operator: !
''');
}
test_map_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1}?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: ConstantPattern
expression: IntegerLiteral
literal: 1
rightBracket: }
operator: ?
''');
}
test_map_recovery_bogusTokensAfterMapElement() {
// If the extra tokens after a map element don't look like they could be a
// key expression, the parser skips to the end of the map to avoid a large
// number of parse errors.
_parse(
'''
void f(x) {
switch (x) {
case {'foo': int() * 2}:
break;
}
}
''',
errors: [error(ParserErrorCode.expectedToken, 50, 1)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'foo'
separator: :
value: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightBracket: }
''');
}
void test_map_recovery_incompleteEntry() {
_parse(
'''
const c = 0;
void f(Object o) {
switch (o) {
case {c}:
break;
}
}
''',
errors: [
error(ParserErrorCode.expectedToken, 59, 1),
error(ParserErrorCode.missingIdentifier, 59, 1),
],
);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleIdentifier
token: c
separator: : <synthetic>
value: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: }
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_map_recovery_missingClosingBrace() {
// If the extra tokens after a map element don't look like they could be a
// key expression, and the pattern doesn't have a matching `}`, the parser
// assumes it's the `}` that is missing.
_parse(
'''
void f(x) {
switch (x) {
case ({'foo': int()):
break;
}
}
''',
errors: [error(ScannerErrorCode.expectedToken, 50, 1)],
);
var node = findNode.switchStatement('switch').members.single;
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'foo'
separator: :
value: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightBracket: } <synthetic>
rightParenthesis: )
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_map_recovery_missingComma() {
// If the extra tokens after a map element look like they could be a key
// expression, the parser assumes there's a missing comma.
_parse(
'''
void f(x) {
switch (x) {
case {'foo': int() 'bar': int()}:
break;
}
}
''',
errors: [error(ParserErrorCode.expectedToken, 50, 5)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'foo'
separator: :
value: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
MapPatternEntry
key: SimpleStringLiteral
literal: 'bar'
separator: :
value: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightBracket: }
''');
}
test_nullAssert_insideCase() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: !
''');
}
test_nullAssert_insideCast() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y! as num:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: NullAssertPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: !
asToken: as
type: NamedType
name: num
''');
}
test_nullAssert_insideIfCase() {
_parse('''
void f(x) {
if (x case var y!) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: NullAssertPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
operator: !
''');
}
test_nullAssert_insideList() {
_parse('''
void f(x) {
switch (x) {
case [1!]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
rightBracket: ]
''');
}
test_nullAssert_insideLogicalAnd_lhs() {
_parse('''
void f(x) {
switch (x) {
case 1! && 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
operator: &&
rightOperand: ConstantPattern
expression: IntegerLiteral
literal: 2
''');
}
test_nullAssert_insideLogicalAnd_rhs() {
_parse('''
void f(x) {
switch (x) {
case 1 && 2!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: &&
rightOperand: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
operator: !
''');
}
test_nullAssert_insideLogicalOr_lhs() {
_parse('''
void f(x) {
switch (x) {
case 1! || 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
operator: ||
rightOperand: ConstantPattern
expression: IntegerLiteral
literal: 2
''');
}
test_nullAssert_insideLogicalOr_rhs() {
_parse('''
void f(x) {
switch (x) {
case 1 || 2!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ||
rightOperand: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
operator: !
''');
}
test_nullAssert_insideMap() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1!}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
rightBracket: }
''');
}
test_nullAssert_insideNullAssert() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y!!:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: NullAssertPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: !
operator: !
''');
}
test_nullAssert_insideNullCheck() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y!?:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: NullAssertPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: !
operator: ?
''');
}
test_nullAssert_insideObject_explicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: 1!):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
rightParenthesis: )
''');
}
test_nullAssert_insideObject_implicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(: var f!):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: NullAssertPattern
pattern: DeclaredVariablePattern
keyword: var
name: f
operator: !
rightParenthesis: )
''');
}
test_nullAssert_insideParenthesized() {
_parse('''
void f(x) {
switch (x) {
case (1!):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
rightParenthesis: )
''');
}
test_nullAssert_insideRecord_explicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (n: 1!, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: n
colon: :
pattern: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_nullAssert_insideRecord_implicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (: var n!, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: NullAssertPattern
pattern: DeclaredVariablePattern
keyword: var
name: n
operator: !
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_nullAssert_insideRecord_unnamed() {
_parse('''
void f(x) {
switch (x) {
case (1!, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: NullAssertPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: !
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_nullCheck_insideCase() {
_parse('''
void f(x) {
const y = 1;
switch (x) {
case y?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: ?
''');
}
test_nullCheck_insideCast() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y? as num:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: NullCheckPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: ?
asToken: as
type: NamedType
name: num
''');
}
test_nullCheck_insideIfCase() {
_parse('''
void f(x) {
if (x case var y?) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: NullCheckPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
operator: ?
''');
}
test_nullCheck_insideList() {
_parse('''
void f(x) {
switch (x) {
case [1?]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
rightBracket: ]
''');
}
test_nullCheck_insideLogicalAnd_lhs() {
_parse('''
void f(x) {
switch (x) {
case 1? && 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
operator: &&
rightOperand: ConstantPattern
expression: IntegerLiteral
literal: 2
''');
}
test_nullCheck_insideLogicalAnd_rhs() {
_parse('''
void f(x) {
switch (x) {
case 1 && 2?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: &&
rightOperand: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
operator: ?
''');
}
test_nullCheck_insideLogicalOr_lhs() {
_parse('''
void f(x) {
switch (x) {
case 1? || 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
operator: ||
rightOperand: ConstantPattern
expression: IntegerLiteral
literal: 2
''');
}
test_nullCheck_insideLogicalOr_rhs() {
_parse('''
void f(x) {
switch (x) {
case 1 || 2?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ||
rightOperand: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
operator: ?
''');
}
test_nullCheck_insideMap() {
_parse('''
void f(x) {
switch (x) {
case {'a': 1?}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
rightBracket: }
''');
}
test_nullCheck_insideNullAssert() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y?!:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: NullCheckPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: ?
operator: !
''');
}
test_nullCheck_insideNullCheck() {
_parse(
'''
void f(x) {
const y = 1;
switch (x) {
case y? ?:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 51, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: NullCheckPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: y
operator: ?
operator: ?
''');
}
test_nullCheck_insideObject_explicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: 1?):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
rightParenthesis: )
''');
}
test_nullCheck_insideObject_implicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(: var f?):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: NullCheckPattern
pattern: DeclaredVariablePattern
keyword: var
name: f
operator: ?
rightParenthesis: )
''');
}
test_nullCheck_insideParenthesized() {
_parse('''
void f(x) {
switch (x) {
case (1?):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
rightParenthesis: )
''');
}
test_nullCheck_insideRecord_explicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (n: 1?, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: n
colon: :
pattern: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_nullCheck_insideRecord_implicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (: var n?, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: NullCheckPattern
pattern: DeclaredVariablePattern
keyword: var
name: n
operator: ?
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_nullCheck_insideRecord_unnamed() {
_parse('''
void f(x) {
switch (x) {
case (1?, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: NullCheckPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ?
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_object_dynamic() {
_parse('''
void f(x) {
switch (x) {
case dynamic():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: dynamic
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_async() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var async() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: async
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_await() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var await() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: await
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_hide() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var hide() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: hide
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_of() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var of() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: of
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_on() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var on() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: on
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_show() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var show() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: show
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_sync() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var sync() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: sync
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_otherIdentifier_yield() {
// The type name in an object pattern is a `typeIdentifier`; in the spec
// grammar, `typeIdentifier` includes `OTHER_IDENTIFIER`, so this is
// allowed.
_parse('''
void f(x) {
var yield() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: yield
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_prefixed_withTypeArgs_insideAssignment() {
_parse('''
void f(x) {
async.Future<int>() = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: async
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_prefixed_withTypeArgs_insideCase() {
_parse('''
import 'dart:async' as async;
void f(x) {
switch (x) {
case async.Future<int>():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: async
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_prefixed_withTypeArgs_insideCast() {
_parse('''
import 'dart:async' as async;
void f(x) {
switch (x) {
case async.Future<int>() as Object:
break;
}
}
''');
var node = findNode.switchPatternCase("async.Future<int>() as Object");
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: CastPattern
pattern: ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: async
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
asToken: as
type: NamedType
name: Object
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_object_prefixed_withTypeArgs_insideDeclaration() {
_parse('''
void f(x) {
var async.Future<int>() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: async
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_prefixed_withTypeArgs_insideNullAssert() {
_parse('''
import 'dart:async' as async;
void f(x) {
switch (x) {
case async.Future<int>()!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: async
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
operator: !
''');
}
test_object_prefixed_withTypeArgs_insideNullCheck() {
_parse('''
import 'dart:async' as async;
void f(x) {
switch (x) {
case async.Future<int>()?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: async
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
operator: ?
''');
}
test_object_prefixedNamedUnderscore_withoutTypeArgs_insideCase() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
switch (x) {
case _.Future():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: _
period: .
name: Future
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_prefixedNamedUnderscore_withoutTypeArgs_insideDeclaration() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
var _.Future() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: _
period: .
name: Future
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_prefixedNamedUnderscore_withTypeArgs_insideCase() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
switch (x) {
case _.Future<int>():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
importPrefix: ImportPrefixReference
name: _
period: .
name: Future
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_recovery_bogusTokensAfterPatternField() {
// If the extra tokens after a pattern field don't look like they could be a
// subsequent pattern field, the parser skips to the closing parenthesis to
// avoid a large number of parse errors.
_parse(
'''
void f(x) {
switch (x) {
case dynamic(foo: int() * 2):
break;
}
}
''',
errors: [error(ParserErrorCode.expectedToken, 55, 1)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: dynamic
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: foo
colon: :
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightParenthesis: )
''');
}
test_object_recovery_missingClosingParen() {
// If the extra tokens after a pattern don't look like they could be a
// subsequent pattern field, and the pattern doesn't have a matching `)`,
// the parser assumes it's the `)` that is missing.
_parse(
'''
void f(x) {
switch (x) {
case dynamic(foo: int():
break;
}
}
''',
errors: [error(ScannerErrorCode.expectedToken, 71, 1)],
);
var node = findNode.switchStatement('switch').members.single;
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: dynamic
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: foo
colon: :
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightParenthesis: ) <synthetic>
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
''');
}
test_object_recovery_missingComma() {
// If the extra tokens after a pattern field look like they could be a
// subsequent pattern field, the parser assumes there's a missing comma.
_parse(
'''
void f(x) {
switch (x) {
case dynamic(foo: int() bar: int()):
break;
}
}
''',
errors: [error(ParserErrorCode.expectedToken, 55, 3)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: dynamic
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: foo
colon: :
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
PatternField
name: PatternFieldName
name: bar
colon: :
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
rightParenthesis: )
''');
}
test_object_unprefixed_withoutTypeArgs_insideCast() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: 1) as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
asToken: as
type: NamedType
name: Object
''');
}
test_object_unprefixed_withoutTypeArgs_insideNullAssert() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: 1)!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: !
''');
}
test_object_unprefixed_withoutTypeArgs_insideNullCheck() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: 1)?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: ?
''');
}
test_object_unprefixed_withTypeArgs_insideCase() {
_parse('''
class C<T> {}
void f(x) {
switch (x) {
case C<int>():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_unprefixed_withTypeArgs_insideDeclaration() {
_parse('''
class C<T> {}
void f(x) {
var C<int>() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_unprefixed_withTypeArgs_insideNullAssert() {
_parse('''
class C<T> {
T? f;
}
void f(x) {
switch (x) {
case C<int>(f: 1)!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ObjectPattern
type: NamedType
name: C
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: !
''');
}
test_object_unprefixedNamedUnderscore_withoutTypeArgs_insideCase() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
switch (x) {
case _():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: _
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_unprefixedNamedUnderscore_withoutTypeArgs_insideDeclaration() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
var _() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: _
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_unprefixedNamedUnderscore_withTypeArgs_insideCase() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
switch (x) {
case _<int>():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: _
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_object_unprefixedNamedUnderscore_withTypeArgs_insideDeclaration() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
var _<int>() = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: _
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
leftParenthesis: (
rightParenthesis: )
''');
}
test_parenthesized_insideAssignment() {
_parse('''
f(x) {
(a) = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: AssignedVariablePattern
name: a
rightParenthesis: )
''');
}
test_parenthesized_insideCase() {
_parse('''
f(x) {
switch (x) {
case (1):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_parenthesized_insideCast() {
_parse('''
void f(x) {
switch (x) {
case (1) as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
asToken: as
type: NamedType
name: Object
''');
}
test_parenthesized_insideDeclaration() {
_parse('''
f(x) {
var (a) = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
''');
}
test_parenthesized_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case (1)!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: !
''');
}
test_parenthesized_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case (1)?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
operator: ?
''');
}
test_pattern_inForIn_element_noMetadata() {
_parse('''
void f(x) => [for (var (a, b) in x) 0];
''');
var node = findNode.forElement('for');
assertParsedNodeText(node, r'''
ForElement
forKeyword: for
leftParenthesis: (
forLoopParts: ForEachPartsWithPattern
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
inKeyword: in
iterable: SimpleIdentifier
token: x
rightParenthesis: )
body: IntegerLiteral
literal: 0
''');
}
test_pattern_inForIn_element_withMetadata() {
_parse('''
void f(x) => [for (@annotation var (a, b) in x) 0];
''');
var node = findNode.forElement('for');
assertParsedNodeText(node, r'''
ForElement
forKeyword: for
leftParenthesis: (
forLoopParts: ForEachPartsWithPattern
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
inKeyword: in
iterable: SimpleIdentifier
token: x
rightParenthesis: )
body: IntegerLiteral
literal: 0
''');
}
test_pattern_inForIn_statement_noMetadata() {
_parse('''
void f(x) {
for (var (a, b) in x) {}
}
''');
var node = findNode.forStatement('for');
assertParsedNodeText(node, r'''
ForStatement
forKeyword: for
leftParenthesis: (
forLoopParts: ForEachPartsWithPattern
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
inKeyword: in
iterable: SimpleIdentifier
token: x
rightParenthesis: )
body: Block
leftBracket: {
rightBracket: }
''');
}
test_pattern_inForIn_statement_withMetadata() {
_parse('''
void f(x) {
for (@annotation var (a, b) in x) {}
}
''');
var node = findNode.forStatement('for');
assertParsedNodeText(node, r'''
ForStatement
forKeyword: for
leftParenthesis: (
forLoopParts: ForEachPartsWithPattern
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
inKeyword: in
iterable: SimpleIdentifier
token: x
rightParenthesis: )
body: Block
leftBracket: {
rightBracket: }
''');
}
test_pattern_inForInitializer_element() {
_parse('''
void f(x) => [for (var (a, b) = x; ;) 0];
''');
var node = findNode.forElement('for');
assertParsedNodeText(node, r'''
ForElement
forKeyword: for
leftParenthesis: (
forLoopParts: ForPartsWithPattern
variables: PatternVariableDeclaration
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
leftSeparator: ;
rightSeparator: ;
rightParenthesis: )
body: IntegerLiteral
literal: 0
''');
}
test_pattern_inForInitializer_statement() {
_parse('''
void f(x) {
for (var (a, b) = x; ;) {}
}
''');
var node = findNode.forStatement('for');
assertParsedNodeText(node, r'''
ForStatement
forKeyword: for
leftParenthesis: (
forLoopParts: ForPartsWithPattern
variables: PatternVariableDeclaration
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
leftSeparator: ;
rightSeparator: ;
rightParenthesis: )
body: Block
leftBracket: {
rightBracket: }
''');
}
test_pattern_inForPartsWithExpression_element() {
_parse('''
void f(x) => [for ((a, b) = x; ;) 0];
''');
var node = findNode.forElement('for');
assertParsedNodeText(node, r'''
ForElement
forKeyword: for
leftParenthesis: (
forLoopParts: ForPartsWithExpression
initialization: PatternAssignment
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: AssignedVariablePattern
name: a
PatternField
pattern: AssignedVariablePattern
name: b
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
leftSeparator: ;
rightSeparator: ;
rightParenthesis: )
body: IntegerLiteral
literal: 0
''');
}
test_pattern_inForPartsWithExpression_statement() {
_parse('''
void f(x) {
for ((a, b) = x; ;) {}
}
''');
var node = findNode.forStatement('for');
assertParsedNodeText(node, r'''
ForStatement
forKeyword: for
leftParenthesis: (
forLoopParts: ForPartsWithExpression
initialization: PatternAssignment
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: AssignedVariablePattern
name: a
PatternField
pattern: AssignedVariablePattern
name: b
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
leftSeparator: ;
rightSeparator: ;
rightParenthesis: )
body: Block
leftBracket: {
rightBracket: }
''');
}
test_patternAssignment_declaresVariableWithMissingName() {
// Test case from https://github.com/dart-lang/sdk/issues/54178.
_parse(
'''
void main() {
final b = (final g, final ) = 55;
}
''',
errors: [
error(ParserErrorCode.patternAssignmentDeclaresVariable, 33, 1),
error(ParserErrorCode.missingIdentifier, 42, 1),
error(ParserErrorCode.patternAssignmentDeclaresVariable, 42, 1),
],
);
// No assertion on the parsed node text; all we are concerned with is that
// the parser doesn't crash.
}
test_patternVariableDeclaration_inClass() {
// If a pattern variable declaration appears outside a function or method,
// the parser recovers by replacing the pattern with a synthetic identifier,
// so that it parses as an ordinary field or top level variable declaration.
_parse(
'''
class C {
var (a, b) = (0, 1);
}
''',
errors: [
error(
ParserErrorCode.patternVariableDeclarationOutsideFunctionOrMethod,
16,
6,
),
],
);
var node = findNode.classDeclaration('class');
assertParsedNodeText(node, r'''
ClassDeclaration
classKeyword: class
name: C
leftBracket: {
members
FieldDeclaration
fields: VariableDeclarationList
keyword: var
variables
VariableDeclaration
name: <empty> <synthetic>
equals: =
initializer: RecordLiteral
leftParenthesis: (
fields
IntegerLiteral
literal: 0
IntegerLiteral
literal: 1
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_patternVariableDeclaration_topLevel() {
// If a pattern variable declaration appears outside a function or method,
// the parser recovers by replacing the pattern with a synthetic identifier,
// so that it parses as an ordinary field or top level variable declaration.
_parse(
'''
var (a, b) = (0, 1);
''',
errors: [
error(
ParserErrorCode.patternVariableDeclarationOutsideFunctionOrMethod,
4,
6,
),
],
);
var node = findNode.unit;
assertParsedNodeText(node, r'''
CompilationUnit
declarations
TopLevelVariableDeclaration
variables: VariableDeclarationList
keyword: var
variables
VariableDeclaration
name: <empty> <synthetic>
equals: =
initializer: RecordLiteral
leftParenthesis: (
fields
IntegerLiteral
literal: 0
IntegerLiteral
literal: 1
rightParenthesis: )
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_disallowsConst() {
// TODO(paulberry): do better error recovery.
_parse(
'''
f(x) {
const (_) = x;
}
''',
errors: [
error(ParserErrorCode.missingAssignableSelector, 9, 9),
error(ParserErrorCode.illegalAssignmentToNonAssignable, 9, 9),
error(ParserErrorCode.recordLiteralOnePositionalNoTrailingComma, 17, 1),
],
);
}
test_patternVariableDeclarationStatement_disallowsLate() {
_parse(
'''
f(x) {
late var (_) = x;
}
''',
errors: [error(ParserErrorCode.latePatternVariableDeclaration, 9, 4)],
);
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: WildcardPattern
name: _
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_final_extractor() {
_parse('''
f(x) {
final C(f: a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: final
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_final_list() {
_parse('''
f(x) {
final [a] = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: final
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
name: a
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_final_map() {
_parse('''
f(x) {
final {'a': a} = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: final
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: DeclaredVariablePattern
name: a
rightBracket: }
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_final_parenthesized() {
_parse('''
f(x) {
final (a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: final
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_final_record() {
_parse('''
f(x) {
final (a,) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: final
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_var_extractor() {
_parse('''
f(x) {
var C(f: a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_var_list() {
_parse('''
f(x) {
var [a] = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
name: a
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_var_map() {
_parse('''
f(x) {
var {'a': a} = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: DeclaredVariablePattern
name: a
rightBracket: }
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_var_parenthesized() {
_parse('''
f(x) {
var (a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_noMetadata_var_record() {
_parse('''
f(x) {
var (a,) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_final_extractor() {
_parse('''
f(x) {
@annotation
final C(f: a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: final
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_final_list() {
_parse('''
f(x) {
@annotation
final [a] = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: final
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
name: a
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_final_map() {
_parse('''
f(x) {
@annotation
final {'a': a} = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: final
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: DeclaredVariablePattern
name: a
rightBracket: }
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_final_parenthesized() {
_parse('''
f(x) {
@annotation
final (a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: final
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_final_record() {
_parse('''
f(x) {
@annotation
final (a,) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: final
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_var_extractor() {
_parse('''
f(x) {
@annotation
var C(f: a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_var_list() {
_parse('''
f(x) {
@annotation
var [a] = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
name: a
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_var_map() {
_parse('''
f(x) {
@annotation
var {'a': a} = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: DeclaredVariablePattern
name: a
rightBracket: }
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_var_parenthesized() {
_parse('''
f(x) {
@annotation
var (a) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_patternVariableDeclarationStatement_withMetadata_var_record() {
_parse('''
f(x) {
@annotation
var (a,) = x;
}
''');
var node = findNode.patternVariableDeclarationStatement('= x');
assertParsedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: annotation
keyword: var
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
equals: =
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
test_prefixedIdentifier_when_not() {
// Based on the repro from https://github.com/dart-lang/sdk/issues/52199.
_parse('''
void f(x) {
switch (x) {
case Enum.value when !flag:
}
}
''');
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: Enum
period: .
identifier: SimpleIdentifier
token: value
whenClause: WhenClause
whenKeyword: when
expression: PrefixExpression
operator: !
operand: SimpleIdentifier
token: flag
colon: :
''');
}
test_record_insideAssignment_empty() {
_parse('''
void f(x) {
() = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
rightParenthesis: )
''');
}
test_record_insideAssignment_oneField() {
_parse('''
void f(x) {
(a,) = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: AssignedVariablePattern
name: a
rightParenthesis: )
''');
}
test_record_insideAssignment_twoFields() {
_parse('''
void f(x) {
(a, b) = x;
}
''');
var node = findNode.patternAssignment('= x').pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: AssignedVariablePattern
name: a
PatternField
pattern: AssignedVariablePattern
name: b
rightParenthesis: )
''');
}
test_record_insideCase_empty() {
_parse('''
void f(x) {
switch (x) {
case ():
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
rightParenthesis: )
''');
}
test_record_insideCase_oneField() {
_parse('''
void f(x) {
switch (x) {
case (1,):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_record_insideCase_twoFields() {
_parse('''
void f(x) {
switch (x) {
case (1, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_record_insideCast() {
_parse('''
void f(x) {
switch (x) {
case (1, 2) as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
asToken: as
type: NamedType
name: Object
''');
}
test_record_insideDeclaration_empty() {
_parse('''
void f(x) {
var () = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
rightParenthesis: )
''');
}
test_record_insideDeclaration_oneField() {
_parse('''
void f(x) {
var (a,) = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
rightParenthesis: )
''');
}
test_record_insideDeclaration_twoFields() {
_parse('''
void f(x) {
var (a, b) = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: DeclaredVariablePattern
name: a
PatternField
pattern: DeclaredVariablePattern
name: b
rightParenthesis: )
''');
}
test_record_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case (1, 2)!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
operator: !
''');
}
test_record_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case (1, 2)?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
operator: ?
''');
}
test_recordPattern_nonNullable_beforeAs() {
_parse('''
void f(x) {
switch (x) {
case (_,) as (Object,):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: WildcardPattern
name: _
rightParenthesis: )
asToken: as
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_recordPattern_nonNullable_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case (_,) when true:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: WildcardPattern
name: _
rightParenthesis: )
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_recordPattern_nullable_beforeAs() {
_parse(
'''
void f(x) {
switch (x) {
case (_,)? as (Object,):
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 36, 5)],
);
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: NullCheckPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: WildcardPattern
name: _
rightParenthesis: )
operator: ?
asToken: as
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_recordPattern_nullable_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case (_,)? when true:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullCheckPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: WildcardPattern
name: _
rightParenthesis: )
operator: ?
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_recordTypedVariablePattern_nonNullable_beforeAnd() {
_parse('''
void f(x) {
switch (x) {
case (int,) y && _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalAndPattern
leftOperand: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
operator: &&
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedVariablePattern_nonNullable_beforeAs() {
_parse('''
void f(x) {
switch (x) {
case (int,) y as (Object,):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
asToken: as
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_recordTypedVariablePattern_nonNullable_beforeColon() {
_parse('''
void f(x) {
switch (x) {
case (int,) y:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
''');
}
test_recordTypedVariablePattern_nonNullable_beforeComma() {
_parse('''
void f(x) {
switch (x) {
case [(int,) y, _]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
WildcardPattern
name: _
rightBracket: ]
''');
}
test_recordTypedVariablePattern_nonNullable_beforeExclamation() {
_parse('''
void f(x) {
switch (x) {
case (int,) y!:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullAssertPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
operator: !
''');
}
test_recordTypedVariablePattern_nonNullable_beforeOr() {
_parse('''
void f(x) {
switch (x) {
case (int,) y || _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalOrPattern
leftOperand: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
operator: ||
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedVariablePattern_nonNullable_beforeQuestion() {
_parse('''
void f(x) {
switch (x) {
case (int,) y?:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullCheckPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
operator: ?
''');
}
test_recordTypedVariablePattern_nonNullable_beforeRightArrow() {
_parse('''
void f(x) => switch (x) { (int,) y => 0 };
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
''');
}
test_recordTypedVariablePattern_nonNullable_beforeRightBrace() {
_parse('''
void f(x) {
switch (x) {
case {0: (int,) y}:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: IntegerLiteral
literal: 0
separator: :
value: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
rightBracket: }
''');
}
test_recordTypedVariablePattern_nonNullable_beforeRightBracket() {
_parse('''
void f(x) {
switch (x) {
case [(int,) y]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
rightBracket: ]
''');
}
test_recordTypedVariablePattern_nonNullable_beforeRightParen() {
_parse('''
void f(x) {
switch (x) {
case ((int,) y):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
rightParenthesis: )
''');
}
test_recordTypedVariablePattern_nonNullable_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case (int,) y when true:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: y
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_recordTypedVariablePattern_nullable_beforeAnd() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y && _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalAndPattern
leftOperand: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
operator: &&
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedVariablePattern_nullable_beforeAs() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y as (Object,):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
asToken: as
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_recordTypedVariablePattern_nullable_beforeColon() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
''');
}
test_recordTypedVariablePattern_nullable_beforeComma() {
_parse('''
void f(x) {
switch (x) {
case [(int,)? y, _]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
WildcardPattern
name: _
rightBracket: ]
''');
}
test_recordTypedVariablePattern_nullable_beforeExclamation() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y!:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullAssertPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
operator: !
''');
}
test_recordTypedVariablePattern_nullable_beforeOr() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y || _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalOrPattern
leftOperand: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
operator: ||
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedVariablePattern_nullable_beforeQuestion() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y?:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullCheckPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
operator: ?
''');
}
test_recordTypedVariablePattern_nullable_beforeRightArrow() {
_parse('''
void f(x) => switch (x) { (int,)? y => 0 };
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
''');
}
test_recordTypedVariablePattern_nullable_beforeRightBrace() {
_parse('''
void f(x) {
switch (x) {
case {0: (int,)? y}:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: IntegerLiteral
literal: 0
separator: :
value: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
rightBracket: }
''');
}
test_recordTypedVariablePattern_nullable_beforeRightBracket() {
_parse('''
void f(x) {
switch (x) {
case [(int,)? y]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
rightBracket: ]
''');
}
test_recordTypedVariablePattern_nullable_beforeRightParen() {
_parse('''
void f(x) {
switch (x) {
case ((int,)? y):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
rightParenthesis: )
''');
}
test_recordTypedVariablePattern_nullable_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case (int,)? y when true:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: y
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeAnd() {
_parse('''
void f(x) {
switch (x) {
case (int,) _ && _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalAndPattern
leftOperand: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
operator: &&
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeAs() {
_parse('''
void f(x) {
switch (x) {
case (int,) _ as (Object,):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
asToken: as
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeColon() {
_parse('''
void f(x) {
switch (x) {
case (int,) _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeComma() {
_parse('''
void f(x) {
switch (x) {
case [(int,) _, _]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
WildcardPattern
name: _
rightBracket: ]
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeExclamation() {
_parse('''
void f(x) {
switch (x) {
case (int,) _!:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullAssertPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
operator: !
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeOr() {
_parse('''
void f(x) {
switch (x) {
case (int,) _ || _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalOrPattern
leftOperand: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
operator: ||
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeQuestion() {
_parse('''
void f(x) {
switch (x) {
case (int,) _?:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullCheckPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
operator: ?
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeRightArrow() {
_parse('''
void f(x) => switch (x) { (int,) _ => 0 };
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeRightBrace() {
_parse('''
void f(x) {
switch (x) {
case {0: (int,) _}:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: IntegerLiteral
literal: 0
separator: :
value: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
rightBracket: }
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeRightBracket() {
_parse('''
void f(x) {
switch (x) {
case [(int,) _]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
rightBracket: ]
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeRightParen() {
_parse('''
void f(x) {
switch (x) {
case ((int,) _):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
rightParenthesis: )
''');
}
test_recordTypedWildcardPattern_nonNullable_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case (int,) _ when true:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
name: _
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_recordTypedWildcardPattern_nullable_beforeAnd() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _ && _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalAndPattern
leftOperand: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
operator: &&
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedWildcardPattern_nullable_beforeAs() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _ as (Object,):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
asToken: as
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_recordTypedWildcardPattern_nullable_beforeColon() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
''');
}
test_recordTypedWildcardPattern_nullable_beforeComma() {
_parse('''
void f(x) {
switch (x) {
case [(int,)? _, _]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
WildcardPattern
name: _
rightBracket: ]
''');
}
test_recordTypedWildcardPattern_nullable_beforeExclamation() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _!:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullAssertPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
operator: !
''');
}
test_recordTypedWildcardPattern_nullable_beforeOr() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _ || _:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: LogicalOrPattern
leftOperand: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
operator: ||
rightOperand: WildcardPattern
name: _
''');
}
test_recordTypedWildcardPattern_nullable_beforeQuestion() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _?:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: NullCheckPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
operator: ?
''');
}
test_recordTypedWildcardPattern_nullable_beforeRightArrow() {
_parse('''
void f(x) => switch (x) { (int,)? _ => 0 };
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
''');
}
test_recordTypedWildcardPattern_nullable_beforeRightBrace() {
_parse('''
void f(x) {
switch (x) {
case {0: (int,)? _}:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: IntegerLiteral
literal: 0
separator: :
value: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
rightBracket: }
''');
}
test_recordTypedWildcardPattern_nullable_beforeRightBracket() {
_parse('''
void f(x) {
switch (x) {
case [(int,)? _]:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ListPattern
leftBracket: [
elements
WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
rightBracket: ]
''');
}
test_recordTypedWildcardPattern_nullable_beforeRightParen() {
_parse('''
void f(x) {
switch (x) {
case ((int,)? _):
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
rightParenthesis: )
''');
}
test_recordTypedWildcardPattern_nullable_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case (int,)? _ when true:
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
question: ?
name: _
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_relational_containingBitwiseOrExpression_equality() {
_parse('''
void f(x) {
switch (x) {
case == 1 | 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: ==
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: |
rightOperand: IntegerLiteral
literal: 2
''');
}
test_relational_containingBitwiseOrExpression_relational() {
_parse('''
void f(x) {
switch (x) {
case > 1 | 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: >
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: |
rightOperand: IntegerLiteral
literal: 2
''');
}
test_relational_containingRelationalExpression_equality() {
// The patterns grammar doesn't allow a relational expression inside a
// relational pattern (even though technically it would be unambiguous).
// TODO(paulberry): try to improve parser error recovery in this scenario.
_parse(
'''
void f(x) {
switch (x) {
case == 1 > 0:
break;
}
}
''',
errors: [
error(ParserErrorCode.expectedToken, 41, 1),
error(ParserErrorCode.missingIdentifier, 41, 1),
error(ParserErrorCode.expectedToken, 43, 1),
error(ParserErrorCode.missingIdentifier, 44, 1),
error(ParserErrorCode.unexpectedToken, 44, 1),
],
);
// We don't care what the parsed AST is, just that there are errors.
}
test_relational_containingRelationalExpression_relational() {
// The patterns grammar doesn't allow a relational expression inside a
// relational pattern (even though technically it would be unambiguous).
// TODO(paulberry): try to improve parser error recovery in this scenario.
_parse(
'''
void f(x) {
switch (x) {
case > 1 > 0:
break;
}
}
''',
errors: [
error(ParserErrorCode.expectedToken, 40, 1),
error(ParserErrorCode.missingIdentifier, 40, 1),
error(ParserErrorCode.expectedToken, 42, 1),
error(ParserErrorCode.missingIdentifier, 43, 1),
error(ParserErrorCode.unexpectedToken, 43, 1),
],
);
// We don't care what the parsed AST is, just that there are errors.
}
test_relational_insideCase_equal() {
_parse('''
void f(x) {
switch (x) {
case == 1 << 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: ==
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: <<
rightOperand: IntegerLiteral
literal: 1
''');
}
test_relational_insideCase_greaterThan() {
_parse('''
void f(x) {
switch (x) {
case > 1 << 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: >
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: <<
rightOperand: IntegerLiteral
literal: 1
''');
}
test_relational_insideCase_greaterThanOrEqual() {
_parse('''
void f(x) {
switch (x) {
case >= 1 << 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: >=
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: <<
rightOperand: IntegerLiteral
literal: 1
''');
}
test_relational_insideCase_lessThan() {
_parse('''
void f(x) {
switch (x) {
case < 1 << 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: <
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: <<
rightOperand: IntegerLiteral
literal: 1
''');
}
test_relational_insideCase_lessThanOrEqual() {
_parse('''
void f(x) {
switch (x) {
case <= 1 << 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: <=
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: <<
rightOperand: IntegerLiteral
literal: 1
''');
}
test_relational_insideCase_notEqual() {
_parse('''
void f(x) {
switch (x) {
case != 1 << 1:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RelationalPattern
operator: !=
operand: BinaryExpression
leftOperand: IntegerLiteral
literal: 1
operator: <<
rightOperand: IntegerLiteral
literal: 1
''');
}
test_relational_insideIfCase() {
_parse('''
void f(x) {
if (x case == 1) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
''');
}
test_relational_insideList() {
_parse('''
void f(x) {
switch (x) {
case [== 1]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
rightBracket: ]
''');
}
test_relational_insideLogicalAnd_lhs() {
_parse('''
void f(x) {
switch (x) {
case == 1 && 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
operator: &&
rightOperand: ConstantPattern
expression: IntegerLiteral
literal: 2
''');
}
test_relational_insideLogicalAnd_rhs() {
_parse('''
void f(x) {
switch (x) {
case 1 && == 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalAndPattern
leftOperand: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: &&
rightOperand: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 2
''');
}
test_relational_insideLogicalOr_lhs() {
_parse('''
void f(x) {
switch (x) {
case == 1 || 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
operator: ||
rightOperand: ConstantPattern
expression: IntegerLiteral
literal: 2
''');
}
test_relational_insideLogicalOr_rhs() {
_parse('''
void f(x) {
switch (x) {
case 1 || == 2:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
LogicalOrPattern
leftOperand: ConstantPattern
expression: IntegerLiteral
literal: 1
operator: ||
rightOperand: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 2
''');
}
test_relational_insideMap() {
_parse('''
void f(x) {
switch (x) {
case {'a': == 1}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
MapPatternEntry
key: SimpleStringLiteral
literal: 'a'
separator: :
value: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
rightBracket: }
''');
}
test_relational_insideNullCheck_equal() {
_parse(
'''
void f(x) {
switch (x) {
case == 1?:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 36, 4)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
operator: ?
''');
}
test_relational_insideNullCheck_greaterThan() {
_parse(
'''
void f(x) {
switch (x) {
case > 1?:
break;
}
}
''',
errors: [error(ParserErrorCode.invalidInsideUnaryPattern, 36, 3)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: RelationalPattern
operator: >
operand: IntegerLiteral
literal: 1
operator: ?
''');
}
test_relational_insideObject_explicitlyNamed() {
_parse('''
class C {
int? f;
}
void f(x) {
switch (x) {
case C(f: == 1):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ObjectPattern
type: NamedType
name: C
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: f
colon: :
pattern: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_relational_insideParenthesized() {
_parse('''
void f(x) {
switch (x) {
case (== 1):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
test_relational_insideRecord_explicitlyNamed() {
_parse('''
void f(x) {
switch (x) {
case (n: == 1, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: n
colon: :
pattern: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_relational_insideRecord_unnamed() {
_parse('''
void f(x) {
switch (x) {
case (== 1, 2):
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
RecordPattern
leftParenthesis: (
fields
PatternField
pattern: RelationalPattern
operator: ==
operand: IntegerLiteral
literal: 1
PatternField
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
rightParenthesis: )
''');
}
test_rest_subpatternStartingTokens() {
// Test a wide variety of rest subpatterns to make sure the parser properly
// identifies each as a subpattern. (The logic for deciding if a rest
// pattern has a subpattern is based on the token that follows the `..`, so
// we test every kind of token that can legally follow `...`). Note that
// not all of these are semantically meaningful, but they should all be
// parseable.
// TODO(paulberry): if support for symbol literal patterns is added (see
// https://github.com/dart-lang/language/issues/2636), adjust this test
// accordingly.
_parse('''
void f(x) {
switch (x) {
case [...== null]:
case [...!= null]:
case [...< 0]:
case [...> 0]:
case [...<= 0]:
case [...>= 0]:
case [...0]:
case [...0.0]:
case [...0x0]:
case [...null]:
case [...false]:
case [...true]:
case [...'foo']:
case [...x]:
case [...const List()]:
case [...var x]:
case [...final x]:
case [...List x]:
case [..._]:
case [...(_)]:
case [...[_]]:
case [...[]]:
case [...<int>[]]:
case [...{}]:
case [...List()]:
break;
}
}
''');
// No assertions; it's sufficient to make sure the parse succeeds without
// errors.
}
test_rest_withoutSubpattern_insideList() {
_parse('''
void f(x) {
switch (x) {
case [...]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
RestPatternElement
operator: ...
rightBracket: ]
''');
}
test_rest_withoutSubpattern_insideMap() {
_parse('''
void f(x) {
switch (x) {
case {...}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
RestPatternElement
operator: ...
rightBracket: }
''');
}
test_rest_withSubpattern_insideList() {
_parse('''
void f(x) {
switch (x) {
case [...var y]:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
ListPattern
leftBracket: [
elements
RestPatternElement
operator: ...
pattern: DeclaredVariablePattern
keyword: var
name: y
rightBracket: ]
''');
}
test_rest_withSubpattern_insideMap() {
// The parser accepts this syntax even though it's not legal dart, because
// we suspect it's a mistake a user is likely to make, and we want to ensure
// that we give a helpful error message.
_parse('''
void f(x) {
switch (x) {
case {...var y}:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
MapPattern
leftBracket: {
elements
RestPatternElement
operator: ...
pattern: DeclaredVariablePattern
keyword: var
name: y
rightBracket: }
''');
}
test_skipOuterPattern_eof() {
// See https://github.com/dart-lang/sdk/issues/50563
_parse(
'''
main() {
int var = 0;
''',
errors: [
error(ParserErrorCode.expectedToken, 11, 3),
error(ParserErrorCode.missingIdentifier, 19, 1),
error(ScannerErrorCode.expectedToken, 24, 1),
],
);
}
test_switchExpression_empty() {
// Even though an empty switch expression is illegal (because it's not
// exhaustive), it should be accepted by the parser to enable analyzer code
// completions.
_parse('''
f(x) => switch(x) {};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
rightBracket: }
''');
}
test_switchExpression_onePattern_guarded() {
_parse('''
f(x) => switch(x) {
_ when true => 0
};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_switchExpression_onePattern_noTrailingComma() {
_parse('''
f(x) => switch(x) {
_ => 0
};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_switchExpression_onePattern_trailingComma() {
_parse('''
f(x) => switch(x) {
_ => 0,
};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_switchExpression_recovery_bogusTokensAfterCase() {
// If the extra tokens after a switch case don't look like they could be a
// pattern, the parser skips to the end of the switch expression to avoid a
// large number of parse errors.
_parse(
'''
f(x) => switch(x) {
int() => 0 : 1
};
''',
errors: [error(ParserErrorCode.expectedToken, 33, 1)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_switchExpression_recovery_bogusTokensAfterCase_laterComma() {
// If the extra tokens after a switch case don't look like they could be a
// pattern, the parser doesn't try to skip beyond the closing `}` to find
// the next case.
_parse(
'''
f(x) => [switch(x) {
int() => 0 : 1
}, 0];
''',
errors: [error(ParserErrorCode.expectedToken, 34, 1)],
);
var node = findNode.listLiteral('[');
assertParsedNodeText(node, r'''
ListLiteral
leftBracket: [
elements
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
IntegerLiteral
literal: 0
rightBracket: ]
''');
}
test_switchExpression_recovery_bogusTokensAfterCase_nestedComma() {
// If the extra tokens after a switch case don't look like they could be a
// pattern, the parser doesn't try to skip to a nested `,` trying to find
// the next case.
_parse(
'''
f(x) => switch(x) {
int() => 0 : (1, 2)
};
''',
errors: [error(ParserErrorCode.expectedToken, 33, 1)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
rightBracket: }
''');
}
test_switchExpression_recovery_caseKeyword() {
_parse(
'''
f(x) => switch (x) {
case 1 => 'one',
case 2 => 'two'
};
''',
errors: [
error(ParserErrorCode.unexpectedToken, 23, 4),
error(ParserErrorCode.unexpectedToken, 42, 4),
],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
arrow: =>
expression: SimpleStringLiteral
literal: 'one'
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
arrow: =>
expression: SimpleStringLiteral
literal: 'two'
rightBracket: }
''');
}
test_switchExpression_recovery_colonInsteadOfArrow() {
_parse(
'''
f(x) => switch (x) {
1: 'one',
2: 'two'
};
''',
errors: [
error(ParserErrorCode.expectedToken, 24, 1),
error(ParserErrorCode.expectedToken, 36, 1),
],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
arrow: :
expression: SimpleStringLiteral
literal: 'one'
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
arrow: :
expression: SimpleStringLiteral
literal: 'two'
rightBracket: }
''');
}
test_switchExpression_recovery_defaultKeyword() {
_parse(
'''
f(x) => switch (x) {
1 => 'one',
default => 'other'
};
''',
errors: [error(ParserErrorCode.defaultInSwitchExpression, 37, 7)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
arrow: =>
expression: SimpleStringLiteral
literal: 'one'
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: default
arrow: =>
expression: SimpleStringLiteral
literal: 'other'
rightBracket: }
''');
}
test_switchExpression_recovery_illegalFunctionExpressionInGuard() {
// If a function expression occurs in a guard, parsing skips to the case
// that follows.
_parse(
'''
f(x) => switch (x) {
_ when () => true => 1,
_ => 2
};
''',
errors: [error(ParserErrorCode.expectedToken, 41, 2)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: BooleanLiteral
literal: true
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: IntegerLiteral
literal: 2
rightBracket: }
''');
}
test_switchExpression_recovery_illegalFunctionExpressionInGuard_semicolon() {
// If a function expression occurs in a guard, parsing skips to the case
// that follows. The logic to skip to the next case understands that a
// naive user might have mistakenly used `;` instead of `,` to separate
// cases.
_parse(
'''
f(x) => switch (x) {
_ when () => true => 1;
_ => 2
};
''',
errors: [error(ParserErrorCode.expectedToken, 41, 2)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: RecordLiteral
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: BooleanLiteral
literal: true
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: IntegerLiteral
literal: 2
rightBracket: }
''');
}
test_switchExpression_recovery_missingComma() {
// If the extra tokens after a switch case look like they could be a
// pattern, the parser assumes there's a missing comma.
_parse(
'''
f(x) => switch(x) {
int() => 0
double() => 1
};
''',
errors: [error(ParserErrorCode.expectedToken, 35, 6)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: int
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 0
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ObjectPattern
type: NamedType
name: double
leftParenthesis: (
rightParenthesis: )
arrow: =>
expression: IntegerLiteral
literal: 1
rightBracket: }
''');
}
test_switchExpression_recovery_semicolonInsteadOfComma() {
_parse(
'''
f(x) => switch (x) {
1 => 'one';
2 => 'two'
};
''',
errors: [error(ParserErrorCode.expectedToken, 33, 1)],
);
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 1
arrow: =>
expression: SimpleStringLiteral
literal: 'one'
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 2
arrow: =>
expression: SimpleStringLiteral
literal: 'two'
rightBracket: }
''');
}
test_switchExpression_recovery_unmatchedLessThanInTokensToBeSkipped() {
// Test case from https://github.com/dart-lang/sdk/issues/54236.
_parse(
'''
f(x) => switch (x) {
1 => 2
> 1 => 1
< 1 => 0
};
''',
errors: [error(ParserErrorCode.expectedToken, 40, 2)],
);
// No assertion on the parsed node text; all we are concerned with is that
// the parser doesn't crash.
}
test_switchExpression_twoPatterns() {
_parse('''
f(x) => switch(x) {
int _ => 0,
_ => 1
};
''');
var node = findNode.switchExpression('switch');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
type: NamedType
name: int
name: _
arrow: =>
expression: IntegerLiteral
literal: 0
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
arrow: =>
expression: IntegerLiteral
literal: 1
rightBracket: }
''');
}
test_syntheticIdentifier_insideListPattern() {
_parse(
'''
void f(Object? x) {
switch (x) {
case [if]:
};
}
''',
errors: [error(ParserErrorCode.missingIdentifier, 45, 2)],
);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ListPattern
leftBracket: [
elements
ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: ]
colon: :
''');
}
test_syntheticIdentifier_insideMapPattern() {
_parse(
'''
void f(Object? x) {
switch (x) {
case {0: if}:
};
}
''',
errors: [
error(ParserErrorCode.missingIdentifier, 48, 2),
error(ParserErrorCode.expectedToken, 48, 2),
error(ParserErrorCode.expectedToken, 48, 2),
],
);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: MapPattern
leftBracket: {
elements
MapPatternEntry
key: IntegerLiteral
literal: 0
separator: :
value: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
MapPatternEntry
key: SimpleIdentifier
token: <empty> <synthetic>
separator: : <synthetic>
value: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: }
colon: :
''');
}
test_syntheticIdentifier_insideParenthesizedPattern() {
_parse(
'''
void f(Object? x) {
switch (x) {
case (if):
};
}
''',
errors: [
error(ParserErrorCode.missingIdentifier, 45, 2),
error(ParserErrorCode.expectedToken, 45, 2),
],
);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightParenthesis: )
colon: :
''');
}
test_syntheticIdentifier_insideRecordPattern() {
_parse(
'''
void f(Object? x) {
switch (x) {
case (_, if):
};
}
''',
errors: [
error(ParserErrorCode.missingIdentifier, 48, 2),
error(ParserErrorCode.expectedToken, 48, 2),
],
);
var node = findNode.switchPatternCase('case');
assertParsedNodeText(node, r'''
SwitchPatternCase
keyword: case
guardedPattern: GuardedPattern
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: WildcardPattern
name: _
PatternField
pattern: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
rightParenthesis: )
colon: :
''');
}
test_syntheticIdentifier_insideSwitchExpression() {
_parse(
'''
void f(Object? x) => switch (x) {if};
''',
errors: [
error(ParserErrorCode.missingIdentifier, 33, 2),
error(ParserErrorCode.expectedToken, 33, 2),
error(ParserErrorCode.expectedToken, 33, 2),
],
);
var node = findNode.switchExpression('if');
assertParsedNodeText(node, r'''
SwitchExpression
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
rightParenthesis: )
leftBracket: {
cases
SwitchExpressionCase
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: SimpleIdentifier
token: <empty> <synthetic>
arrow: => <synthetic>
expression: SimpleIdentifier
token: <empty> <synthetic>
rightBracket: }
''');
}
test_typeQuestionBeforeWhen_conditional() {
// The logic for parsing types has special disambiguation rules for deciding
// whether a trailing `?` should be included in the type; these rules are
// based primarily on what token(s) follow the `?`. Make sure that these
// rules do the right thing if the token that follows the `?` is `when`, but
// the `when` is an ordinary identifier.
_parse('''
void f(condition, when, otherwise) => condition as bool ? when : otherwise;
''');
var node = findNode.functionDeclaration('=>').functionExpression.body;
assertParsedNodeText(node, r'''
ExpressionFunctionBody
functionDefinition: =>
expression: ConditionalExpression
condition: AsExpression
expression: SimpleIdentifier
token: condition
asOperator: as
type: NamedType
name: bool
question: ?
thenExpression: SimpleIdentifier
token: when
colon: :
elseExpression: SimpleIdentifier
token: otherwise
semicolon: ;
''');
}
test_typeQuestionBeforeWhen_guard() {
// The logic for parsing types has special disambiguation rules for deciding
// whether a trailing `?` should be included in the type; these rules are
// based primarily on what token(s) follow the `?`. Make sure that these
// rules do the right thing if the token that follows the `?` is the `when`
// of a pattern guard.
_parse('''
void f(x) {
switch (x) {
case _ as int? when x == null:
break;
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: CastPattern
pattern: WildcardPattern
name: _
asToken: as
type: NamedType
name: int
question: ?
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ==
rightOperand: NullLiteral
literal: null
''');
}
test_variable_bare_insideCast() {
_parse('''
void f(x) {
var (y as Object) = x;
}
''');
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: CastPattern
pattern: DeclaredVariablePattern
name: y
asToken: as
type: NamedType
name: Object
rightParenthesis: )
''');
}
test_variable_final_inDeclarationContext() {
_parse(
'''
void f(x) {
var (final y) = x;
}
''',
errors: [
error(
ParserErrorCode.variablePatternKeywordInDeclarationContext,
19,
5,
),
],
);
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
keyword: final
name: y
rightParenthesis: )
''');
}
test_variable_final_untyped_insideIfCase() {
_parse('''
void f(x) {
if (x case final y) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: DeclaredVariablePattern
keyword: final
name: y
''');
}
test_variable_final_untyped_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case final y!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: DeclaredVariablePattern
keyword: final
name: y
operator: !
''');
}
test_variable_final_untyped_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case final y?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: DeclaredVariablePattern
keyword: final
name: y
operator: ?
''');
}
test_variable_namedAs() {
_parse(
'''
void f(x) {
switch (x) {
case var as:
}
}
''',
errors: [error(ParserErrorCode.illegalPatternVariableName, 40, 2)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
DeclaredVariablePattern
keyword: var
name: as
''');
}
test_variable_namedWhen() {
_parse(
'''
void f(x) {
switch (x) {
case var when:
}
}
''',
errors: [error(ParserErrorCode.illegalPatternVariableName, 40, 4)],
);
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
DeclaredVariablePattern
keyword: var
name: when
''');
}
test_variable_type_record_empty_inDeclarationContext() {
_parse('''
void f(x) {
var (() y) = x;
}
''');
var node = findNode.patternVariableDeclaration('var').pattern;
assertParsedNodeText(node, '''
ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
rightParenthesis: )
name: y
rightParenthesis: )
''');
}
test_variable_type_record_empty_inMatchingContext() {
_parse('''
void f(x) {
switch (x) {
case () y:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, '''
DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
rightParenthesis: )
name: y
''');
}
test_variable_type_record_nonEmpty_inDeclarationContext() {
_parse('''
void f(x) {
var ((int, String) y) = x;
}
''');
var node = findNode.patternVariableDeclaration('var').pattern;
assertParsedNodeText(node, '''
ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: String
rightParenthesis: )
name: y
rightParenthesis: )
''');
}
test_variable_type_record_nonEmpty_inMatchingContext() {
_parse('''
void f(x) {
switch (x) {
case (int, String) y:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, '''
DeclaredVariablePattern
type: RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: String
rightParenthesis: )
name: y
''');
}
test_variable_typed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case int y:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
DeclaredVariablePattern
type: NamedType
name: int
name: y
''');
}
test_variable_typed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case int y as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: DeclaredVariablePattern
type: NamedType
name: int
name: y
asToken: as
type: NamedType
name: Object
''');
}
test_variable_typed_insideIfCase() {
_parse('''
void f(x) {
if (x case int y) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: DeclaredVariablePattern
type: NamedType
name: int
name: y
''');
}
test_variable_typed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case int y!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: DeclaredVariablePattern
type: NamedType
name: int
name: y
operator: !
''');
}
test_variable_typed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case int y?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: DeclaredVariablePattern
type: NamedType
name: int
name: y
operator: ?
''');
}
test_variable_typedNamedUnderscore_insideCase() {
// We need to make sure the `_` isn't misinterpreted as a wildcard pattern
_parse('''
void f(x) {
switch (x) {
case _ y:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
DeclaredVariablePattern
type: NamedType
name: _
name: y
''');
}
test_variable_var_inDeclarationContext() {
_parse(
'''
void f(x) {
var (var y) = x;
}
''',
errors: [
error(
ParserErrorCode.variablePatternKeywordInDeclarationContext,
19,
3,
),
],
);
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
keyword: var
name: y
rightParenthesis: )
''');
}
test_variable_var_insideCase() {
_parse('''
void f(x) {
switch (x) {
case var y:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
DeclaredVariablePattern
keyword: var
name: y
''');
}
test_variable_var_insideCast() {
_parse('''
void f(x) {
switch (x) {
case var y as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
asToken: as
type: NamedType
name: Object
''');
}
test_variable_var_insideIfCase() {
_parse('''
void f(x) {
if (x case var y) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
''');
}
test_variable_var_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case var y!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
operator: !
''');
}
test_variable_var_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case var y?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: DeclaredVariablePattern
keyword: var
name: y
operator: ?
''');
}
test_varKeywordInTypedVariablePattern_declarationContext() {
_parse(
'''
void f(int x) {
var (var int y) = x;
}
''',
errors: [
error(
ParserErrorCode.variablePatternKeywordInDeclarationContext,
23,
3,
),
],
);
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: DeclaredVariablePattern
keyword: var
type: NamedType
name: int
name: y
rightParenthesis: )
''');
}
test_varKeywordInTypedVariablePattern_declarationContext_wildcard() {
_parse(
'''
void f(x) {
var (var int _) = x;
}
''',
errors: [
error(
ParserErrorCode.variablePatternKeywordInDeclarationContext,
19,
3,
),
],
);
var node = findNode.patternVariableDeclaration('= x').pattern;
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
pattern: WildcardPattern
keyword: var
type: NamedType
name: int
name: _
rightParenthesis: )
''');
}
test_varKeywordInTypedVariablePattern_matchingContext() {
_parse(
'''
void f(x) {
switch (x) {
case var int y:
break;
}
}
''',
errors: [error(ParserErrorCode.varAndType, 36, 3)],
);
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: DeclaredVariablePattern
keyword: var
type: NamedType
name: int
name: y
''');
}
test_varKeywordInTypedVariablePattern_matchingContext_wildcard() {
_parse(
'''
void f(x) {
switch (x) {
case var int _:
break;
}
}
''',
errors: [error(ParserErrorCode.varAndType, 36, 3)],
);
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
keyword: var
type: NamedType
name: int
name: _
''');
}
test_wildcard_bare_beforeWhen() {
_parse('''
void f(x) {
switch (x) {
case _ when true:
break;
}
}
''');
var node = findNode.singleGuardedPattern;
assertParsedNodeText(node, r'''
GuardedPattern
pattern: WildcardPattern
name: _
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
''');
}
test_wildcard_bare_insideCase() {
_parse('''
void f(x) {
switch (x) {
case _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
WildcardPattern
name: _
''');
}
test_wildcard_bare_insideCast() {
_parse('''
void f(x) {
switch (x) {
case _ as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: WildcardPattern
name: _
asToken: as
type: NamedType
name: Object
''');
}
test_wildcard_bare_insideIfCase() {
_parse('''
void f(x) {
if (x case _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
name: _
''');
}
test_wildcard_bare_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case _!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: WildcardPattern
name: _
operator: !
''');
}
test_wildcard_bare_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case _?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: WildcardPattern
name: _
operator: ?
''');
}
test_wildcard_final_typed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case final int _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
WildcardPattern
keyword: final
type: NamedType
name: int
name: _
''');
}
test_wildcard_final_typed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case final int _ as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: WildcardPattern
keyword: final
type: NamedType
name: int
name: _
asToken: as
type: NamedType
name: Object
''');
}
test_wildcard_final_typed_insideIfCase() {
_parse('''
void f(x) {
if (x case final int _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
keyword: final
type: NamedType
name: int
name: _
''');
}
test_wildcard_final_typed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case final int _!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: WildcardPattern
keyword: final
type: NamedType
name: int
name: _
operator: !
''');
}
test_wildcard_final_typed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case final int _?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: WildcardPattern
keyword: final
type: NamedType
name: int
name: _
operator: ?
''');
}
test_wildcard_final_untyped_insideCase() {
_parse('''
void f(x) {
switch (x) {
case final _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
WildcardPattern
keyword: final
name: _
''');
}
test_wildcard_final_untyped_insideCast() {
_parse('''
void f(x) {
switch (x) {
case final _ as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: WildcardPattern
keyword: final
name: _
asToken: as
type: NamedType
name: Object
''');
}
test_wildcard_final_untyped_insideIfCase() {
_parse('''
void f(x) {
if (x case final _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
keyword: final
name: _
''');
}
test_wildcard_final_untyped_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case final _!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: WildcardPattern
keyword: final
name: _
operator: !
''');
}
test_wildcard_final_untyped_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case final _?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: WildcardPattern
keyword: final
name: _
operator: ?
''');
}
test_wildcard_inPatternAssignment_bareIdentifier() {
_parse('''
void f() {
[a, _] = y;
}
''');
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
WildcardPattern
name: _
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_wildcard_inPatternAssignment_usingFinal() {
_parse(
'''
void f() {
[a, final _] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 23, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
WildcardPattern
keyword: final
name: _
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_wildcard_inPatternAssignment_usingFinalAndType() {
_parse(
'''
void f() {
[a, final int _] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 27, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
WildcardPattern
keyword: final
type: NamedType
name: int
name: _
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_wildcard_inPatternAssignment_usingType() {
_parse(
'''
void f() {
[a, int _] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 21, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
WildcardPattern
type: NamedType
name: int
name: _
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_wildcard_inPatternAssignment_usingVar() {
_parse(
'''
void f() {
[a, var _] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 21, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
WildcardPattern
keyword: var
name: _
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_wildcard_inPatternAssignment_usingVarAndType() {
_parse(
'''
void f() {
[a, var int _] = y;
}
''',
errors: [error(ParserErrorCode.patternAssignmentDeclaresVariable, 25, 1)],
);
var node = findNode.patternAssignment('=');
assertParsedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
WildcardPattern
keyword: var
type: NamedType
name: int
name: _
rightBracket: ]
equals: =
expression: SimpleIdentifier
token: y
''');
}
test_wildcard_typed_insideCase() {
_parse('''
void f(x) {
switch (x) {
case int _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
WildcardPattern
type: NamedType
name: int
name: _
''');
}
test_wildcard_typed_insideCast() {
_parse('''
void f(x) {
switch (x) {
case int _ as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: WildcardPattern
type: NamedType
name: int
name: _
asToken: as
type: NamedType
name: Object
''');
}
test_wildcard_typed_insideIfCase() {
_parse('''
void f(x) {
if (x case int _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
type: NamedType
name: int
name: _
''');
}
test_wildcard_typed_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case int _!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: WildcardPattern
type: NamedType
name: int
name: _
operator: !
''');
}
test_wildcard_typed_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case int _?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: WildcardPattern
type: NamedType
name: int
name: _
operator: ?
''');
}
test_wildcard_var_insideCase() {
_parse('''
void f(x) {
switch (x) {
case var _:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
WildcardPattern
keyword: var
name: _
''');
}
test_wildcard_var_insideCast() {
_parse('''
void f(x) {
switch (x) {
case var _ as Object:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
CastPattern
pattern: WildcardPattern
keyword: var
name: _
asToken: as
type: NamedType
name: Object
''');
}
test_wildcard_var_insideIfCase() {
_parse('''
void f(x) {
if (x case var _) {}
}
''');
var node = findNode.caseClause('case');
assertParsedNodeText(node, r'''
CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: WildcardPattern
keyword: var
name: _
''');
}
test_wildcard_var_insideNullAssert() {
_parse('''
void f(x) {
switch (x) {
case var _!:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullAssertPattern
pattern: WildcardPattern
keyword: var
name: _
operator: !
''');
}
test_wildcard_var_insideNullCheck() {
_parse('''
void f(x) {
switch (x) {
case var _?:
break;
}
}
''');
var node = findNode.singleGuardedPattern.pattern;
assertParsedNodeText(node, r'''
NullCheckPattern
pattern: WildcardPattern
keyword: var
name: _
operator: ?
''');
}
void _parse(String content, {List<ExpectedError>? errors}) {
var parseResult = parseStringWithErrors(content);
if (errors != null) {
parseResult.assertErrors(errors);
} else {
parseResult.assertNoErrors();
}
findNode = parseResult.findNode;
}
}