Resolve WhenClause in SwitchStatement cases.

Change-Id: I836d0bec357597490ad7302e90ff9e4740547810
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264880
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2022-10-19 17:27:38 +00:00 committed by Commit Queue
parent 35d6ecbcd6
commit d923f69436
4 changed files with 355 additions and 2 deletions

View file

@ -778,14 +778,23 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
getSwitchStatementMemberInfo(covariant SwitchStatement node, int index) {
var member = node.members[index];
AstNode? pattern;
WhenClause? whenClause;
if (member is SwitchCase) {
pattern = member.expression;
} else if (member is SwitchPatternCase) {
pattern = member.pattern;
whenClause = member.whenClause;
}
return SwitchStatementMemberInfo(
[CaseHeadOrDefaultInfo(pattern: pattern)], member.statements,
labels: member.labels);
[
CaseHeadOrDefaultInfo(
pattern: pattern,
guard: whenClause?.expression,
),
],
member.statements,
labels: member.labels,
);
}
@override

View file

@ -144,6 +144,82 @@ IfStatement
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_rewrite_whenClause() async {
await assertNoErrorsInCode(r'''
void f(x, bool Function() a) {
if (x case 0 when a()) {}
}
''');
final node = findNode.ifStatement('if');
assertResolvedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
condition: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: dynamic
caseClause: CaseClause
caseKeyword: case
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
whenClause: WhenClause
whenKeyword: when
expression: FunctionExpressionInvocation
function: SimpleIdentifier
token: a
staticElement: self::@function::f::@parameter::a
staticType: bool Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: bool Function()
staticType: bool
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
test_whenClause() async {
await assertNoErrorsInCode(r'''
void f(x) {
if (x case 0 when true) {}
}
''');
final node = findNode.ifStatement('if');
assertResolvedNodeText(node, r'''
IfStatement
ifKeyword: if
leftParenthesis: (
condition: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: dynamic
caseClause: CaseClause
caseKeyword: case
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
staticType: bool
rightParenthesis: )
thenStatement: Block
leftBracket: {
rightBracket: }
''');
}
}

View file

@ -0,0 +1,266 @@
// 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:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(SwitchStatementPatternTest);
});
}
@reflectiveTest
class SwitchStatementPatternTest extends PatternsResolutionTest {
test_default() async {
await assertNoErrorsInCode(r'''
void f(Object? x) {
switch (x) {
case 0?:
break;
default:
break;
}
}
''');
final node = findNode.switchStatement('switch');
assertResolvedNodeText(node, r'''
SwitchStatement
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: Object?
rightParenthesis: )
leftBracket: {
members
SwitchPatternCase
keyword: case
pattern: PostfixPattern
operand: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
operator: ?
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
SwitchDefault
keyword: default
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
rightBracket: }
''');
}
test_mergeCases() async {
await assertNoErrorsInCode(r'''
void f(Object? x) {
switch (x) {
case 0?:
case 1?:
break;
case 2?:
break;
}
}
''');
final node = findNode.switchStatement('switch');
assertResolvedNodeText(node, r'''
SwitchStatement
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: Object?
rightParenthesis: )
leftBracket: {
members
SwitchPatternCase
keyword: case
pattern: PostfixPattern
operand: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
operator: ?
colon: :
SwitchPatternCase
keyword: case
pattern: PostfixPattern
operand: ConstantPattern
expression: IntegerLiteral
literal: 1
staticType: int
operator: ?
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
SwitchPatternCase
keyword: case
pattern: PostfixPattern
operand: ConstantPattern
expression: IntegerLiteral
literal: 2
staticType: int
operator: ?
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
rightBracket: }
''');
}
test_rewrite_pattern() async {
await assertNoErrorsInCode(r'''
void f(Object? x, int Function() a) {
switch (x) {
case const a():
break;
}
}
''');
final node = findNode.switchStatement('switch');
assertResolvedNodeText(node, r'''
SwitchStatement
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: Object?
rightParenthesis: )
leftBracket: {
members
SwitchPatternCase
keyword: case
pattern: ConstantPattern
const: const
expression: FunctionExpressionInvocation
function: SimpleIdentifier
token: a
staticElement: self::@function::f::@parameter::a
staticType: int Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: int Function()
staticType: int
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
rightBracket: }
''');
}
test_rewrite_whenClause() async {
await assertNoErrorsInCode(r'''
void f(Object? x, bool Function() a) {
switch (x) {
case 0 when a():
break;
}
}
''');
final node = findNode.switchStatement('switch');
assertResolvedNodeText(node, r'''
SwitchStatement
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: Object?
rightParenthesis: )
leftBracket: {
members
SwitchPatternCase
keyword: case
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
whenClause: WhenClause
whenKeyword: when
expression: FunctionExpressionInvocation
function: SimpleIdentifier
token: a
staticElement: self::@function::f::@parameter::a
staticType: bool Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: bool Function()
staticType: bool
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
rightBracket: }
''');
}
test_whenClause() async {
await assertNoErrorsInCode(r'''
void f(Object? x) {
switch (x) {
case 0 when true:
break;
}
}
''');
final node = findNode.switchStatement('switch');
assertResolvedNodeText(node, r'''
SwitchStatement
switchKeyword: switch
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: Object?
rightParenthesis: )
leftBracket: {
members
SwitchPatternCase
keyword: case
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
staticType: bool
colon: :
statements
BreakStatement
breakKeyword: break
semicolon: ;
rightBracket: }
''');
}
}

View file

@ -77,6 +77,7 @@ import 'record_type_annotation_test.dart' as record_type_annotation;
import 'relational_pattern_test.dart' as relational_pattern;
import 'simple_identifier_test.dart' as simple_identifier;
import 'super_formal_parameter_test.dart' as super_formal_parameter;
import 'switch_statement_test.dart' as super_formal_parameter2;
import 'top_level_variable_test.dart' as top_level_variable;
import 'top_type_inference_test.dart' as top_type_inference;
import 'try_statement_test.dart' as try_statement;
@ -158,6 +159,7 @@ main() {
relational_pattern.main();
simple_identifier.main();
super_formal_parameter.main();
super_formal_parameter2.main();
top_level_variable.main();
top_type_inference.main();
try_statement.main();