mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:01:42 +00:00
Parse type variables of local functions before return type.
R=danrubel@google.com Review-Url: https://codereview.chromium.org/2985673002 .
This commit is contained in:
parent
d109fe7f1a
commit
98422979ac
|
@ -1533,12 +1533,12 @@ class AstBuilder extends ScopeListener {
|
|||
pop(); // constructor initializers
|
||||
pop(); // separator before constructor initializers
|
||||
FormalParameterList parameters = pop();
|
||||
TypeParameterList typeParameters = pop();
|
||||
FunctionExpression functionExpression =
|
||||
ast.functionExpression(typeParameters, parameters, body);
|
||||
SimpleIdentifier name = pop();
|
||||
TypeAnnotation returnType = pop();
|
||||
pop(); // modifiers
|
||||
TypeParameterList typeParameters = pop();
|
||||
FunctionExpression functionExpression =
|
||||
ast.functionExpression(typeParameters, parameters, body);
|
||||
push(ast.functionDeclarationStatement(ast.functionDeclaration(
|
||||
null, null, null, returnType, null, name, functionExpression)));
|
||||
}
|
||||
|
|
|
@ -511,11 +511,11 @@ class NodeListener extends ElementListener {
|
|||
AsyncModifier asyncModifier = popNode();
|
||||
NodeList initializers = popNode();
|
||||
NodeList formals = popNode();
|
||||
NodeList typeVariables = popNode();
|
||||
// The name can be an identifier or a send in case of named constructors.
|
||||
Expression name = popNode();
|
||||
TypeAnnotation type = popNode();
|
||||
Modifiers modifiers = popNode();
|
||||
NodeList typeVariables = popNode();
|
||||
pushNode(new FunctionDeclaration(new FunctionExpression(name, typeVariables,
|
||||
formals, body, type, modifiers, initializers, null, asyncModifier)));
|
||||
}
|
||||
|
|
|
@ -2492,11 +2492,6 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
|||
exitLocalScope();
|
||||
}
|
||||
FormalParameters formals = pop();
|
||||
List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop());
|
||||
FunctionNode function = formals.addToFunction(new FunctionNode(body,
|
||||
typeParameters: typeParameters, asyncMarker: asyncModifier)
|
||||
..fileOffset = formals.charOffset
|
||||
..fileEndOffset = token.charOffset);
|
||||
exitLocalScope();
|
||||
var declaration = pop();
|
||||
var returnType = pop();
|
||||
|
@ -2504,6 +2499,11 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
|
|||
returnType ??= const DynamicType();
|
||||
pop(); // Modifiers.
|
||||
exitFunction();
|
||||
List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop());
|
||||
FunctionNode function = formals.addToFunction(new FunctionNode(body,
|
||||
typeParameters: typeParameters, asyncMarker: asyncModifier)
|
||||
..fileOffset = formals.charOffset
|
||||
..fileEndOffset = token.charOffset);
|
||||
if (declaration is FunctionDeclaration) {
|
||||
KernelFunctionDeclaration.setHasImplicitReturnType(
|
||||
declaration, hasImplicitReturnType);
|
||||
|
|
|
@ -281,7 +281,8 @@ class Listener {
|
|||
logEvent("NamedFunctionExpression");
|
||||
}
|
||||
|
||||
/// Handle the beginning of a local function declaration.
|
||||
/// Handle the beginning of a local function declaration. Substructures:
|
||||
/// - Type variables
|
||||
void beginLocalFunctionDeclaration(Token token) {}
|
||||
|
||||
/// A function declaration.
|
||||
|
|
|
@ -1176,14 +1176,8 @@ class Parser {
|
|||
}
|
||||
|
||||
if (looksLikeType && token.isIdentifier) {
|
||||
// If the identifier token has a type substitution comment /*=T*/,
|
||||
// then the set of tokens type tokens should be replaced with the
|
||||
// tokens parsed from the comment.
|
||||
Token afterId = token.next;
|
||||
|
||||
begin =
|
||||
listener.replaceTokenWithGenericCommentTypeAssign(begin, token);
|
||||
|
||||
int afterIdKind = afterId.kind;
|
||||
if (looksLikeVariableDeclarationEnd(afterIdKind)) {
|
||||
// We are looking at `type identifier` followed by
|
||||
|
@ -1197,18 +1191,44 @@ class Parser {
|
|||
if (looksLikeFunctionBody(closeBraceTokenFor(afterId).next)) {
|
||||
// We are looking at `type identifier '(' ... ')'` followed
|
||||
// `( '{' | '=>' | 'async' | 'sync' )`.
|
||||
return parseLocalFunctionDeclaration(begin);
|
||||
|
||||
// Although it looks like there are no type variables here, they
|
||||
// may get injected from a comment.
|
||||
Token formals = parseTypeVariablesOpt(afterId);
|
||||
|
||||
listener.beginLocalFunctionDeclaration(begin);
|
||||
listener.handleModifiers(0);
|
||||
if (voidToken != null) {
|
||||
listener.handleVoidKeyword(voidToken);
|
||||
} else {
|
||||
commitType();
|
||||
}
|
||||
listener.beginFunctionName(token);
|
||||
token = parseIdentifier(
|
||||
token, IdentifierContext.localFunctionDeclaration);
|
||||
listener.endFunctionName(begin, token);
|
||||
return parseLocalFunctionDeclarationFromFormals(formals);
|
||||
}
|
||||
} else if (identical(afterIdKind, LT_TOKEN)) {
|
||||
// We are looking at `type identifier '<'`.
|
||||
Token afterTypeVariables = closeBraceTokenFor(afterId)?.next;
|
||||
if (afterTypeVariables != null &&
|
||||
optional("(", afterTypeVariables)) {
|
||||
if (looksLikeFunctionBody(
|
||||
closeBraceTokenFor(afterTypeVariables).next)) {
|
||||
Token formals = closeBraceTokenFor(afterId)?.next;
|
||||
if (formals != null && optional("(", formals)) {
|
||||
if (looksLikeFunctionBody(closeBraceTokenFor(formals).next)) {
|
||||
// We are looking at "type identifier '<' ... '>' '(' ... ')'"
|
||||
// followed by '{', '=>', 'async', or 'sync'.
|
||||
return parseLocalFunctionDeclaration(begin);
|
||||
parseTypeVariablesOpt(afterId);
|
||||
listener.beginLocalFunctionDeclaration(begin);
|
||||
listener.handleModifiers(0);
|
||||
if (voidToken != null) {
|
||||
listener.handleVoidKeyword(voidToken);
|
||||
} else {
|
||||
commitType();
|
||||
}
|
||||
listener.beginFunctionName(token);
|
||||
token = parseIdentifier(
|
||||
token, IdentifierContext.localFunctionDeclaration);
|
||||
listener.endFunctionName(begin, token);
|
||||
return parseLocalFunctionDeclarationFromFormals(formals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1219,7 +1239,21 @@ class Parser {
|
|||
return parseLabeledStatement(token);
|
||||
} else if (optional('(', token.next)) {
|
||||
if (looksLikeFunctionBody(closeBraceTokenFor(token.next).next)) {
|
||||
return parseLocalFunctionDeclaration(token);
|
||||
// We are looking at `identifier '(' ... ')'` followed by `'{'`,
|
||||
// `'=>'`, `'async'`, or `'sync'`.
|
||||
|
||||
// Although it looks like there are no type variables here, they
|
||||
// may get injected from a comment.
|
||||
Token formals = parseTypeVariablesOpt(token.next);
|
||||
|
||||
listener.beginLocalFunctionDeclaration(token);
|
||||
listener.handleModifiers(0);
|
||||
listener.handleNoType(token);
|
||||
listener.beginFunctionName(token);
|
||||
token = parseIdentifier(
|
||||
token, IdentifierContext.localFunctionDeclaration);
|
||||
listener.endFunctionName(begin, token);
|
||||
return parseLocalFunctionDeclarationFromFormals(formals);
|
||||
}
|
||||
} else if (optional('<', token.next)) {
|
||||
Token afterTypeVariables = closeBraceTokenFor(token.next)?.next;
|
||||
|
@ -1227,7 +1261,18 @@ class Parser {
|
|||
optional("(", afterTypeVariables)) {
|
||||
if (looksLikeFunctionBody(
|
||||
closeBraceTokenFor(afterTypeVariables).next)) {
|
||||
return parseLocalFunctionDeclaration(token);
|
||||
// We are looking at `identifier '<' ... '>' '(' ... ')'`
|
||||
// followed by `'{'`, `'=>'`, `'async'`, or `'sync'`.
|
||||
parseTypeVariablesOpt(token.next);
|
||||
listener.beginLocalFunctionDeclaration(token);
|
||||
listener.handleModifiers(0);
|
||||
listener.handleNoType(token);
|
||||
listener.beginFunctionName(token);
|
||||
token = parseIdentifier(
|
||||
token, IdentifierContext.localFunctionDeclaration);
|
||||
listener.endFunctionName(begin, token);
|
||||
return parseLocalFunctionDeclarationFromFormals(
|
||||
afterTypeVariables);
|
||||
}
|
||||
}
|
||||
// Fall through to expression statement.
|
||||
|
@ -2335,16 +2380,17 @@ class Parser {
|
|||
return isBlock ? token.next : token;
|
||||
}
|
||||
|
||||
Token parseLocalFunctionDeclaration(Token token) {
|
||||
listener.beginLocalFunctionDeclaration(token);
|
||||
Token beginToken = token;
|
||||
token = parseModifiers(token, MemberKind.Local);
|
||||
listener.beginFunctionName(token);
|
||||
token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
|
||||
token = parseQualifiedRestOpt(
|
||||
token, IdentifierContext.localFunctionDeclarationContinuation);
|
||||
listener.endFunctionName(beginToken, token);
|
||||
token = parseTypeVariablesOpt(token);
|
||||
/// Parses the rest of a local function declaration starting from formal
|
||||
/// parameters.
|
||||
///
|
||||
/// Precondition: the parser has previously generated these events:
|
||||
///
|
||||
/// - Type variables.
|
||||
/// - beginLocalFunctionDeclaration.
|
||||
/// - Modifiers.
|
||||
/// - Return type.
|
||||
/// - Function name.
|
||||
Token parseLocalFunctionDeclarationFromFormals(Token token) {
|
||||
token = parseFormalParametersOpt(token, MemberKind.Local);
|
||||
token = parseInitializersOpt(token);
|
||||
AsyncModifier savedAsyncModifier = asyncState;
|
||||
|
|
Loading…
Reference in a new issue