Index: pkg/front_end/lib/src/fasta/parser/parser.dart |
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart |
index c2c49517661540064ba3c8df8283d1b95682ef98..695981294cb8538d0d51dcc91d8163122f69bebc 100644 |
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart |
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart |
@@ -1203,11 +1203,7 @@ class Parser { |
} else { |
commitType(); |
} |
- listener.beginFunctionName(token); |
- token = parseIdentifier( |
- token, IdentifierContext.localFunctionDeclaration); |
- listener.endFunctionName(begin, token); |
- return parseLocalFunctionDeclarationFromFormals(formals); |
+ return parseLocalFunctionDeclarationRest(begin, token, formals); |
} |
} else if (identical(afterIdKind, LT_TOKEN)) { |
// We are looking at `type identifier '<'`. |
@@ -1224,11 +1220,7 @@ class Parser { |
} else { |
commitType(); |
} |
- listener.beginFunctionName(token); |
- token = parseIdentifier( |
- token, IdentifierContext.localFunctionDeclaration); |
- listener.endFunctionName(begin, token); |
- return parseLocalFunctionDeclarationFromFormals(formals); |
+ return parseLocalFunctionDeclarationRest(begin, token, formals); |
} |
} |
} |
@@ -1249,11 +1241,7 @@ class Parser { |
listener.beginLocalFunctionDeclaration(token); |
listener.handleModifiers(0); |
listener.handleNoType(token); |
- listener.beginFunctionName(token); |
- token = parseIdentifier( |
- token, IdentifierContext.localFunctionDeclaration); |
- listener.endFunctionName(begin, token); |
- return parseLocalFunctionDeclarationFromFormals(formals); |
+ return parseLocalFunctionDeclarationRest(begin, token, formals); |
} |
} else if (optional('<', token.next)) { |
Token afterTypeVariables = closeBraceTokenFor(token.next)?.next; |
@@ -1267,12 +1255,8 @@ class Parser { |
listener.beginLocalFunctionDeclaration(token); |
listener.handleModifiers(0); |
listener.handleNoType(token); |
- listener.beginFunctionName(token); |
- token = parseIdentifier( |
- token, IdentifierContext.localFunctionDeclaration); |
- listener.endFunctionName(begin, token); |
- return parseLocalFunctionDeclarationFromFormals( |
- afterTypeVariables); |
+ return parseLocalFunctionDeclarationRest( |
+ begin, token, afterTypeVariables); |
} |
} |
// Fall through to expression statement. |
@@ -2371,17 +2355,14 @@ class Parser { |
Token beginToken = token; |
listener.beginFunctionExpression(token); |
token = parseFormalParameters(token, MemberKind.Local); |
- AsyncModifier savedAsyncModifier = asyncState; |
- token = parseAsyncModifier(token); |
- bool isBlock = optional('{', token); |
- token = parseFunctionBody(token, true, false); |
- asyncState = savedAsyncModifier; |
+ token = parseAsyncOptBody(token, true, false); |
listener.endFunctionExpression(beginToken, token); |
- return isBlock ? token.next : token; |
+ return token; |
} |
- /// Parses the rest of a local function declaration starting from formal |
- /// parameters. |
+ /// Parses the rest of a local function declaration starting from its [name] |
+ /// but then skips any type parameters and continue parsing from [formals] |
+ /// (the formal parameters). |
/// |
/// Precondition: the parser has previously generated these events: |
/// |
@@ -2389,17 +2370,17 @@ class Parser { |
/// - beginLocalFunctionDeclaration. |
/// - Modifiers. |
/// - Return type. |
- /// - Function name. |
- Token parseLocalFunctionDeclarationFromFormals(Token token) { |
- token = parseFormalParametersOpt(token, MemberKind.Local); |
+ Token parseLocalFunctionDeclarationRest( |
+ Token begin, Token name, Token formals) { |
+ Token token = name; |
+ listener.beginFunctionName(token); |
+ token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration); |
+ listener.endFunctionName(begin, token); |
+ token = parseFormalParametersOpt(formals, MemberKind.Local); |
token = parseInitializersOpt(token); |
- AsyncModifier savedAsyncModifier = asyncState; |
- token = parseAsyncModifier(token); |
- token = parseFunctionBody(token, false, true); |
- asyncState = savedAsyncModifier; |
- token = token.next; |
+ token = parseAsyncOptBody(token, false, false); |
listener.endLocalFunctionDeclaration(token); |
- return token; |
+ return token.next; |
} |
/// Parses a named function expression which isn't legal syntax in Dart. |
@@ -2422,13 +2403,24 @@ class Parser { |
token = parseTypeVariablesOpt(token); |
token = parseFormalParameters(token, MemberKind.Local); |
listener.handleNoInitializers(); |
+ token = parseAsyncOptBody(token, true, false); |
+ listener.endNamedFunctionExpression(token); |
+ return token; |
+ } |
+ |
+ /// Parses a function body optionally preceded by an async modifier (see |
+ /// [parseAsyncModifier]). This method is used in both expression context |
+ /// (when [isExpression] is true) and statement context. In statement context |
+ /// (when [isExpression] is false), and if the function body is on the form |
+ /// `=> expression`, a trailing semicolon is required. |
+ /// |
+ /// It's an error if there's no function body unless [allowAbstract] is true. |
+ Token parseAsyncOptBody(Token token, bool isExpression, bool allowAbstract) { |
AsyncModifier savedAsyncModifier = asyncState; |
token = parseAsyncModifier(token); |
- bool isBlock = optional('{', token); |
- token = parseFunctionBody(token, true, false); |
+ token = parseFunctionBody(token, isExpression, allowAbstract); |
asyncState = savedAsyncModifier; |
- listener.endNamedFunctionExpression(token); |
- return isBlock ? token.next : token; |
+ return token; |
} |
Token parseConstructorReference(Token token) { |
@@ -2489,6 +2481,12 @@ class Parser { |
return token; |
} |
+ /// Parses a function body. This method is used in both expression context |
+ /// (when [isExpression] is true) and statement context. In statement context |
+ /// (when [isExpression] is false), and if the function body is on the form |
+ /// `=> expression`, a trailing semicolon is required. |
+ /// |
+ /// It's an error if there's no function body unless [allowAbstract] is true. |
Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
if (optional(';', token)) { |
if (!allowAbstract) { |
@@ -2537,7 +2535,7 @@ class Parser { |
} |
listener.endBlockFunctionBody(statementCount, begin, token); |
expect('}', token); |
- return token; |
+ return isExpression ? token.next : token; |
} |
Token skipAsyncModifier(Token token) { |