| // 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'; | |
| import 'node_text_expectations.dart'; | |
| main() { | |
| defineReflectiveSuite(() { | |
| defineReflectiveTests(SwitchExpressionResolutionTest); | |
| defineReflectiveTests(UpdateNodeTextExpectations); | |
| }); | |
| } | |
| @reflectiveTest | |
| class SwitchExpressionResolutionTest extends PubPackageResolutionTest { | |
| test_case_expression_void() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x) { | |
| (switch(x) { | |
| 0 => 0, | |
| _ => g(), | |
| }); | |
| } | |
| void g() {} | |
| '''); | |
| var node = result.findNode.singleSwitchExpression; | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ConstantPattern | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: UnqualifiedFunctionInvocation | |
| name: g | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| resolution: ExecutableInvocationResolution | |
| element: <testLibrary>::@function::g | |
| invokeType: void Function() | |
| type: void | |
| staticType: void | |
| expression(v1): MethodInvocation | |
| methodName: SimpleIdentifier | |
| token: g | |
| element: <testLibrary>::@function::g | |
| staticType: void Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| staticInvokeType: void Function() | |
| staticType: void | |
| rightBracket: } | |
| staticType: void | |
| '''); | |
| } | |
| test_cases_empty() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| final a = switch (0) {}; | |
| // ^^^^^^ | |
| // [diag.nonExhaustiveSwitchExpression] The type 'int' isn't exhaustively matched by the switch cases since it doesn't match the pattern 'int()'. | |
| '''); | |
| var node = result.findNode.singleSwitchExpression; | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| rightParenthesis: ) | |
| leftBracket: { | |
| rightBracket: } | |
| staticType: Never | |
| '''); | |
| } | |
| test_contextType_case_expression() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| class A { | |
| T foo<T>() => throw 0; | |
| int bar(Object? x) { | |
| return switch (x) { | |
| _ => foo(), | |
| }; | |
| } | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@class::A::@method::bar::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@class::A::@method::bar::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: UnqualifiedFunctionInvocation | |
| name: foo | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| resolution: ExecutableInvocationResolution | |
| element: <testLibrary>::@class::A::@method::foo | |
| invokeType: int Function() | |
| type: int | |
| staticType: int | |
| typeArgumentTypes | |
| int | |
| expression(v1): MethodInvocation | |
| methodName: SimpleIdentifier | |
| token: foo | |
| element: <testLibrary>::@class::A::@method::foo | |
| staticType: T Function<T>() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| staticInvokeType: int Function() | |
| staticType: int | |
| typeArgumentTypes | |
| int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_expression_void() async { | |
| var result = await resolveTestCodeWithDiagnostics(''' | |
| void f(void x) { | |
| (switch(x) { | |
| // ^ | |
| // [diag.useOfVoidResult] This expression has a type of 'void' so its value can't be used. | |
| _ => 0, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.singleSwitchExpression; | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: void | |
| staticType: void | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: void | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: void | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_joinedVariables_inLocalFunction() async { | |
| // Note: this is an important case to test because when variables are inside | |
| // a local function, their enclosing element is `null`. | |
| var result = await resolveTestCodeWithDiagnostics(''' | |
| abstract class C { | |
| List<int> get values; | |
| } | |
| abstract class D { | |
| List<int> get values; | |
| } | |
| test(Object o) => () => | |
| switch (o) { | |
| C(:var values) || D(:var values) => | |
| [for (var value in values) value + 1], | |
| _ => [] | |
| }; | |
| '''); | |
| var node = result.findNode.unqualifiedNameExpression('value + 1'); | |
| assertResolvedNodeText(node, r''' | |
| UnqualifiedNameExpression | |
| name: value | |
| resolution: VariableReadResolution | |
| element: value@185 | |
| type: int | |
| staticType: int | |
| V1: SimpleIdentifier | |
| token: value | |
| element: value@185 | |
| staticType: int | |
| '''); | |
| } | |
| test_location_topLevel() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| num a = 0; | |
| final b = switch (a) { | |
| int(:var isEven) when isEven => 1, | |
| _ => 0, | |
| }; | |
| '''); | |
| var node = result.findNode.singleSwitchExpression; | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: a | |
| resolution: GetterInvocationResolution | |
| element: <testLibrary>::@getter::a | |
| invokeType: num Function() | |
| type: num | |
| staticType: num | |
| expression(v1): SimpleIdentifier | |
| token: a | |
| element: <testLibrary>::@getter::a | |
| staticType: num | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ObjectPattern | |
| type: NamedType | |
| name: int | |
| element: dart:core::@class::int | |
| type: int | |
| leftParenthesis: ( | |
| fields | |
| PatternField | |
| name: PatternFieldName | |
| colon: : | |
| pattern: DeclaredVariablePattern | |
| keyword: var | |
| name: isEven | |
| declaredFragment: isPublic isEven@46 | |
| element: hasImplicitType isPublic | |
| type: bool | |
| matchedValueType: bool | |
| element: dart:core::@class::int::@getter::isEven | |
| rightParenthesis: ) | |
| matchedValueType: num | |
| whenClause: WhenClause | |
| whenKeyword: when | |
| expression2: UnqualifiedNameExpression | |
| name: isEven | |
| resolution: VariableReadResolution | |
| element: isEven@46 | |
| type: bool | |
| staticType: bool | |
| expression(v1): SimpleIdentifier | |
| token: isEven | |
| element: isEven@46 | |
| staticType: bool | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 1 | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: num | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_rewrite_case_expression() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x, int Function() a) { | |
| (switch (x) { | |
| _ => a(), | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpressionCase('_'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: CallInvocation | |
| receiver: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::a | |
| type: int Function() | |
| staticType: int Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| resolution: FunctionTypeInvocationResolution | |
| invokeType: int Function() | |
| type: int | |
| staticType: int | |
| expression(v1): FunctionExpressionInvocation | |
| function: SimpleIdentifier | |
| token: a | |
| element: <testLibrary>::@function::f::@formalParameter::a | |
| staticType: int Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| element: <null> | |
| staticInvokeType: int Function() | |
| staticType: int | |
| '''); | |
| } | |
| test_rewrite_case_pattern() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x) { | |
| (switch (x) { | |
| const A() => 0, | |
| _ => 1, | |
| }); | |
| } | |
| class A { | |
| const A(); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpressionCase('=> 0'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ConstantPattern | |
| constKeyword: const | |
| expression2: ConstructorInvocation | |
| constructorReference: ConstructorReference2 | |
| typeReference: ConstructorTypeReference | |
| name: A | |
| element: <testLibrary>::@class::A | |
| type: A | |
| element: <testLibrary>::@class::A::@constructor::new | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| staticType: A | |
| expression(v1): InstanceCreationExpression | |
| constructorName: ConstructorName | |
| type: NamedType | |
| name: A | |
| element: <testLibrary>::@class::A | |
| type: A | |
| element: <testLibrary>::@class::A::@constructor::new | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| staticType: A | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| '''); | |
| } | |
| test_rewrite_case_whenClause() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x, bool Function() a) { | |
| (switch (x) { | |
| 0 when a() => true, | |
| _ => false, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpressionCase('=> true'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ConstantPattern | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| matchedValueType: Object? | |
| whenClause: WhenClause | |
| whenKeyword: when | |
| expression2: CallInvocation | |
| receiver: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::a | |
| type: bool Function() | |
| staticType: bool Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| resolution: FunctionTypeInvocationResolution | |
| invokeType: bool Function() | |
| type: bool | |
| staticType: bool | |
| expression(v1): FunctionExpressionInvocation | |
| function: SimpleIdentifier | |
| token: a | |
| element: <testLibrary>::@function::f::@formalParameter::a | |
| staticType: bool Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| element: <null> | |
| staticInvokeType: bool Function() | |
| staticType: bool | |
| arrow: => | |
| expression2: BooleanLiteral | |
| literal: true | |
| staticType: bool | |
| '''); | |
| } | |
| test_rewrite_expression() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(int Function() a) { | |
| (switch (a()) { | |
| _ => 0, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: CallInvocation | |
| receiver: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::a | |
| type: int Function() | |
| staticType: int Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| resolution: FunctionTypeInvocationResolution | |
| invokeType: int Function() | |
| type: int | |
| staticType: int | |
| expression(v1): FunctionExpressionInvocation | |
| function: SimpleIdentifier | |
| token: a | |
| element: <testLibrary>::@function::f::@formalParameter::a | |
| staticType: int Function() | |
| argumentList: ArgumentList | |
| leftParenthesis: ( | |
| rightParenthesis: ) | |
| element: <null> | |
| staticInvokeType: int Function() | |
| staticType: int | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: int | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_staticType_cases_leastUpperBound() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x) { | |
| (switch (x) { | |
| true => 0, | |
| _ => null, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ConstantPattern | |
| expression2: BooleanLiteral | |
| literal: true | |
| staticType: bool | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: NullLiteral | |
| literal: null | |
| staticType: Null | |
| rightBracket: } | |
| staticType: int? | |
| '''); | |
| } | |
| test_staticType_cases_same() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x) { | |
| (switch (x) { | |
| true => 0, | |
| _ => 1, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ConstantPattern | |
| expression2: BooleanLiteral | |
| literal: true | |
| staticType: bool | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 1 | |
| staticType: int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_variables_logicalOr() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x) { | |
| (switch (x) { | |
| <int>[var a || var a] => a, | |
| // ^^^^^^^^ | |
| // [diag.deadCode] Dead code. | |
| _ => 0, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ListPattern | |
| typeArguments: TypeArgumentList | |
| leftBracket: < | |
| arguments | |
| NamedType | |
| name: int | |
| element: dart:core::@class::int | |
| type: int | |
| rightBracket: > | |
| leftBracket: [ | |
| elements | |
| LogicalOrPattern | |
| leftOperand: DeclaredVariablePattern | |
| keyword: var | |
| name: a | |
| declaredFragment: isPublic a@50 | |
| element: hasImplicitType isPublic | |
| type: int | |
| matchedValueType: int | |
| operator: || | |
| rightOperand: DeclaredVariablePattern | |
| keyword: var | |
| name: a | |
| declaredFragment: isPublic a@59 | |
| element: hasImplicitType isPublic | |
| type: int | |
| matchedValueType: int | |
| matchedValueType: int | |
| rightBracket: ] | |
| matchedValueType: Object? | |
| requiredType: List<int> | |
| arrow: => | |
| expression2: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: a@null | |
| type: int | |
| staticType: int | |
| expression(v1): SimpleIdentifier | |
| token: a | |
| element: a@null | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_variables_scope() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| const a = 0; | |
| void f(Object? x) { | |
| (switch (x) { | |
| [int a, == a] when a > 0 => a, | |
| // ^ | |
| // [context 1] The declaration of 'a' is here. | |
| // ^ | |
| // [diag.nonConstantRelationalPatternExpression] The relational pattern expression must be a constant. | |
| // [diag.referencedBeforeDeclaration][context 1] Local variable 'a' can't be referenced before it is declared. | |
| _ => 0, | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: ListPattern | |
| leftBracket: [ | |
| elements | |
| DeclaredVariablePattern | |
| type: NamedType | |
| name: int | |
| element: dart:core::@class::int | |
| type: int | |
| name: a | |
| declaredFragment: isPublic a@58 | |
| element: isPublic | |
| type: int | |
| matchedValueType: Object? | |
| RelationalPattern | |
| operator: == | |
| operand2: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: a@58 | |
| type: int | |
| staticType: int | |
| operand(v1): SimpleIdentifier | |
| token: a | |
| element: a@58 | |
| staticType: int | |
| element: dart:core::@class::Object::@method::== | |
| matchedValueType: Object? | |
| rightBracket: ] | |
| matchedValueType: Object? | |
| requiredType: List<Object?> | |
| whenClause: WhenClause | |
| whenKeyword: when | |
| expression2: BinaryOperatorInvocation | |
| leftOperand: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: a@58 | |
| type: int | |
| staticType: int | |
| operator: > | |
| rightOperand: IntegerLiteral | |
| literal: 0 | |
| correspondingParameter: dart:core::@class::num::@method::>::@formalParameter::other | |
| staticType: int | |
| binaryOperator: greaterThan | |
| element: dart:core::@class::num::@method::> | |
| staticType: bool | |
| expression(v1): BinaryExpression | |
| leftOperand: SimpleIdentifier | |
| token: a | |
| element: a@58 | |
| staticType: int | |
| operator: > | |
| rightOperand: IntegerLiteral | |
| literal: 0 | |
| correspondingParameter: dart:core::@class::num::@method::>::@formalParameter::other | |
| staticType: int | |
| element: dart:core::@class::num::@method::> | |
| staticInvokeType: bool Function(num) | |
| staticType: bool | |
| arrow: => | |
| expression2: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: a@58 | |
| type: int | |
| staticType: int | |
| expression(v1): SimpleIdentifier | |
| token: a | |
| element: a@58 | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: IntegerLiteral | |
| literal: 0 | |
| staticType: int | |
| rightBracket: } | |
| staticType: int | |
| '''); | |
| } | |
| test_variables_singleCase() async { | |
| var result = await resolveTestCodeWithDiagnostics(r''' | |
| void f(Object? x) { | |
| (switch (x) { | |
| int a when a > 0 => a, | |
| _ => a, | |
| // ^ | |
| // [diag.undefinedUnqualifiedNameReadNotFound] Undefined name 'a'. | |
| }); | |
| } | |
| '''); | |
| var node = result.findNode.switchExpression('switch'); | |
| assertResolvedNodeText(node, r''' | |
| SwitchExpression | |
| switchKeyword: switch | |
| leftParenthesis: ( | |
| expression2: UnqualifiedNameExpression | |
| name: x | |
| resolution: VariableReadResolution | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| type: Object? | |
| staticType: Object? | |
| expression(v1): SimpleIdentifier | |
| token: x | |
| element: <testLibrary>::@function::f::@formalParameter::x | |
| staticType: Object? | |
| rightParenthesis: ) | |
| leftBracket: { | |
| cases | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: DeclaredVariablePattern | |
| type: NamedType | |
| name: int | |
| element: dart:core::@class::int | |
| type: int | |
| name: a | |
| declaredFragment: isPublic a@44 | |
| element: isPublic | |
| type: int | |
| matchedValueType: Object? | |
| whenClause: WhenClause | |
| whenKeyword: when | |
| expression2: BinaryOperatorInvocation | |
| leftOperand: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: a@44 | |
| type: int | |
| staticType: int | |
| operator: > | |
| rightOperand: IntegerLiteral | |
| literal: 0 | |
| correspondingParameter: dart:core::@class::num::@method::>::@formalParameter::other | |
| staticType: int | |
| binaryOperator: greaterThan | |
| element: dart:core::@class::num::@method::> | |
| staticType: bool | |
| expression(v1): BinaryExpression | |
| leftOperand: SimpleIdentifier | |
| token: a | |
| element: a@44 | |
| staticType: int | |
| operator: > | |
| rightOperand: IntegerLiteral | |
| literal: 0 | |
| correspondingParameter: dart:core::@class::num::@method::>::@formalParameter::other | |
| staticType: int | |
| element: dart:core::@class::num::@method::> | |
| staticInvokeType: bool Function(num) | |
| staticType: bool | |
| arrow: => | |
| expression2: UnqualifiedNameExpression | |
| name: a | |
| resolution: VariableReadResolution | |
| element: a@44 | |
| type: int | |
| staticType: int | |
| expression(v1): SimpleIdentifier | |
| token: a | |
| element: a@44 | |
| staticType: int | |
| SwitchExpressionCase | |
| guardedPattern: GuardedPattern | |
| pattern: WildcardPattern | |
| name: _ | |
| matchedValueType: Object? | |
| arrow: => | |
| expression2: UnqualifiedNameExpression | |
| name: a | |
| resolution: InvalidNamedReadResolution | |
| recoveryElement: <null> | |
| staticType: InvalidType | |
| expression(v1): SimpleIdentifier | |
| token: a | |
| element: <null> | |
| staticType: InvalidType | |
| rightBracket: } | |
| staticType: InvalidType | |
| '''); | |
| } | |
| } |