mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:29:50 +00:00
Resolve PatternAssignment and AssignedVariablePattern.
Change-Id: I79a7a3b7f5b5fed349c9d40d61a9e0f0fd3978ae Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/274723 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
de24bf1cce
commit
78fb91e739
|
@ -893,6 +893,8 @@ CompileTimeErrorCode.PART_OF_NON_PART:
|
|||
status: needsEvaluation
|
||||
CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.PATTERN_TYPE_MISMATCH_IN_IRREFUTABLE_CONTEXT:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT:
|
||||
|
|
|
@ -690,7 +690,11 @@ class AssignedVariablePatternImpl extends DartPatternImpl
|
|||
|
||||
@override
|
||||
DartType computePatternSchema(ResolverVisitor resolverVisitor) {
|
||||
throw UnimplementedError('TODO(scheglov)');
|
||||
final element = this.element;
|
||||
if (element is PromotableElement) {
|
||||
return resolverVisitor.analyzeAssignedVariablePatternSchema(element);
|
||||
}
|
||||
return resolverVisitor.unknownType;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -699,7 +703,11 @@ class AssignedVariablePatternImpl extends DartPatternImpl
|
|||
DartType matchedType,
|
||||
SharedMatchContext context,
|
||||
) {
|
||||
throw UnimplementedError('TODO(scheglov)');
|
||||
resolverVisitor.resolveAssignedVariablePattern(
|
||||
node: this,
|
||||
matchedType: matchedType,
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -10088,8 +10096,7 @@ class PatternAssignmentImpl extends ExpressionImpl
|
|||
|
||||
@override
|
||||
void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
|
||||
// TODO(brianwilkerson) implement resolveExpression
|
||||
throw UnimplementedError();
|
||||
resolver.visitPatternAssignment(this);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -166,6 +166,29 @@ class ResolutionVisitor extends RecursiveAstVisitor<void> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void visitAssignedVariablePattern(
|
||||
covariant AssignedVariablePatternImpl node,
|
||||
) {
|
||||
var name = node.name.lexeme;
|
||||
var element = _nameScope.lookup(name).getter;
|
||||
node.element = element;
|
||||
|
||||
if (element == null) {
|
||||
_errorReporter.reportErrorForToken(
|
||||
CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
|
||||
node.name,
|
||||
[name],
|
||||
);
|
||||
} else if (!(element is LocalVariableElement ||
|
||||
element is ParameterElement)) {
|
||||
_errorReporter.reportErrorForToken(
|
||||
CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE,
|
||||
node.name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitAugmentationImportDirective(AugmentationImportDirective node) {
|
||||
final element = node.element;
|
||||
|
|
|
@ -3681,6 +3681,14 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
|||
hasPublishedDocs: true,
|
||||
);
|
||||
|
||||
static const CompileTimeErrorCode PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE =
|
||||
CompileTimeErrorCode(
|
||||
'PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE',
|
||||
"Only local variables or formal parameters can be used in pattern "
|
||||
"assignments.",
|
||||
correctionMessage: "Try assigning to a local variable.",
|
||||
);
|
||||
|
||||
/// Parameters:
|
||||
/// 0: the matched type
|
||||
/// 1: the required type
|
||||
|
|
|
@ -374,6 +374,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY,
|
||||
CompileTimeErrorCode.PART_OF_NON_PART,
|
||||
CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY,
|
||||
CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE,
|
||||
CompileTimeErrorCode.PATTERN_TYPE_MISMATCH_IN_IRREFUTABLE_CONTEXT,
|
||||
CompileTimeErrorCode
|
||||
.POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT,
|
||||
|
|
|
@ -1334,6 +1334,41 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
NodeReplacer.replace(oldNode, newNode, parent: parent);
|
||||
}
|
||||
|
||||
void resolveAssignedVariablePattern({
|
||||
required AssignedVariablePatternImpl node,
|
||||
required DartType matchedType,
|
||||
required SharedMatchContext context,
|
||||
}) {
|
||||
final element = node.element;
|
||||
if (element is! PromotableElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.isFinal) {
|
||||
final flow = this.flow;
|
||||
if (flow != null) {
|
||||
if (element.isLate) {
|
||||
if (flow.isAssigned(element)) {
|
||||
errorReporter.reportErrorForToken(
|
||||
CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED,
|
||||
node.name,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!flow.isUnassigned(element)) {
|
||||
errorReporter.reportErrorForToken(
|
||||
CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL,
|
||||
node.name,
|
||||
[node.name.lexeme],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
analyzeAssignedVariablePattern(matchedType, context, node, element);
|
||||
}
|
||||
|
||||
/// Resolve LHS [node] of an assignment, an explicit [AssignmentExpression],
|
||||
/// or implicit [PrefixExpression] or [PostfixExpression].
|
||||
PropertyElementResolverResult resolveForWrite({
|
||||
|
@ -2890,6 +2925,15 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
elementResolver.visitPartOfDirective(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPatternAssignment(covariant PatternAssignmentImpl node) {
|
||||
checkUnreachableNode(node);
|
||||
node.staticType =
|
||||
analyzePatternAssignment(node, node.pattern, node.expression)
|
||||
.resolveShorting();
|
||||
popRewrite(); // expression
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPatternVariableDeclarationStatement(
|
||||
PatternVariableDeclarationStatement node) {
|
||||
|
|
|
@ -53,6 +53,17 @@ class FindNode {
|
|||
return nodes.single;
|
||||
}
|
||||
|
||||
/// Returns the [PatternAssignment], there must be only one.
|
||||
PatternAssignment get singlePatternAssignment {
|
||||
var nodes = <PatternAssignment>[];
|
||||
unit.accept(
|
||||
FunctionAstVisitor(
|
||||
patternAssignment: nodes.add,
|
||||
),
|
||||
);
|
||||
return nodes.single;
|
||||
}
|
||||
|
||||
/// Returns the [PatternVariableDeclaration], there must be only one.
|
||||
PatternVariableDeclaration get singlePatternVariableDeclaration {
|
||||
var nodes = <PatternVariableDeclaration>[];
|
||||
|
|
|
@ -16,6 +16,7 @@ class FunctionAstVisitor extends RecursiveAstVisitor<void> {
|
|||
final void Function(IfStatement)? ifStatement;
|
||||
final void Function(Label)? label;
|
||||
final void Function(MethodInvocation)? methodInvocation;
|
||||
final void Function(PatternAssignment)? patternAssignment;
|
||||
final void Function(PatternVariableDeclaration)? patternVariableDeclaration;
|
||||
final void Function(PatternVariableDeclarationStatement)?
|
||||
patternVariableDeclarationStatement;
|
||||
|
@ -33,6 +34,7 @@ class FunctionAstVisitor extends RecursiveAstVisitor<void> {
|
|||
this.ifStatement,
|
||||
this.label,
|
||||
this.methodInvocation,
|
||||
this.patternAssignment,
|
||||
this.patternVariableDeclaration,
|
||||
this.patternVariableDeclarationStatement,
|
||||
this.simpleIdentifier,
|
||||
|
@ -101,6 +103,12 @@ class FunctionAstVisitor extends RecursiveAstVisitor<void> {
|
|||
super.visitMethodInvocation(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPatternAssignment(PatternAssignment node) {
|
||||
patternAssignment?.call(node);
|
||||
super.visitPatternAssignment(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPatternVariableDeclaration(PatternVariableDeclaration node) {
|
||||
patternVariableDeclaration?.call(node);
|
||||
|
|
|
@ -11170,6 +11170,9 @@ CompileTimeErrorCode:
|
|||
%uri="lib/part_file.dart"
|
||||
part of 'test.dart';
|
||||
```
|
||||
PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE:
|
||||
problemMessage: Only local variables or formal parameters can be used in pattern assignments.
|
||||
correctionMessage: Try assigning to a local variable.
|
||||
PATTERN_TYPE_MISMATCH_IN_IRREFUTABLE_CONTEXT:
|
||||
problemMessage: "The matched value of type '{0}' isn't assignable to the required type '{1}'."
|
||||
correctionMessage: "Try changing the required type of the pattern, or the matched value type."
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
// 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/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;
|
||||
}
|
||||
''');
|
||||
final node = findNode.singlePatternAssignment;
|
||||
assertResolvedNodeText(node, r'''
|
||||
PatternAssignment
|
||||
pattern: ListPattern
|
||||
leftBracket: [
|
||||
elements
|
||||
AssignedVariablePattern
|
||||
name: a
|
||||
element: self::@function::f::@parameter::a
|
||||
rightBracket: ]
|
||||
requiredType: List<int>
|
||||
equals: =
|
||||
expression: SimpleIdentifier
|
||||
token: x
|
||||
staticElement: self::@function::f::@parameter::x
|
||||
staticType: List<int>
|
||||
staticType: List<int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_container_parenthesizedPattern() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(int x, num a) {
|
||||
(a) = x;
|
||||
}
|
||||
''');
|
||||
final node = findNode.singlePatternAssignment;
|
||||
assertResolvedNodeText(node, r'''
|
||||
PatternAssignment
|
||||
pattern: ParenthesizedPattern
|
||||
leftParenthesis: (
|
||||
pattern: AssignedVariablePattern
|
||||
name: a
|
||||
element: self::@function::f::@parameter::a
|
||||
rightParenthesis: )
|
||||
equals: =
|
||||
expression: SimpleIdentifier
|
||||
token: x
|
||||
staticElement: self::@function::f::@parameter::x
|
||||
staticType: int
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_container_parenthesizedPattern_schema() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(int a) {
|
||||
(a) = g();
|
||||
}
|
||||
|
||||
T g<T>() => throw 0;
|
||||
''');
|
||||
final node = findNode.singlePatternAssignment;
|
||||
assertResolvedNodeText(node, r'''
|
||||
PatternAssignment
|
||||
pattern: ParenthesizedPattern
|
||||
leftParenthesis: (
|
||||
pattern: AssignedVariablePattern
|
||||
name: a
|
||||
element: self::@function::f::@parameter::a
|
||||
rightParenthesis: )
|
||||
equals: =
|
||||
expression: MethodInvocation
|
||||
methodName: SimpleIdentifier
|
||||
token: g
|
||||
staticElement: self::@function::g
|
||||
staticType: T Function<T>()
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
typeArgumentTypes
|
||||
int
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_container_recordPattern_named() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(({int foo}) x, num a) {
|
||||
(foo: a,) = x;
|
||||
}
|
||||
''');
|
||||
final node = findNode.singlePatternAssignment;
|
||||
assertResolvedNodeText(node, r'''
|
||||
PatternAssignment
|
||||
pattern: RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: AssignedVariablePattern
|
||||
name: a
|
||||
element: self::@function::f::@parameter::a
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
equals: =
|
||||
expression: SimpleIdentifier
|
||||
token: x
|
||||
staticElement: self::@function::f::@parameter::x
|
||||
staticType: ({int foo})
|
||||
staticType: ({int foo})
|
||||
''');
|
||||
}
|
||||
|
||||
test_container_recordPattern_positional() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f((int,) x, num a) {
|
||||
(a,) = x;
|
||||
}
|
||||
''');
|
||||
final node = findNode.singlePatternAssignment;
|
||||
assertResolvedNodeText(node, r'''
|
||||
PatternAssignment
|
||||
pattern: RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: AssignedVariablePattern
|
||||
name: a
|
||||
element: self::@function::f::@parameter::a
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
equals: =
|
||||
expression: SimpleIdentifier
|
||||
token: x
|
||||
staticElement: self::@function::f::@parameter::x
|
||||
staticType: (int)
|
||||
staticType: (int)
|
||||
''');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
''');
|
||||
final node = findNode.simple('a;');
|
||||
assertResolvedNodeText(node, r'''
|
||||
SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
}
|
|
@ -67,6 +67,7 @@ import 'object_pattern_test.dart' as object_pattern;
|
|||
import 'optional_const_test.dart' as optional_const;
|
||||
import 'parenthesized_pattern_test.dart' as parenthesized_pattern;
|
||||
import 'part_test.dart' as part_;
|
||||
import 'pattern_assignment_test.dart' as pattern_assignment;
|
||||
import 'pattern_variable_declaration_statement_test.dart'
|
||||
as pattern_variable_declaration_statement;
|
||||
import 'postfix_expression_test.dart' as postfix_expression;
|
||||
|
@ -153,6 +154,7 @@ main() {
|
|||
optional_const.main();
|
||||
parenthesized_pattern.main();
|
||||
part_.main();
|
||||
pattern_assignment.main();
|
||||
pattern_variable_declaration_statement.main();
|
||||
postfix_expression.main();
|
||||
postfix_pattern.main();
|
||||
|
|
|
@ -17,7 +17,17 @@ main() {
|
|||
|
||||
@reflectiveTest
|
||||
class DeadCodeTest extends PubPackageResolutionTest
|
||||
with DeadCodeTestCases, DeadCodeTestCases_Language212 {}
|
||||
with DeadCodeTestCases, DeadCodeTestCases_Language212 {
|
||||
test_ifElement_patternAssignment() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(int a) {
|
||||
[if (false) (a) = 0];
|
||||
}
|
||||
''', [
|
||||
error(HintCode.DEAD_CODE, 30, 7),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class DeadCodeTest_Language218 extends PubPackageResolutionTest
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// 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/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(PatternAssignmentNotLocalVariableTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class PatternAssignmentNotLocalVariableTest extends PubPackageResolutionTest {
|
||||
test_class() async {
|
||||
await assertErrorsInCode('''
|
||||
void f() {
|
||||
(int) = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE, 14, 3),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_field() async {
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
var x = 0;
|
||||
|
||||
void f() {
|
||||
(x) = 0;
|
||||
}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE, 42, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_typeParameter() async {
|
||||
await assertErrorsInCode('''
|
||||
class A<T> {
|
||||
void f() {
|
||||
(T) = 0;
|
||||
}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE, 31, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_dynamic() async {
|
||||
await assertErrorsInCode('''
|
||||
void f() {
|
||||
(dynamic) = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE, 14, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_function() async {
|
||||
await assertErrorsInCode('''
|
||||
void f() {
|
||||
(f) = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE, 14, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_topLevelVariable() async {
|
||||
await assertErrorsInCode('''
|
||||
var x = 0;
|
||||
|
||||
void f() {
|
||||
(x) = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE, 26, 1),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -60,6 +60,17 @@ void f(Object x) {
|
|||
]);
|
||||
}
|
||||
|
||||
test_patternAssignment_assignedVariablePattern() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(int a) {
|
||||
(a) = 1.2;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.PATTERN_TYPE_MISMATCH_IN_IRREFUTABLE_CONTEXT,
|
||||
19, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_recordPattern_notRecord() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(Object x) {
|
||||
|
|
|
@ -607,6 +607,8 @@ import 'packed_annotation_alignment_test.dart' as packed_annotation_alignment;
|
|||
import 'packed_annotation_test.dart' as packed_annotation;
|
||||
import 'part_of_different_library_test.dart' as part_of_different_library;
|
||||
import 'part_of_non_part_test.dart' as part_of_non_part;
|
||||
import 'pattern_assignment_not_local_variable_test.dart'
|
||||
as pattern_assignment_not_local_variable;
|
||||
import 'pattern_type_mismatch_in_irrefutable_context_test.dart'
|
||||
as pattern_type_mismatch_in_irrefutable_context;
|
||||
import 'positional_super_formal_parameter_with_positional_argument_test.dart'
|
||||
|
@ -1224,6 +1226,7 @@ main() {
|
|||
packed_annotation_alignment.main();
|
||||
part_of_different_library.main();
|
||||
part_of_non_part.main();
|
||||
pattern_assignment_not_local_variable.main();
|
||||
pattern_type_mismatch_in_irrefutable_context.main();
|
||||
positional_super_formal_parameter_with_positional_argument.main();
|
||||
prefix_collides_with_top_level_member.main();
|
||||
|
|
|
@ -18,6 +18,16 @@ main() {
|
|||
@reflectiveTest
|
||||
class UndefinedIdentifierTest extends PubPackageResolutionTest
|
||||
with UndefinedIdentifierTestCases {
|
||||
test_assignedPatternVariable() async {
|
||||
await assertErrorsInCode('''
|
||||
void f() {
|
||||
(x) = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 14, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_get_from_external_variable_final_valid() async {
|
||||
await assertNoErrorsInCode('''
|
||||
external final int x;
|
||||
|
|
|
@ -1070,6 +1070,15 @@ class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPatternAssignment(PatternAssignment node) {
|
||||
_writeln('PatternAssignment');
|
||||
_withIndent(() {
|
||||
_writeNamedChildEntities(node);
|
||||
_writeType('staticType', node.staticType);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPatternVariableDeclaration(PatternVariableDeclaration node) {
|
||||
_writeln('PatternVariableDeclaration');
|
||||
|
|
Loading…
Reference in a new issue