blob: 5e2a3ddb9bfa4ca207f42f36b01ccbe277d9d884 [file] [log] [blame]
// Copyright (c) 2018, 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/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(IfElementResolutionTest);
});
}
@reflectiveTest
class IfElementResolutionTest extends PubPackageResolutionTest {
test_caseClause() async {
await assertNoErrorsInCode(r'''
void f(Object x) {
[if (x case 0) 1 else 2];
}
''');
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::x
staticType: Object
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
matchedValueType: Object
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
staticType: int
elseKeyword: else
elseElement: IntegerLiteral
literal: 2
staticType: int
''');
}
test_caseClause_topLevelVariableInitializer() async {
await assertNoErrorsInCode(r'''
final x = 0;
final y = [ if (x case var a) a ];
''');
var node = findNode.singleIfElement;
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@getter::x
staticType: int
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: DeclaredVariablePattern
keyword: var
name: a
declaredElement: hasImplicitType a@40
type: int
matchedValueType: int
rightParenthesis: )
thenElement: SimpleIdentifier
token: a
staticElement: a@40
staticType: int
''');
}
test_caseClause_variables_scope() async {
// Each `guardedPattern` introduces a new case scope which is where the
// variables defined by that case's pattern are bound.
// There is no initializing expression for the variables in a case pattern,
// but they are considered initialized after the entire case pattern,
// before the guard expression if there is one. However, all pattern
// variables are in scope in the entire pattern.
await assertErrorsInCode(r'''
const a = 0;
void f(Object x) {
[
if (x case [int a, == a] when a > 0)
a
else
a
];
}
''', [
error(CompileTimeErrorCode.NON_CONSTANT_RELATIONAL_PATTERN_EXPRESSION, 62,
1),
error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 62, 1,
contextMessages: [message(testFile, 56, 1)]),
]);
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::x
staticType: Object
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ListPattern
leftBracket: [
elements
DeclaredVariablePattern
type: NamedType
name: int
element: dart:core::<definingUnit>::@class::int
type: int
name: a
declaredElement: a@56
type: int
matchedValueType: Object?
RelationalPattern
operator: ==
operand: SimpleIdentifier
token: a
staticElement: a@56
staticType: int
element: dart:core::<definingUnit>::@class::Object::@method::==
matchedValueType: Object?
rightBracket: ]
matchedValueType: Object
requiredType: List<Object?>
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: a
staticElement: a@56
staticType: int
operator: >
rightOperand: IntegerLiteral
literal: 0
parameter: dart:core::<definingUnit>::@class::num::@method::>::@parameter::other
staticType: int
staticElement: dart:core::<definingUnit>::@class::num::@method::>
staticInvokeType: bool Function(num)
staticType: bool
rightParenthesis: )
thenElement: SimpleIdentifier
token: a
staticElement: a@56
staticType: int
elseKeyword: else
elseElement: SimpleIdentifier
token: a
staticElement: <thisLibrary>::<definingUnit>::@getter::a
staticType: int
''');
}
test_caseClause_variables_single() async {
await assertErrorsInCode(r'''
void f(Object x) {
[
if (x case int a when a > 0)
a
else
a // error
];
}
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 79, 1),
]);
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::x
staticType: Object
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: DeclaredVariablePattern
type: NamedType
name: int
element: dart:core::<definingUnit>::@class::int
type: int
name: a
declaredElement: a@42
type: int
matchedValueType: Object
whenClause: WhenClause
whenKeyword: when
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: a
staticElement: a@42
staticType: int
operator: >
rightOperand: IntegerLiteral
literal: 0
parameter: dart:core::<definingUnit>::@class::num::@method::>::@parameter::other
staticType: int
staticElement: dart:core::<definingUnit>::@class::num::@method::>
staticInvokeType: bool Function(num)
staticType: bool
rightParenthesis: )
thenElement: SimpleIdentifier
token: a
staticElement: a@42
staticType: int
elseKeyword: else
elseElement: SimpleIdentifier
token: a
staticElement: <null>
staticType: InvalidType
''');
}
test_expression_super() async {
await assertErrorsInCode(r'''
class A {
void f() {
[if (super) 0 else 1];
}
}
''', [
error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 32, 5),
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 32, 5),
]);
var node = findNode.singleIfElement;
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SuperExpression
superKeyword: super
staticType: A
rightParenthesis: )
thenElement: IntegerLiteral
literal: 0
staticType: int
elseKeyword: else
elseElement: IntegerLiteral
literal: 1
staticType: int
''');
}
test_rewrite_caseClause_pattern() async {
await assertNoErrorsInCode(r'''
void f(Object x) {
[if (x case const A()) 0];
}
class A {
const A();
}
''');
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::x
staticType: Object
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
const: const
expression: InstanceCreationExpression
constructorName: ConstructorName
type: NamedType
name: A
element: <thisLibrary>::<definingUnit>::@class::A
type: A
staticElement: <thisLibrary>::<definingUnit>::@class::A::@constructor::new
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticType: A
matchedValueType: Object
rightParenthesis: )
thenElement: IntegerLiteral
literal: 0
staticType: int
''');
}
test_rewrite_expression() async {
await assertNoErrorsInCode(r'''
void f(bool Function() a) {
[if (a()) 0];
}
''');
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: FunctionExpressionInvocation
function: SimpleIdentifier
token: a
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::a
staticType: bool Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: bool Function()
staticType: bool
rightParenthesis: )
thenElement: IntegerLiteral
literal: 0
staticType: int
''');
}
test_rewrite_expression_caseClause() async {
await assertNoErrorsInCode(r'''
void f(int Function() a) {
[if (a() case 0) 1];
}
''');
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: FunctionExpressionInvocation
function: SimpleIdentifier
token: a
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::a
staticType: int Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: int Function()
staticType: int
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
matchedValueType: int
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
staticType: int
''');
}
test_rewrite_whenClause() async {
await assertNoErrorsInCode(r'''
void f(Object x, bool Function() a) {
[if (x case 0 when a()) 1];
}
''');
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::x
staticType: Object
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
matchedValueType: Object
whenClause: WhenClause
whenKeyword: when
expression: FunctionExpressionInvocation
function: SimpleIdentifier
token: a
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::a
staticType: bool Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: bool Function()
staticType: bool
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
staticType: int
''');
}
test_whenClause() async {
await assertNoErrorsInCode(r'''
void f(Object x) {
[if (x case 0 when true) 1 else 2];
}
''');
var node = findNode.ifElement('if');
assertResolvedNodeText(node, r'''
IfElement
ifKeyword: if
leftParenthesis: (
expression: SimpleIdentifier
token: x
staticElement: <thisLibrary>::<definingUnit>::@function::f::@parameter::x
staticType: Object
caseClause: CaseClause
caseKeyword: case
guardedPattern: GuardedPattern
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
matchedValueType: Object
whenClause: WhenClause
whenKeyword: when
expression: BooleanLiteral
literal: true
staticType: bool
rightParenthesis: )
thenElement: IntegerLiteral
literal: 1
staticType: int
elseKeyword: else
elseElement: IntegerLiteral
literal: 2
staticType: int
''');
}
}