mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 15:21:54 +00:00
Resolve RecordPattern(s).
Change-Id: I229efb591cbb2d6cfe77b38155526f881fee7dbe Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264891 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
b03b9c3712
commit
6c60f506c8
|
@ -10543,7 +10543,7 @@ class RecordPatternFieldNameImpl extends AstNodeImpl
|
|||
/// '(' [RecordPatternField] (',' [RecordPatternField])* ')'
|
||||
@experimental
|
||||
class RecordPatternImpl extends DartPatternImpl implements RecordPattern {
|
||||
final NodeListImpl<RecordPatternField> _fields = NodeListImpl._();
|
||||
final NodeListImpl<RecordPatternFieldImpl> _fields = NodeListImpl._();
|
||||
|
||||
@override
|
||||
final Token leftParenthesis;
|
||||
|
@ -10553,7 +10553,7 @@ class RecordPatternImpl extends DartPatternImpl implements RecordPattern {
|
|||
|
||||
RecordPatternImpl({
|
||||
required this.leftParenthesis,
|
||||
required List<RecordPatternField> fields,
|
||||
required List<RecordPatternFieldImpl> fields,
|
||||
required this.rightParenthesis,
|
||||
}) {
|
||||
_fields._initialize(this, fields);
|
||||
|
@ -10566,7 +10566,7 @@ class RecordPatternImpl extends DartPatternImpl implements RecordPattern {
|
|||
Token get endToken => rightParenthesis;
|
||||
|
||||
@override
|
||||
NodeList<RecordPatternField> get fields => _fields;
|
||||
NodeList<RecordPatternFieldImpl> get fields => _fields;
|
||||
|
||||
@override
|
||||
ChildEntities get _childEntities => super._childEntities
|
||||
|
@ -10587,7 +10587,12 @@ class RecordPatternImpl extends DartPatternImpl implements RecordPattern {
|
|||
DartType matchedType,
|
||||
Map<PromotableElement, VariableTypeInfo<AstNode, DartType>> typeInfos,
|
||||
MatchContext<AstNode, Expression> context) {
|
||||
// TODO(scheglov) https://github.com/dart-lang/sdk/issues/50066
|
||||
resolverVisitor.recordPatternResolver.resolve(
|
||||
node: this,
|
||||
matchedType: matchedType,
|
||||
typeInfos: typeInfos,
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
// 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:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart';
|
||||
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/element/extensions.dart';
|
||||
import 'package:analyzer/src/dart/element/type_provider.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart';
|
||||
|
||||
class RecordPatternResolver {
|
||||
final ResolverVisitor resolverVisitor;
|
||||
|
||||
int _positionalFieldIndex = 0;
|
||||
|
||||
RecordPatternResolver(this.resolverVisitor);
|
||||
|
||||
TypeProviderImpl get _typeProvider => resolverVisitor.typeProvider;
|
||||
|
||||
void resolve({
|
||||
required RecordPatternImpl node,
|
||||
required DartType matchedType,
|
||||
required Map<PromotableElement, VariableTypeInfo<AstNode, DartType>>
|
||||
typeInfos,
|
||||
required MatchContext<AstNode, Expression> context,
|
||||
}) {
|
||||
_positionalFieldIndex = 0;
|
||||
for (var field in node.fields) {
|
||||
var fieldType = _resolveFieldType(matchedType, field);
|
||||
field.pattern
|
||||
.resolvePattern(resolverVisitor, fieldType, typeInfos, context);
|
||||
}
|
||||
}
|
||||
|
||||
DartType _resolveFieldType(
|
||||
DartType matchedType,
|
||||
RecordPatternFieldImpl field,
|
||||
) {
|
||||
if (matchedType is RecordType) {
|
||||
var fieldNameNode = field.fieldName;
|
||||
if (fieldNameNode != null) {
|
||||
var nameToken = fieldNameNode.name;
|
||||
nameToken ??= field.pattern.variablePattern?.name;
|
||||
if (nameToken == null) {
|
||||
resolverVisitor.errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.MISSING_EXTRACTOR_PATTERN_GETTER_NAME,
|
||||
field,
|
||||
);
|
||||
return _typeProvider.dynamicType;
|
||||
}
|
||||
|
||||
var fieldName = nameToken.lexeme;
|
||||
var recordField = matchedType.fieldByName(fieldName);
|
||||
if (recordField != null) {
|
||||
return recordField.type;
|
||||
}
|
||||
} else {
|
||||
if (_positionalFieldIndex < matchedType.positionalFields.length) {
|
||||
return matchedType.positionalFields[_positionalFieldIndex++].type;
|
||||
}
|
||||
}
|
||||
} else if (matchedType.isDynamic) {
|
||||
return _typeProvider.dynamicType;
|
||||
}
|
||||
|
||||
return resolverVisitor.typeSystem.objectQuestion;
|
||||
}
|
||||
}
|
|
@ -4634,11 +4634,14 @@ class AstBuilder extends StackListener {
|
|||
void handleRecordPattern(Token token, int count) {
|
||||
debugEvent("RecordPattern");
|
||||
|
||||
var fields = popTypedList2<RecordPatternField>(count);
|
||||
push(RecordPatternImpl(
|
||||
var fields = popTypedList2<RecordPatternFieldImpl>(count);
|
||||
push(
|
||||
RecordPatternImpl(
|
||||
leftParenthesis: token,
|
||||
fields: fields,
|
||||
rightParenthesis: token.endGroup!));
|
||||
rightParenthesis: token.endGroup!,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -57,6 +57,7 @@ import 'package:analyzer/src/dart/resolver/prefix_expression_resolver.dart';
|
|||
import 'package:analyzer/src/dart/resolver/prefixed_identifier_resolver.dart';
|
||||
import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
|
||||
import 'package:analyzer/src/dart/resolver/record_literal_resolver.dart';
|
||||
import 'package:analyzer/src/dart/resolver/record_pattern_resolver.dart';
|
||||
import 'package:analyzer/src/dart/resolver/scope.dart';
|
||||
import 'package:analyzer/src/dart/resolver/shared_type_analyzer.dart';
|
||||
import 'package:analyzer/src/dart/resolver/simple_identifier_resolver.dart';
|
||||
|
@ -281,6 +282,9 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
late final ExtractorPatternResolver extractorPatternResolver =
|
||||
ExtractorPatternResolver(this);
|
||||
|
||||
late final RecordPatternResolver recordPatternResolver =
|
||||
RecordPatternResolver(this);
|
||||
|
||||
final bool genericMetadataIsEnabled;
|
||||
|
||||
/// Stack for obtaining rewritten expressions. Prior to visiting an
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// 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';
|
||||
|
@ -14,7 +15,7 @@ main() {
|
|||
|
||||
@reflectiveTest
|
||||
class RecordPatternResolutionTest extends PatternsResolutionTest {
|
||||
test_fields_empty() async {
|
||||
test_dynamicType_empty() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
switch (x) {
|
||||
|
@ -24,42 +25,171 @@ void f(x) {
|
|||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertParsedNodeText(node, r'''
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_fields_pair() async {
|
||||
test_dynamicType_named_variable_untyped() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
switch (x) {
|
||||
case (1, 2):
|
||||
case (foo: var y):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertParsedNodeText(node, r'''
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: ConstantPattern
|
||||
expression: IntegerLiteral
|
||||
literal: 1
|
||||
RecordPatternField
|
||||
pattern: ConstantPattern
|
||||
expression: IntegerLiteral
|
||||
literal: 2
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: y
|
||||
declaredElement: hasImplicitType y@46
|
||||
type: dynamic
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_fields_singleton() async {
|
||||
test_dynamicType_positional_variable_untyped() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
switch (x) {
|
||||
case (var y):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
ParenthesizedPattern
|
||||
leftParenthesis: (
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: y
|
||||
declaredElement: hasImplicitType y@41
|
||||
type: dynamic
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_empty() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case ():
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_named_constant() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case (foo: 0):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: ConstantPattern
|
||||
expression: IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_named_variable_typed() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case (foo: int y):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: int
|
||||
staticElement: dart:core::@class::int
|
||||
staticType: null
|
||||
type: int
|
||||
name: y
|
||||
declaredElement: y@54
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_named_variable_untyped() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case (foo: var y):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: y
|
||||
declaredElement: hasImplicitType y@54
|
||||
type: Object?
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_positional_constant() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case (0,):
|
||||
break;
|
||||
|
@ -67,7 +197,7 @@ void f(x) {
|
|||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertParsedNodeText(node, r'''
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
|
@ -75,6 +205,319 @@ RecordPattern
|
|||
pattern: ConstantPattern
|
||||
expression: IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_positional_variable_typed() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case (int y,):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: int
|
||||
staticElement: dart:core::@class::int
|
||||
staticType: null
|
||||
type: int
|
||||
name: y
|
||||
declaredElement: y@49
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_interfaceType_positional_variable_untyped() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case (var y,):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: y
|
||||
declaredElement: hasImplicitType y@49
|
||||
type: Object?
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_empty() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(() x) {
|
||||
switch (x) {
|
||||
case ():
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_mixed() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f((int, double, {String foo}) x) {
|
||||
switch (x) {
|
||||
case (var a, foo: var b, var c):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: a
|
||||
declaredElement: hasImplicitType a@69
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: b
|
||||
declaredElement: hasImplicitType b@81
|
||||
type: String
|
||||
fieldElement: <null>
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: c
|
||||
declaredElement: hasImplicitType c@88
|
||||
type: double
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_named_hasName_unresolved() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(({int foo}) x) {
|
||||
switch (x) {
|
||||
case (bar: var a):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: bar
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: a
|
||||
declaredElement: hasImplicitType a@58
|
||||
type: Object?
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_named_hasName_variable() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(({int foo}) x) {
|
||||
switch (x) {
|
||||
case (foo: var y):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
name: foo
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: y
|
||||
declaredElement: hasImplicitType y@58
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_named_noName_constant() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(({int foo}) x) {
|
||||
switch (x) {
|
||||
case (: 0):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.MISSING_EXTRACTOR_PATTERN_GETTER_NAME, 49, 3),
|
||||
]);
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
colon: :
|
||||
pattern: ConstantPattern
|
||||
expression: IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_named_noName_variable() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(({int foo}) x) {
|
||||
switch (x) {
|
||||
case (: var foo):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
colon: :
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: foo
|
||||
declaredElement: hasImplicitType foo@55
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_named_noName_variable_nullCheck() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(({int? foo}) x) {
|
||||
switch (x) {
|
||||
case (: var foo?):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
fieldName: RecordPatternFieldName
|
||||
colon: :
|
||||
pattern: PostfixPattern
|
||||
operand: VariablePattern
|
||||
keyword: var
|
||||
name: foo
|
||||
declaredElement: hasImplicitType foo@56
|
||||
type: int
|
||||
operator: ?
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_positional_tooMany() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f((int,) x) {
|
||||
switch (x) {
|
||||
case (var a, var b):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: a
|
||||
declaredElement: hasImplicitType a@48
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: b
|
||||
declaredElement: hasImplicitType b@55
|
||||
type: Object?
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
||||
test_recordType_positional_variable() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f((int,) x) {
|
||||
switch (x) {
|
||||
case (var a,):
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
final node = findNode.switchPatternCase('case').pattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
RecordPattern
|
||||
leftParenthesis: (
|
||||
fields
|
||||
RecordPatternField
|
||||
pattern: VariablePattern
|
||||
keyword: var
|
||||
name: a
|
||||
declaredElement: hasImplicitType a@48
|
||||
type: int
|
||||
fieldElement: <null>
|
||||
rightParenthesis: )
|
||||
''');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue