blob: 6a2969e2ddc0c49ab4f45cc7bd769b7f07b8e9b6 [file] [log] [blame]
// 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/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PatternAssignmentResolutionTest);
});
}
@reflectiveTest
class PatternAssignmentResolutionTest extends PubPackageResolutionTest {
test_assignable_final_definitelyAssigned() async {
await assertErrorsInCode(
r'''
void f() {
final int a;
a = 0;
(a) = 1;
a;
}
''',
[error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL, 38, 1)],
);
}
test_assignable_final_definitelyUnassigned() async {
await assertNoErrorsInCode(r'''
void f() {
final int a;
(a) = 0;
a;
}
''');
}
test_assignable_final_notDefinitelyUnassigned() async {
await assertErrorsInCode(
r'''
void f(bool flag) {
final int a;
if (flag) {
a = 0;
}
(a) = 1;
a;
}
''',
[error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL, 67, 1)],
);
}
test_assignable_lateFinal_definitelyAssigned() async {
await assertErrorsInCode(
r'''
void f() {
late final int a;
a = 0;
(a) = 1;
a;
}
''',
[error(CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED, 43, 1)],
);
}
test_assignable_lateFinal_definitelyUnassigned() async {
await assertNoErrorsInCode(r'''
void f() {
late final int a;
(a) = 1;
a;
}
''');
}
test_assignable_lateFinal_notDefinitelyAssigned() async {
await assertNoErrorsInCode(r'''
void f(bool flag) {
late final int a;
if (flag) {
a = 0;
}
(a) = 1;
a;
}
''');
}
test_container_listPattern() async {
await assertNoErrorsInCode(r'''
void f(List<int> x, num a) {
[a] = x;
}
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: ListPattern
leftBracket: [
elements
AssignedVariablePattern
name: a
element2: <testLibrary>::@function::f::@formalParameter::a
matchedValueType: int
rightBracket: ]
matchedValueType: List<int>
requiredType: List<int>
equals: =
expression: SimpleIdentifier
token: x
element: <testLibrary>::@function::f::@formalParameter::x
staticType: List<int>
patternTypeSchema: List<num>
staticType: List<int>
''');
}
test_container_objectPattern_implicitGetter() async {
await assertNoErrorsInCode(r'''
class A {
int get foo => 0;
}
void f(int foo) {
A(:foo) = A();
}
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: ObjectPattern
type: NamedType
name: A
element2: <testLibrary>::@class::A
type: A
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: AssignedVariablePattern
name: foo
element2: <testLibrary>::@function::f::@formalParameter::foo
matchedValueType: int
element2: <testLibrary>::@class::A::@getter::foo
rightParenthesis: )
matchedValueType: A
equals: =
expression: InstanceCreationExpression
constructorName: ConstructorName
type: NamedType
name: A
element2: <testLibrary>::@class::A
type: A
element: <testLibrary>::@class::A::@constructor::new
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticType: A
patternTypeSchema: A
staticType: A
''');
}
test_container_parenthesizedPattern() async {
await assertNoErrorsInCode(r'''
void f(int x, num a) {
(a) = x;
}
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: AssignedVariablePattern
name: a
element2: <testLibrary>::@function::f::@formalParameter::a
matchedValueType: int
rightParenthesis: )
matchedValueType: int
equals: =
expression: SimpleIdentifier
token: x
element: <testLibrary>::@function::f::@formalParameter::x
staticType: int
patternTypeSchema: num
staticType: int
''');
}
test_container_parenthesizedPattern_schema() async {
await assertNoErrorsInCode(r'''
void f(int a) {
(a) = g();
}
T g<T>() => throw 0;
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: AssignedVariablePattern
name: a
element2: <testLibrary>::@function::f::@formalParameter::a
matchedValueType: int
rightParenthesis: )
matchedValueType: int
equals: =
expression: MethodInvocation
methodName: SimpleIdentifier
token: g
element: <testLibrary>::@function::g
staticType: T Function<T>()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticInvokeType: int Function()
staticType: int
typeArgumentTypes
int
patternTypeSchema: int
staticType: int
''');
}
test_container_recordPattern_named() async {
await assertNoErrorsInCode(r'''
void f(({int foo}) x, num a) {
(foo: a,) = x;
}
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
name: foo
colon: :
pattern: AssignedVariablePattern
name: a
element2: <testLibrary>::@function::f::@formalParameter::a
matchedValueType: int
element2: <null>
rightParenthesis: )
matchedValueType: ({int foo})
equals: =
expression: SimpleIdentifier
token: x
element: <testLibrary>::@function::f::@formalParameter::x
staticType: ({int foo})
patternTypeSchema: ({num foo})
staticType: ({int foo})
''');
}
test_container_recordPattern_named_implicit() async {
await assertNoErrorsInCode(r'''
void f(int a) {
(:a) = (a: 0);
}
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
name: PatternFieldName
colon: :
pattern: AssignedVariablePattern
name: a
element2: <testLibrary>::@function::f::@formalParameter::a
matchedValueType: int
element2: <null>
rightParenthesis: )
matchedValueType: ({int a})
equals: =
expression: RecordLiteral
leftParenthesis: (
fields
NamedExpression
name: Label
label: SimpleIdentifier
token: a
element: <null>
staticType: null
colon: :
expression: IntegerLiteral
literal: 0
staticType: int
rightParenthesis: )
staticType: ({int a})
patternTypeSchema: ({int a})
staticType: ({int a})
''');
}
test_container_recordPattern_positional() async {
await assertNoErrorsInCode(r'''
void f((int,) x, num a) {
(a,) = x;
}
''');
var node = findNode.singlePatternAssignment;
assertResolvedNodeText(node, r'''
PatternAssignment
pattern: RecordPattern
leftParenthesis: (
fields
PatternField
pattern: AssignedVariablePattern
name: a
element2: <testLibrary>::@function::f::@formalParameter::a
matchedValueType: int
element2: <null>
rightParenthesis: )
matchedValueType: (int,)
equals: =
expression: SimpleIdentifier
token: x
element: <testLibrary>::@function::f::@formalParameter::x
staticType: (int,)
patternTypeSchema: (num,)
staticType: (int,)
''');
}
test_declaredVariable_inPatternAssignment_referenced() async {
// Note: the error is reporting during parsing but we test it here to make
// sure that error recovery produces an AST that can be analyzed without
// crashing.
await assertErrorsInCode(
r'''
void f(a, y) {
[a, var d] = y;
d;
}
''',
[
// The reference doesn't resolve so the errors include
// UNUSED_LOCAL_VARIABLE and UNDEFINED_IDENTIFIER.
error(ParserErrorCode.PATTERN_ASSIGNMENT_DECLARES_VARIABLE, 25, 1),
error(WarningCode.UNUSED_LOCAL_VARIABLE, 25, 1),
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 35, 1),
],
);
}
test_declaredVariable_inPatternAssignment_unreferenced() async {
// Note: the error is reporting during parsing but we test it here to make
// sure that error recovery produces an AST that can be analyzed without
// crashing.
await assertErrorsInCode(
r'''
void f(a, y) {
[a, var d] = y;
}
''',
[
error(ParserErrorCode.PATTERN_ASSIGNMENT_DECLARES_VARIABLE, 25, 1),
error(WarningCode.UNUSED_LOCAL_VARIABLE, 25, 1),
],
);
}
test_final_becomesDefinitelyAssigned() async {
await assertErrorsInCode(
r'''
void f() {
final int a;
(a) = 0;
a;
a = 1;
}
''',
[error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL, 44, 1)],
);
}
test_promotes() async {
await assertNoErrorsInCode(r'''
void f(num a) {
if (a is! int) {
(a) = 0;
}
a;
}
''');
var node = findNode.simple('a;');
assertResolvedNodeText(node, r'''
SimpleIdentifier
token: a
element: <testLibrary>::@function::f::@formalParameter::a
staticType: int
''');
}
}