| 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 a18a016b41fb8399164cce1841d1d118501b2787..5f67ad19f2399d91387942a51721feb026de126c 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
|
| @@ -7023,7 +7010,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;
|
| @@ -7338,7 +7325,7 @@ class Parser {
|
| // type.
|
| return null;
|
| }
|
| - return parseReturnType(false);
|
| + return parseTypeAnnotation(false);
|
| }
|
| Token next2 = next.next;
|
| Token next3 = next2.next;
|
| @@ -7346,7 +7333,7 @@ class Parser {
|
| _tokenMatchesIdentifier(next2) &&
|
| (_tokenMatchesIdentifier(next3) ||
|
| _tokenMatches(next3, TokenType.LT))) {
|
| - return parseReturnType(false);
|
| + return parseTypeAnnotation(false);
|
| }
|
| }
|
| return null;
|
| @@ -7891,7 +7878,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;
|
|
|