Improve literal function recovery
This fixes a crash when parsing literal functions
and improves recovery.
Change-Id: I22e7793d08e772bd186e1fb8fd01e09fa72ea13e
Reviewed-on: https://dart-review.googlesource.com/62380
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 19a76ce..18d1d5a 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -7037,6 +7037,25 @@
expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
}
+ void test_parseFunctionExpression_functionInPlaceOfTypeName() {
+ Expression expression = parseExpression('<test(' ', (){});>[0, 1, 2]',
+ codes: usingFastaParser
+ ? [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.UNEXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_FUNCTION_BODY,
+ ]
+ : [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
+ ]);
+ expect(expression, isNotNull);
+ }
+
void test_parseFunctionExpression_constAndTypeParameters2() {
FunctionExpression expression =
parseFunctionExpression('const <E>(E i) => i++');
diff --git a/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
index 6e680c9..107fd21 100644
--- a/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
@@ -63,14 +63,15 @@
@failingTest
void test_functionInPlaceOfTypeName() {
// https://github.com/dart-lang/sdk/issues/30370
- // TODO(danrubel): Fix this crash
+ // TODO(danrubel): Improve recovery. Currently, the fasta scanner
+ // does not associate `<` with `>` in this situation.
testRecovery('''
f() {
return <test('', (){});>[0, 1, 2];
}
''', [ParserErrorCode.UNEXPECTED_TOKEN], '''
f() {
- return <test>[0, 1, 2];
+ return _s_ < test('', (){}); _s_ > [0, 1, 2];
}
''');
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index d12753f..3b8f651 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -4079,21 +4079,17 @@
/// This is a suffix parser because it is assumed that type arguments have
/// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
Token parseLiteralFunctionSuffix(Token token) {
- Token next = token.next;
- assert(optional('(', next));
- Token closeBrace = next.endGroup;
- if (closeBrace != null) {
- Token nextToken = closeBrace.next;
- int kind = nextToken.kind;
- if (identical(kind, FUNCTION_TOKEN) ||
- identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
- (identical(kind, KEYWORD_TOKEN) &&
- (optional('async', nextToken) || optional('sync', nextToken)))) {
- return parseFunctionExpression(token);
- }
- // Fall through.
+ assert(optional('(', token.next));
+ // Scanner ensures `(` has matching `)`.
+ Token next = token.next.endGroup.next;
+ int kind = next.kind;
+ if (!identical(kind, FUNCTION_TOKEN) &&
+ !identical(kind, OPEN_CURLY_BRACKET_TOKEN) &&
+ (!identical(kind, KEYWORD_TOKEN) ||
+ !optional('async', next) && !optional('sync', next))) {
+ reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
}
- return reportUnexpectedToken(next);
+ return parseFunctionExpression(token);
}
/// genericListLiteral | genericMapLiteral | genericFunctionLiteral.