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 db73c6aa64daaf69b6c362e35da60e00caab4122..781525cd21443da07746b665d108377153df0924 100644 |
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart |
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart |
@@ -1158,82 +1158,86 @@ class Parser { |
/// after the type. Otherwise, it returns null. |
Token parseType(Token token, |
[TypeContinuation continuation = TypeContinuation.Required]) { |
- switch (continuation) { |
- case TypeContinuation.Typedef: |
- if (optional('=', peekAfterNominalType(token))) { |
- return null; // This isn't a type, it's a new-style typedef. |
+ Token begin = token; |
+ |
+ /// Call this function when it's known that [begin] is a type. This |
+ /// function will call the appropriate event methods on [listener] to |
+ /// handle the type. |
+ Token commitType() { |
ahe
2017/06/27 15:39:23
This code is copied from below and dartfmt'ed.
|
+ if (isGeneralizedFunctionType(token)) { |
+ // A function type without return type. |
+ // Push the non-existing return type first. The loop below will |
+ // generate the full type. |
+ listener.handleNoType(token); |
+ } else if (optional("void", token) && |
+ isGeneralizedFunctionType(token.next)) { |
+ listener.handleVoidKeyword(token); |
+ token = token.next; |
+ } else { |
+ IdentifierContext context = IdentifierContext.typeReference; |
+ if (token.isIdentifier && optional(".", token.next)) { |
+ context = IdentifierContext.prefixedTypeReference; |
} |
- continue optional; |
+ token = parseIdentifier(token, context); |
+ token = parseQualifiedRestOpt( |
+ token, IdentifierContext.typeReferenceContinuation); |
+ token = parseTypeArgumentsOpt(token); |
+ listener.handleType(begin, token); |
+ } |
+ |
+ { |
+ Token newBegin = |
+ listener.replaceTokenWithGenericCommentTypeAssign(begin, token); |
+ if (!identical(newBegin, begin)) { |
+ listener.discardTypeReplacedWithCommentTypeAssign(); |
+ return parseType(newBegin); |
+ } |
+ } |
+ |
+ // While we see a `Function(` treat the pushed type as return type. |
+ // For example: `int Function() Function(int) Function(String x)`. |
+ while (isGeneralizedFunctionType(token)) { |
+ token = parseFunctionType(token); |
+ } |
+ return token; |
+ } |
+ |
+ switch (continuation) { |
+ case TypeContinuation.Required: |
+ return commitType(); |
optional: |
case TypeContinuation.Optional: |
if (optional("void", token)) { |
if (isGeneralizedFunctionType(token.next)) { |
- // This is a type, parse it. |
- break; |
+ return commitType(); // This is a type, parse it. |
danrubel
2017/06/28 03:04:41
token and token.next are check here and then again
ahe
2017/06/28 08:02:57
Exactly, that happened in CL 2958073002 :-)
|
} else { |
listener.handleVoidKeyword(token); |
return token.next; |
} |
} else { |
if (isGeneralizedFunctionType(token)) { |
- // Function type without return type, parse it. |
- break; |
+ return commitType(); // Function type without return type, parse it. |
} |
token = listener.injectGenericCommentTypeAssign(token); |
Token peek = peekAfterIfType(token); |
if (peek != null && (peek.isIdentifier || optional('this', peek))) { |
// This is a type followed by an identifier, parse it. |
- break; |
+ return commitType(); |
} |
listener.handleNoType(token); |
return token; |
} |
break; |
- case TypeContinuation.Required: |
- break; |
- |
- default: |
- throw "Internal error: Unhandled continuation '$continuation'."; |
- } |
- Token begin = token; |
- if (isGeneralizedFunctionType(token)) { |
- // A function type without return type. |
- // Push the non-existing return type first. The loop below will |
- // generate the full type. |
- listener.handleNoType(token); |
- } else if (optional("void", token) && |
- isGeneralizedFunctionType(token.next)) { |
- listener.handleVoidKeyword(token); |
- token = token.next; |
- } else { |
- IdentifierContext context = IdentifierContext.typeReference; |
- if (token.isIdentifier && optional(".", token.next)) { |
- context = IdentifierContext.prefixedTypeReference; |
- } |
- token = parseIdentifier(token, context); |
- token = parseQualifiedRestOpt( |
- token, IdentifierContext.typeReferenceContinuation); |
- token = parseTypeArgumentsOpt(token); |
- listener.handleType(begin, token); |
- } |
- |
- { |
- Token newBegin = |
- listener.replaceTokenWithGenericCommentTypeAssign(begin, token); |
- if (!identical(newBegin, begin)) { |
- listener.discardTypeReplacedWithCommentTypeAssign(); |
- return parseType(newBegin); |
- } |
+ case TypeContinuation.Typedef: |
+ if (optional('=', peekAfterNominalType(token))) { |
+ return null; // This isn't a type, it's a new-style typedef. |
+ } |
+ continue optional; |
} |
- // While we see a `Function(` treat the pushed type as return type. |
- // For example: `int Function() Function(int) Function(String x)`. |
- while (isGeneralizedFunctionType(token)) { |
- token = parseFunctionType(token); |
- } |
- return token; |
+ throw "Internal error: Unhandled continuation '$continuation'."; |
} |
/// Parses a generalized function type. |