240eda5647
This also includes some small refactorings for parameter names to start using the diagnostic wording instead of error. As well as a small change to `contextMessage` and related to use a list of `Pattern`s instead of a single `String` for better matching. In future CLs, the TODOs added in this one will be addressed so we can fully migrate this. Added them because of the size of the CL. Bug: https://github.com/dart-lang/sdk/issues/61557 Change-Id: I5557668a1baed98faff977255c9f22e0d9d96008 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/452180 Commit-Queue: Paul Berry <paulberry@google.com> Auto-Submit: Felipe Morschel <git@fmorschel.dev> Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
12744 lines
262 KiB
Dart
12744 lines
262 KiB
Dart
// 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:analyzer_testing/src/analysis_rule/pub_package_resolution.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
import '../src/dart/resolution/node_text_expectations.dart';
|
|
import '../src/diagnostics/parser_diagnostics.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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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.
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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:
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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:
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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) {}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [error(ParserErrorCode.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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [error(ParserErrorCode.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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [error(ParserErrorCode.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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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);
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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);
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
error(ParserErrorCode.missingAssignableSelector, 9, 9),
|
|
error(ParserErrorCode.illegalAssignmentToNonAssignable, 9, 9),
|
|
error(ParserErrorCode.recordLiteralOnePositionalNoTrailingComma, 17, 1),
|
|
],
|
|
);
|
|
}
|
|
|
|
test_patternVariableDeclarationStatement_disallowsLate() {
|
|
_parse(
|
|
'''
|
|
f(x) {
|
|
late var (_) = x;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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,):
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
''',
|
|
diagnostics: [
|
|
error(ParserErrorCode.expectedToken, 11, 3),
|
|
error(ParserErrorCode.missingIdentifier, 19, 1),
|
|
error(ParserErrorCode.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
|
|
};
|
|
''',
|
|
diagnostics: [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];
|
|
''',
|
|
diagnostics: [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)
|
|
};
|
|
''',
|
|
diagnostics: [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'
|
|
};
|
|
''',
|
|
diagnostics: [
|
|
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'
|
|
};
|
|
''',
|
|
diagnostics: [
|
|
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'
|
|
};
|
|
''',
|
|
diagnostics: [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
|
|
};
|
|
''',
|
|
diagnostics: [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
|
|
};
|
|
''',
|
|
diagnostics: [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
|
|
};
|
|
''',
|
|
diagnostics: [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'
|
|
};
|
|
''',
|
|
diagnostics: [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
|
|
};
|
|
''',
|
|
diagnostics: [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]:
|
|
};
|
|
}
|
|
''',
|
|
diagnostics: [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}:
|
|
};
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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):
|
|
};
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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):
|
|
};
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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};
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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:
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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:
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
}
|
|
''',
|
|
diagnostics: [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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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;
|
|
}
|
|
''',
|
|
diagnostics: [
|
|
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<ExpectedDiagnostic>? diagnostics}) {
|
|
var parseResult = parseStringWithErrors(content);
|
|
if (diagnostics != null) {
|
|
parseResult.assertErrors(diagnostics);
|
|
} else {
|
|
parseResult.assertNoErrors();
|
|
}
|
|
findNode = parseResult.findNode;
|
|
}
|
|
}
|