Index: pkg/analyzer/lib/src/generated/parser.dart |
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart |
index 9053bb0463cc7ff2c731d2a2f2c579b3cdac5eca..ba2d870e52e4e5603a1461e46d076f2a5f740385 100644 |
--- a/pkg/analyzer/lib/src/generated/parser.dart |
+++ b/pkg/analyzer/lib/src/generated/parser.dart |
@@ -351,7 +351,7 @@ class Parser { |
bool get hasReturnTypeInTypeAlias { |
// TODO(brianwilkerson) This is too expensive as implemented and needs to be |
// re-implemented or removed. |
- Token next = skipReturnType(_currentToken); |
+ Token next = skipTypeAnnotation(_currentToken); |
if (next == null) { |
return false; |
} |
@@ -449,10 +449,7 @@ class Parser { |
*/ |
bool isFunctionDeclaration() { |
Keyword keyword = _currentToken.keyword; |
- if (keyword == Keyword.VOID) { |
- return true; |
- } |
- Token afterReturnType = skipTypeName(_currentToken); |
+ Token afterReturnType = skipTypeWithoutFunction(_currentToken); |
if (afterReturnType != null && |
_tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) { |
afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType); |
@@ -1328,9 +1325,6 @@ class Parser { |
TokenType.COMMA, |
TokenType.SEMICOLON |
])) { |
- if (returnType is! GenericFunctionType) { |
- _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
- } |
return parseInitializedIdentifierList( |
commentAndMetadata, |
modifiers.staticKeyword, |
@@ -2137,9 +2131,6 @@ class Parser { |
TokenType.COMMA, |
TokenType.SEMICOLON |
])) { |
- if (returnType is! GenericFunctionType) { |
- _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
- } |
return astFactory.topLevelVariableDeclaration( |
commentAndMetadata.comment, |
commentAndMetadata.metadata, |
@@ -2217,7 +2208,7 @@ class Parser { |
null, _validateModifiersForTopLevelVariable(modifiers), null), |
_expect(TokenType.SEMICOLON)); |
} |
- TypeAnnotation returnType = parseReturnType(false); |
+ TypeAnnotation returnType = parseTypeAnnotation(false); |
keyword = _currentToken.keyword; |
next = _peek(); |
if ((keyword == Keyword.GET || keyword == Keyword.SET) && |
@@ -2892,7 +2883,7 @@ class Parser { |
keywordToken = null; |
} |
} else if (_isTypedIdentifier(_currentToken)) { |
- type = parseReturnType(false); |
+ type = parseTypeAnnotation(false); |
} else if (inFunctionType && _matchesIdentifier()) { |
type = parseTypeAnnotation(false); |
} else if (!optional) { |
@@ -3414,7 +3405,7 @@ class Parser { |
* | '(' normalParameterTypes ',' optionalParameterTypes ')' | |
* | '(' optionalParameterTypes ')' |
* normalParameterTypes ::= |
- * normalParameterType (',' normalParameterType)* |
+ * normalParameterType (',' normalParameterType)* |
* normalParameterType ::= |
* type | typedIdentifier |
* optionalParameterTypes ::= |
@@ -4137,9 +4128,6 @@ class Parser { |
TokenType.COMMA, |
TokenType.SEMICOLON |
])) { |
- if (returnType is! GenericFunctionType) { |
- _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
- } |
return _parseVariableDeclarationStatementAfterType( |
commentAndMetadata, null, returnType); |
} else { |
@@ -4217,9 +4205,6 @@ class Parser { |
TokenType.COMMA, |
TokenType.SEMICOLON |
])) { |
- if (returnType is! GenericFunctionType) { |
- _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
- } |
return _parseVariableDeclarationStatementAfterType( |
commentAndMetadata, null, returnType); |
} else { |
@@ -4365,15 +4350,10 @@ class Parser { |
//_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.endToken); |
} |
TypeAnnotation type = holder.type; |
- if (type != null) { |
- if (type is TypeName && |
- _tokenMatchesKeyword(type.name.beginToken, Keyword.VOID)) { |
- _reportErrorForToken( |
- ParserErrorCode.VOID_PARAMETER, type.name.beginToken); |
- } else if (holder.keyword != null && |
- _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) { |
- _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword); |
- } |
+ if (type != null && |
+ holder.keyword != null && |
+ _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) { |
+ _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword); |
} |
if (thisKeyword != null) { |
// TODO(brianwilkerson) If there are type parameters but no parameters, |
@@ -4701,14 +4681,14 @@ class Parser { |
if (keyword == Keyword.AS) { |
Token asOperator = getAndAdvance(); |
return astFactory.asExpression( |
- expression, asOperator, parseTypeAnnotation(true)); |
+ expression, asOperator, parseTypeNotVoid(true)); |
} else if (keyword == Keyword.IS) { |
Token isOperator = getAndAdvance(); |
Token notOperator = null; |
if (_matches(TokenType.BANG)) { |
notOperator = getAndAdvance(); |
} |
- TypeAnnotation type = parseTypeAnnotation(true); |
+ TypeAnnotation type = parseTypeNotVoid(true); |
return astFactory.isExpression(expression, isOperator, notOperator, type); |
} else if (_currentToken.type.isRelationalOperator) { |
Token operator = getAndAdvance(); |
@@ -4747,26 +4727,6 @@ class Parser { |
return astFactory.returnStatement(returnKeyword, expression, semicolon); |
} |
- /** |
- * Parse a return type. Return the return type that was parsed. |
- * |
- * returnType ::= |
- * 'void' |
- * | type |
- */ |
- TypeAnnotation parseReturnType(bool inExpression) { |
- if (_currentToken.keyword == Keyword.VOID) { |
- if (_atGenericFunctionTypeAfterReturnType(_peek())) { |
- return parseTypeAnnotation(false); |
- } else { |
- return astFactory.typeName( |
- astFactory.simpleIdentifier(getAndAdvance()), null); |
- } |
- } else { |
- return parseTypeAnnotation(inExpression); |
- } |
- } |
- |
/** |
* Parse a setter. The [commentAndMetadata] is the documentation comment and |
* metadata to be associated with the declaration. The [externalKeyword] is |
@@ -5130,7 +5090,7 @@ class Parser { |
TypeName exceptionType = null; |
if (_matchesKeyword(Keyword.ON)) { |
onKeyword = getAndAdvance(); |
- exceptionType = parseTypeAnnotation(false); |
+ exceptionType = parseTypeNotVoid(false); |
} |
Token catchKeyword = null; |
Token leftParenthesis = null; |
@@ -5218,6 +5178,27 @@ class Parser { |
* | functionType |
*/ |
TypeAnnotation parseTypeAnnotation(bool inExpression) { |
+ TypeAnnotation type = null; |
+ if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
+ // Generic function type with no return type. |
+ type = parseGenericFunctionTypeAfterReturnType(null); |
+ } else { |
+ type = parseTypeWithoutFunction(inExpression); |
+ } |
+ while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
+ type = parseGenericFunctionTypeAfterReturnType(type); |
+ } |
+ return type; |
+ } |
+ |
+ /** |
+ * Parse a type which is not `void`. |
+ * |
+ * typeNotVoid ::= |
+ * functionType |
+ * | typeNotVoidWithoutFunction |
+ */ |
+ TypeAnnotation parseTypeNotVoid(bool inExpression) { |
TypeAnnotation type = null; |
if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
// Generic function type with no return type. |
@@ -5235,6 +5216,22 @@ class Parser { |
return type; |
} |
+ /** |
+ * Parse a type which is not a function type. |
+ * |
+ * typeWithoutFunction ::= |
+ * `void` |
+ * | typeNotVoidWithoutFunction |
+ */ |
+ TypeAnnotation parseTypeWithoutFunction(bool inExpression) { |
+ if (_currentToken.keyword == Keyword.VOID) { |
+ return astFactory.typeName( |
+ astFactory.simpleIdentifier(getAndAdvance()), null); |
+ } else { |
+ return parseTypeName(inExpression); |
+ } |
+ } |
+ |
/** |
* Parse a list of type arguments. Return the type argument list that was |
* parsed. |
@@ -5260,11 +5257,14 @@ class Parser { |
} |
/** |
- * Parse a type name. Return the type name that was parsed. |
+ * Parse a type which is not void and is not a function type. Return the type |
+ * that was parsed. |
* |
- * type ::= |
+ * typeNotVoidWithoutFunction ::= |
* qualified typeArguments? |
*/ |
+ // TODO(eernst): Rename this to `parseTypeNotVoidWithoutFunction`? |
+ // Apparently, it was named `parseTypeName` before type arguments existed. |
TypeName parseTypeName(bool inExpression) { |
TypeName realType = _parseTypeName(inExpression); |
// If this is followed by a generic method type comment, allow the comment |
@@ -5290,7 +5290,7 @@ class Parser { |
} |
if (_matchesKeyword(Keyword.EXTENDS)) { |
Token keyword = getAndAdvance(); |
- TypeAnnotation bound = parseTypeAnnotation(false); |
+ TypeAnnotation bound = parseTypeNotVoid(false); |
return astFactory.typeParameter(commentAndMetadata.comment, |
commentAndMetadata.metadata, name, keyword, bound); |
} |
@@ -5620,29 +5620,6 @@ class Parser { |
return null; |
} |
- /** |
- * Parse a return type, starting at the [startToken], without actually |
- * creating a return type or changing the current token. Return the token |
- * following the return type that was parsed, or `null` if the given token is |
- * not the first token in a valid return type. |
- * |
- * This method must be kept in sync with [parseReturnType]. |
- * |
- * returnType ::= |
- * 'void' |
- * | type |
- */ |
- Token skipReturnType(Token startToken) { |
- if (_tokenMatchesKeyword(startToken, Keyword.VOID)) { |
- if (_atGenericFunctionTypeAfterReturnType(_peek())) { |
- return skipTypeAnnotation(startToken); |
- } |
- return startToken.next; |
- } else { |
- return skipTypeAnnotation(startToken); |
- } |
- } |
- |
/** |
* Parse a simple identifier, starting at the [startToken], without actually |
* creating a simple identifier or changing the current token. Return the |
@@ -5701,12 +5678,10 @@ class Parser { |
Token skipTypeAnnotation(Token startToken) { |
Token next = null; |
if (_atGenericFunctionTypeAfterReturnType(startToken)) { |
+ // Generic function type with no return type. |
next = skipGenericFunctionTypeAfterReturnType(startToken); |
- } else if (startToken.keyword == Keyword.VOID && |
- _atGenericFunctionTypeAfterReturnType(startToken.next)) { |
- next = startToken.next; |
} else { |
- next = skipTypeName(startToken); |
+ next = skipTypeWithoutFunction(startToken); |
} |
while (next != null && _atGenericFunctionTypeAfterReturnType(next)) { |
next = skipGenericFunctionTypeAfterReturnType(next); |
@@ -5714,6 +5689,22 @@ class Parser { |
return next; |
} |
+ /** |
+ * Parse a typeWithoutFunction, starting at the [startToken], without actually |
+ * creating a TypeAnnotation or changing the current token. Return the token |
+ * following the typeWithoutFunction that was parsed, or `null` if the given |
+ * token is not the first token in a valid typeWithoutFunction. |
+ * |
+ * This method must be kept in sync with [parseTypeWithoutFunction]. |
+ */ |
+ Token skipTypeWithoutFunction(Token startToken) { |
+ if (startToken.keyword == Keyword.VOID) { |
+ return startToken.next; |
+ } else { |
+ return skipTypeName(startToken); |
+ } |
+ } |
+ |
/** |
* Parse a list of type arguments, starting at the [startToken], without |
* actually creating a type argument list or changing the current token. |
@@ -5735,7 +5726,7 @@ class Parser { |
!_injectGenericCommentTypeList()) { |
return null; |
} |
- token = skipTypeName(token.next); |
+ token = skipTypeAnnotation(token.next); |
if (token == null) { |
// If the start token '<' is followed by '>' |
// then assume this should be type argument list but is missing a type |
@@ -5746,7 +5737,7 @@ class Parser { |
return null; |
} |
while (_tokenMatches(token, TokenType.COMMA)) { |
- token = skipTypeName(token.next); |
+ token = skipTypeAnnotation(token.next); |
if (token == null) { |
return null; |
} |
@@ -5933,7 +5924,7 @@ class Parser { |
// This looks like the start of a function |
return true; |
} |
- Token token = skipReturnType(_currentToken); |
+ Token token = skipTypeAnnotation(_currentToken); |
if (token == null) { |
return false; |
} |
@@ -6321,7 +6312,7 @@ class Parser { |
* name that is followed by a variable or field formal parameter. |
*/ |
bool _isTypedIdentifier(Token startToken) { |
- Token token = skipReturnType(startToken); |
+ Token token = skipTypeAnnotation(startToken); |
if (token == null) { |
return false; |
} else if (_tokenMatchesIdentifier(token)) { |
@@ -6330,10 +6321,6 @@ class Parser { |
_tokenMatches(token.next, TokenType.PERIOD) && |
_tokenMatchesIdentifier(token.next.next)) { |
return true; |
- } else if (_tokenMatchesKeyword(startToken, Keyword.VOID)) { |
- // The keyword 'void' isn't a valid identifier, so it should be assumed to |
- // be a type name. |
- return true; |
} else if (startToken.next != token && |
!_tokenMatches(token, TokenType.OPEN_PAREN)) { |
// The type is more than a simple identifier, so it should be assumed to |
@@ -7011,7 +6998,7 @@ class Parser { |
CommentAndMetadata commentAndMetadata, Token keyword) { |
TypeAnnotation returnType = null; |
if (hasReturnTypeInTypeAlias) { |
- returnType = parseReturnType(false); |
+ returnType = parseTypeAnnotation(false); |
} |
SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); |
TypeParameterList typeParameters = null; |
@@ -7326,7 +7313,7 @@ class Parser { |
// type. |
return null; |
} |
- return parseReturnType(false); |
+ return parseTypeAnnotation(false); |
} |
Token next2 = next.next; |
Token next3 = next2.next; |
@@ -7334,7 +7321,7 @@ class Parser { |
_tokenMatchesIdentifier(next2) && |
(_tokenMatchesIdentifier(next3) || |
_tokenMatches(next3, TokenType.LT))) { |
- return parseReturnType(false); |
+ return parseTypeAnnotation(false); |
} |
} |
return null; |
@@ -7879,7 +7866,7 @@ class Parser { |
(_tokenMatchesIdentifier(next.next.next) || |
_tokenMatches(next.next.next, TokenType.LT) || |
_tokenMatchesKeyword(next.next.next, Keyword.THIS)))) { |
- return skipReturnType(startToken); |
+ return skipTypeAnnotation(startToken); |
} |
} |
return null; |