Add list literal spread collection parsing support
Change-Id: I96098e35baf44660b3f7a49952fde64def9998c7
Reviewed-on: https://dart-review.googlesource.com/c/89680
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 94a0fbe..2ffe897 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -46,7 +46,8 @@
messageStaticConstructor,
messageTypedefNotFunction,
templateDuplicateLabelInSwitchStatement,
- templateExpectedIdentifier;
+ templateExpectedIdentifier,
+ templateUnexpectedToken;
import 'package:front_end/src/fasta/quote.dart';
import 'package:front_end/src/fasta/scanner/token_constants.dart';
import 'package:front_end/src/fasta/source/stack_listener.dart'
@@ -270,6 +271,13 @@
scriptTag = ast.scriptTag(token);
}
+ @override
+ void handleSpreadExpression(Token spreadToken) {
+ // TODO(danrubel): generate new AST structure
+ handleRecoverableError(templateUnexpectedToken.withArguments(spreadToken),
+ spreadToken, spreadToken);
+ }
+
void handleStringJuxtaposition(int literalCount) {
debugEvent("StringJuxtaposition");
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b022212..44249b8 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -260,6 +260,30 @@
super.test_parseUnaryExpression_decrement_super_withComment();
}
+ void test_listLiteral_spread() {
+ // TODO(danrubel): Revise this test once AST supports new syntax
+ ListLiteral list = parseExpression('[1, ...[2]]', errors: [
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 3),
+ ]);
+ expect(list.elements, hasLength(2));
+ IntegerLiteral first = list.elements[0];
+ expect(first.value, 1);
+ ListLiteral second = list.elements[1];
+ expect(second.elements, hasLength(1));
+ }
+
+ void test_listLiteral_spreadQ() {
+ // TODO(danrubel): Revise this test once AST supports new syntax
+ ListLiteral list = parseExpression('[1, ...?[2]]', errors: [
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 4),
+ ]);
+ expect(list.elements, hasLength(2));
+ IntegerLiteral first = list.elements[0];
+ expect(first.value, 1);
+ ListLiteral second = list.elements[1];
+ expect(second.elements, hasLength(1));
+ }
+
void test_mapLiteral() {
MapLiteral map = parseExpression('{3: 6}', parseSetLiterals: true);
expect(map.constKeyword, isNull);
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index d023620..ae4004e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3519,6 +3519,16 @@
}
@override
+ void handleSpreadExpression(Token spreadToken) {
+ debugEvent("SpreadExpression");
+ // TODO(danrubel) implement spread expression support
+ handleRecoverableError(
+ fasta.templateUnexpectedToken.withArguments(spreadToken),
+ spreadToken,
+ spreadToken);
+ }
+
+ @override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
push(const FixedNullableList<UnresolvedType<KernelTypeBuilder>>()
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 51e3b9e..f447023 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -1308,6 +1308,11 @@
}
@override
+ void handleSpreadExpression(Token spreadToken) {
+ listener?.handleSpreadExpression(spreadToken);
+ }
+
+ @override
void handleStringJuxtaposition(int literalCount) {
listener?.handleStringJuxtaposition(literalCount);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index d681804..dc31098 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -1074,6 +1074,13 @@
logEvent("ConstExpression");
}
+ /// Called after the parser has parsed an expression that starts with
+ /// one of the spread collection tokens `...` or `...?`. Substructures:
+ /// - expression
+ void handleSpreadExpression(Token spreadToken) {
+ logEvent("SpreadExpression");
+ }
+
/// Handle the start of a function typed formal parameter. Substructures:
/// - type variables
void beginFunctionTypedFormalParameter(Token token) {}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index a3a59c2..6ab177a 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -4186,7 +4186,12 @@
token = next;
break;
}
- token = parseExpression(token);
+ if (optional('...', next) || optional('...?', next)) {
+ token = parseExpression(token.next);
+ listener.handleSpreadExpression(next);
+ } else {
+ token = parseExpression(token);
+ }
next = token.next;
++count;
if (!optional(',', next)) {
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index 5ba2c51..97611a1 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -376,6 +376,12 @@
doConstuctorInvocation(token, true);
}
+ @override
+ void handleSpreadExpression(Token spreadToken) {
+ // TODO(danrubel) add support for spread collections
+ // but for now this is ignored and an error reported in the body builder
+ }
+
void doConstuctorInvocation(Token token, bool isConst) {
state.pop(); // Arguments.
state.popPushNull(token.lexeme, token); // Constructor reference.