diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index 0b80ee22b43..794172a0e27 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -778,14 +778,23 @@ class ResolverVisitor extends ThrowingAstVisitor 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 diff --git a/pkg/analyzer/test/src/dart/resolution/if_statement_test.dart b/pkg/analyzer/test/src/dart/resolution/if_statement_test.dart index 55fe891447c..871cf4da570 100644 --- a/pkg/analyzer/test/src/dart/resolution/if_statement_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/if_statement_test.dart @@ -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: + 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: } '''); } } diff --git a/pkg/analyzer/test/src/dart/resolution/switch_statement_test.dart b/pkg/analyzer/test/src/dart/resolution/switch_statement_test.dart new file mode 100644 index 00000000000..e81caa69da2 --- /dev/null +++ b/pkg/analyzer/test/src/dart/resolution/switch_statement_test.dart @@ -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: + 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: + 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: } +'''); + } +} diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart index ebb56f895bc..2473218b7f2 100644 --- a/pkg/analyzer/test/src/dart/resolution/test_all.dart +++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart @@ -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();