Add support to AstBuilder to build record type annotations

Change-Id: I621c15077a990b8f631d7861c7d4e54718809cdf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255824
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Brian Wilkerson 2022-08-19 20:55:55 +00:00 committed by Commit Bot
parent e04a9e80ce
commit 04535fa727
3 changed files with 212 additions and 21 deletions

View file

@ -2436,37 +2436,74 @@ class AstBuilder extends StackListener {
@override
void endRecordType(Token leftBracket, Token? questionMark, int count) {
debugEvent("RecordType");
_reportFeatureNotEnabled(
feature: ExperimentalFeatures.records,
startToken: leftBracket,
);
if (!enableNonNullable) {
reportErrorIfNullableType(questionMark);
if (!enableRecords) {
_reportFeatureNotEnabled(
feature: ExperimentalFeatures.records,
startToken: leftBracket,
);
}
// TODO: Implement record type. This currently pushes a dummy type.
push(
ast.namedType(
name: ast.simpleIdentifier(leftBracket),
typeArguments: null,
question: questionMark,
),
);
RecordTypeAnnotationNamedFieldsImpl? namedFields;
var elements = popTypedList<Object>(count) ?? const [];
var last = elements.lastOrNull;
if (last is RecordTypeAnnotationNamedFieldsImpl) {
elements.removeLast();
namedFields = last;
}
var positionalFields = <RecordTypeAnnotationPositionalField>[];
for (var elem in elements) {
positionalFields.add(elem as RecordTypeAnnotationPositionalField);
}
push(RecordTypeAnnotationImpl(
leftParenthesis: leftBracket,
positionalFields: positionalFields,
namedFields: namedFields,
rightParenthesis: leftBracket.endGroup!,
question: questionMark,
));
}
@override
void endRecordTypeEntry() {
// TODO: Implement record type entry.
pop(); // Identifier.
pop(); // Type.
pop(); // Metadata.
debugEvent("RecordTypeEntry");
var name = pop() as SimpleIdentifier?;
var type = pop() as TypeAnnotationImpl;
var metadata = pop() as List<Annotation>?;
var comma = (name ?? type).endToken.next;
if (comma?.type != TokenType.COMMA) {
comma = null;
}
push(RecordTypeAnnotationPositionalFieldImpl(
metadata: metadata,
type: type,
name: name?.token,
comma: comma,
));
}
@override
void endRecordTypeNamedFields(int count, Token leftBracket) {
// TODO: Implement record type named fields.
debugEvent("RecordTypeNamedFields");
var elements =
popTypedList<RecordTypeAnnotationPositionalFieldImpl>(count) ??
const [];
var fields = <RecordTypeAnnotationNamedField>[];
for (var elem in elements) {
fields.add(RecordTypeAnnotationNamedFieldImpl(
comma: elem.comma,
metadata: elem.metadata,
type: elem.type,
name: elem.name!,
));
}
push(RecordTypeAnnotationNamedFieldsImpl(
leftBracket: leftBracket,
fields: fields,
rightBracket: leftBracket.endGroup!,
));
}
@override

View file

@ -547,6 +547,124 @@ RecordLiteral
''');
}
void test_recordTypeAnnotation_mixed() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool, {int a, bool b}) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: SimpleIdentifier
token: int
comma: ,
RecordTypeAnnotationPositionalField
type: NamedType
name: SimpleIdentifier
token: bool
comma: ,
namedFields: RecordTypeAnnotationNamedFields
leftBracket: {
fields
RecordTypeAnnotationNamedField
type: NamedType
name: SimpleIdentifier
token: int
name: a
comma: ,
RecordTypeAnnotationNamedField
type: NamedType
name: SimpleIdentifier
token: bool
name: b
rightBracket: }
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_named() {
var parseResult = parseStringWithErrors(r'''
void f(({int a, bool b}) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('({int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
namedFields: RecordTypeAnnotationNamedFields
leftBracket: {
fields
RecordTypeAnnotationNamedField
type: NamedType
name: SimpleIdentifier
token: int
name: a
comma: ,
RecordTypeAnnotationNamedField
type: NamedType
name: SimpleIdentifier
token: bool
name: b
rightBracket: }
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_nullable() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool)? r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: SimpleIdentifier
token: int
comma: ,
RecordTypeAnnotationPositionalField
type: NamedType
name: SimpleIdentifier
token: bool
rightParenthesis: )
question: ?
''');
}
void test_recordTypeAnnotation_positional() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: SimpleIdentifier
token: int
comma: ,
RecordTypeAnnotationPositionalField
type: NamedType
name: SimpleIdentifier
token: bool
rightParenthesis: )
''');
}
void test_superFormalParameter() {
var parseResult = parseStringWithErrors(r'''
class A {

View file

@ -970,6 +970,42 @@ class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
});
}
@override
void visitRecordTypeAnnotation(RecordTypeAnnotation node) {
_writeln('RecordTypeAnnotation');
_withIndent(() {
_writeNamedChildEntities(node);
_writeType('staticType', node.type);
});
}
@override
void visitRecordTypeAnnotationNamedField(
RecordTypeAnnotationNamedField node) {
_writeln('RecordTypeAnnotationNamedField');
_withIndent(() {
_writeNamedChildEntities(node);
});
}
@override
void visitRecordTypeAnnotationNamedFields(
RecordTypeAnnotationNamedFields node) {
_writeln('RecordTypeAnnotationNamedFields');
_withIndent(() {
_writeNamedChildEntities(node);
});
}
@override
void visitRecordTypeAnnotationPositionalField(
RecordTypeAnnotationPositionalField node) {
_writeln('RecordTypeAnnotationPositionalField');
_withIndent(() {
_writeNamedChildEntities(node);
});
}
@override
void visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node,