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 c16281ee5b4b91c871d2a0476d07226972377398..dced5b5041e44d6a128e528ee77a46cb372dc432 100644 |
--- a/pkg/analyzer/lib/src/generated/parser.dart |
+++ b/pkg/analyzer/lib/src/generated/parser.dart |
@@ -1535,32 +1535,6 @@ class Parser { |
} |
/** |
- * Parse a class type alias. The [commentAndMetadata] is the metadata to be |
- * associated with the member. The [abstractKeyword] is the token representing |
- * the 'abstract' keyword. The [classKeyword] is the token representing the |
- * 'class' keyword. Return the class type alias that was parsed. |
- * |
- * This method assumes that the current token matches an identifier. |
- * |
- * classTypeAlias ::= |
- * identifier typeParameters? '=' 'abstract'? mixinApplication |
- * |
- * mixinApplication ::= |
- * type withClause implementsClause? ';' |
- */ |
- ClassTypeAlias parseClassTypeAlias(CommentAndMetadata commentAndMetadata, |
- Token abstractKeyword, Token classKeyword) { |
- SimpleIdentifier className = |
- _parseSimpleIdentifierUnchecked(isDeclaration: true); |
- TypeParameterList typeParameters = null; |
- if (_matches(TokenType.LT)) { |
- typeParameters = parseTypeParameterList(); |
- } |
- return _parseClassTypeAliasAfterName(commentAndMetadata, abstractKeyword, |
- classKeyword, className, typeParameters); |
- } |
- |
- /** |
* Parse a single combinator. Return the combinator that was parsed, or `null` |
* if no combinator is found. |
* |
@@ -2780,7 +2754,8 @@ class Parser { |
* | 'var' |
* | type |
*/ |
- FinalConstVarOrType parseFinalConstVarOrType(bool optional) { |
+ FinalConstVarOrType parseFinalConstVarOrType(bool optional, |
+ {bool inFunctionType = false}) { |
Token keywordToken = null; |
TypeName type = null; |
Keyword keyword = _currentToken.keyword; |
@@ -2802,6 +2777,8 @@ class Parser { |
} |
} else if (_isTypedIdentifier(_currentToken)) { |
type = parseReturnType(); |
+ } else if (inFunctionType && _matchesIdentifier()) { |
+ type = parseTypeAnnotation(); |
} else if (!optional) { |
_reportErrorForCurrentToken( |
ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); |
@@ -2826,34 +2803,60 @@ class Parser { |
* normalFormalParameter ('=' expression)? |
* normalFormalParameter (':' expression)? |
*/ |
- FormalParameter parseFormalParameter(ParameterKind kind) { |
- NormalFormalParameter parameter = parseNormalFormalParameter(); |
+ FormalParameter parseFormalParameter(ParameterKind kind, |
+ {bool inFunctionType = false}) { |
+ NormalFormalParameter parameter = |
+ parseNormalFormalParameter(inFunctionType: inFunctionType); |
TokenType type = _currentToken.type; |
if (type == TokenType.EQ) { |
+ if (inFunctionType) { |
+ _reportErrorForCurrentToken( |
+ ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE); |
+ } |
Token separator = getAndAdvance(); |
Expression defaultValue = parseExpression2(); |
if (kind == ParameterKind.REQUIRED) { |
_reportErrorForNode( |
ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter); |
kind = ParameterKind.POSITIONAL; |
+ } else if (kind == ParameterKind.NAMED && |
+ inFunctionType && |
+ parameter.identifier == null) { |
+ _reportErrorForCurrentToken( |
+ ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER); |
} |
return astFactory.defaultFormalParameter( |
parameter, kind, separator, defaultValue); |
} else if (type == TokenType.COLON) { |
+ if (inFunctionType) { |
+ _reportErrorForCurrentToken( |
+ ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE); |
+ } |
Token separator = getAndAdvance(); |
Expression defaultValue = parseExpression2(); |
- if (kind == ParameterKind.POSITIONAL) { |
- _reportErrorForToken( |
- ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, |
- separator); |
- } else if (kind == ParameterKind.REQUIRED) { |
+ if (kind == ParameterKind.REQUIRED) { |
_reportErrorForNode( |
ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter); |
kind = ParameterKind.NAMED; |
+ } else if (kind == ParameterKind.POSITIONAL) { |
+ _reportErrorForToken( |
+ ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, |
+ separator); |
+ } else if (kind == ParameterKind.NAMED && |
+ inFunctionType && |
+ parameter.identifier == null) { |
+ _reportErrorForCurrentToken( |
+ ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER); |
} |
return astFactory.defaultFormalParameter( |
parameter, kind, separator, defaultValue); |
} else if (kind != ParameterKind.REQUIRED) { |
+ if (kind == ParameterKind.NAMED && |
+ inFunctionType && |
+ parameter.identifier == null) { |
+ _reportErrorForCurrentToken( |
+ ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER); |
+ } |
return astFactory.defaultFormalParameter(parameter, kind, null, null); |
} |
return parameter; |
@@ -2881,9 +2884,9 @@ class Parser { |
* namedFormalParameters ::= |
* '{' defaultNamedParameter (',' defaultNamedParameter)* '}' |
*/ |
- FormalParameterList parseFormalParameterList() { |
+ FormalParameterList parseFormalParameterList({bool inFunctionType = false}) { |
if (_matches(TokenType.OPEN_PAREN)) { |
- return _parseFormalParameterListUnchecked(); |
+ return _parseFormalParameterListUnchecked(inFunctionType: inFunctionType); |
} |
// TODO(brianwilkerson) Improve the error message. |
_reportErrorForCurrentToken( |
@@ -3267,6 +3270,90 @@ class Parser { |
} |
/** |
+ * Parse the portion of a generic function type following the [returnType]. |
+ * |
+ * functionType ::= |
+ * returnType? 'Function' typeParameters? parameterTypeList |
+ * parameterTypeList ::= |
+ * '(' ')' | |
+ * | '(' normalParameterTypes ','? ')' | |
+ * | '(' normalParameterTypes ',' optionalParameterTypes ')' | |
+ * | '(' optionalParameterTypes ')' |
+ * normalParameterTypes ::= |
+ * normalParameterType (',' normalParameterType)* |
+ * normalParameterType ::= |
+ * type | typedIdentifier |
+ * optionalParameterTypes ::= |
+ * optionalPositionalParameterTypes | namedParameterTypes |
+ * optionalPositionalParameterTypes ::= |
+ * '[' normalParameterTypes ','? ']' |
+ * namedParameterTypes ::= |
+ * '{' typedIdentifier (',' typedIdentifier)* ','? '}' |
+ * typedIdentifier ::= |
+ * type identifier |
+ */ |
+ GenericFunctionType parseGenericFunctionTypeAfterReturnType( |
+ TypeAnnotation returnType) { |
+ Token functionKeyword = null; |
+ if (_matchesString('Function')) { |
+ functionKeyword = getAndAdvance(); |
+ } else if (_matchesIdentifier()) { |
+ _reportErrorForCurrentToken(ParserErrorCode.NAMED_FUNCTION_TYPE); |
+ } else { |
+ _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_KEYWORD); |
+ } |
+ TypeParameterList typeParameters = null; |
+ if (_matches(TokenType.LT)) { |
+ typeParameters = parseTypeParameterList(); |
+ } |
+ FormalParameterList parameters = |
+ parseFormalParameterList(inFunctionType: true); |
+ return astFactory.genericFunctionType( |
+ returnType, functionKeyword, typeParameters, parameters); |
+ } |
+ |
+ /** |
+ * Parse a generic function type alias. |
+ * |
+ * This method assumes that the current token is an identifier. |
+ * |
+ * genericTypeAlias ::= |
+ * 'typedef' identifier typeParameterList? '=' functionType ';' |
+ */ |
+ GenericTypeAlias parseGenericTypeAlias( |
+ CommentAndMetadata commentAndMetadata, Token keyword) { |
+ Identifier name = _parseSimpleIdentifierUnchecked(isDeclaration: true); |
+ TypeParameterList typeParameters = null; |
+ if (_matches(TokenType.LT)) { |
+ typeParameters = parseTypeParameterList(); |
+ } |
+ Token equals = _expect(TokenType.EQ); |
+ TypeAnnotation functionType = parseTypeAnnotation(); |
+ Token semicolon = _expect(TokenType.SEMICOLON); |
+ if (functionType is! GenericFunctionType) { |
+ // TODO(brianwilkerson) Generate an error and recover (better than this). |
+ return astFactory.genericTypeAlias( |
+ commentAndMetadata.comment, |
+ commentAndMetadata.metadata, |
+ keyword, |
+ name, |
+ typeParameters, |
+ equals, |
+ null, |
+ semicolon); |
+ } |
+ return astFactory.genericTypeAlias( |
+ commentAndMetadata.comment, |
+ commentAndMetadata.metadata, |
+ keyword, |
+ name, |
+ typeParameters, |
+ equals, |
+ functionType, |
+ semicolon); |
+ } |
+ |
+ /** |
* Parse a getter. The [commentAndMetadata] is the documentation comment and |
* metadata to be associated with the declaration. The externalKeyword] is the |
* 'external' token. The staticKeyword] is the static keyword, or `null` if |
@@ -4015,15 +4102,21 @@ class Parser { |
* declaredIdentifier |
* | metadata identifier |
*/ |
- NormalFormalParameter parseNormalFormalParameter() { |
+ NormalFormalParameter parseNormalFormalParameter( |
+ {bool inFunctionType = false}) { |
CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); |
- FinalConstVarOrType holder = parseFinalConstVarOrType(true); |
+ FinalConstVarOrType holder = parseFinalConstVarOrType(!inFunctionType, |
+ inFunctionType: inFunctionType); |
Token thisKeyword = null; |
Token period = null; |
if (_matchesKeyword(Keyword.THIS)) { |
thisKeyword = getAndAdvance(); |
period = _expect(TokenType.PERIOD); |
} |
+ if (!_matchesIdentifier() && inFunctionType) { |
+ return astFactory.simpleFormalParameter(commentAndMetadata.comment, |
+ commentAndMetadata.metadata, holder.keyword, holder.type, null); |
+ } |
SimpleIdentifier identifier = parseSimpleIdentifier(); |
TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
if (_matches(TokenType.OPEN_PAREN)) { |
@@ -4860,16 +4953,10 @@ class Parser { |
* |
* typeAlias ::= |
* 'typedef' typeAliasBody |
+ * | genericTypeAlias |
* |
* typeAliasBody ::= |
- * classTypeAlias |
- * | functionTypeAlias |
- * |
- * classTypeAlias ::= |
- * identifier typeParameters? '=' 'abstract'? mixinApplication |
- * |
- * mixinApplication ::= |
- * qualified withClause implementsClause? ';' |
+ * functionTypeAlias |
* |
* functionTypeAlias ::= |
* functionPrefix typeParameterList? formalParameterList ';' |
@@ -4885,16 +4972,12 @@ class Parser { |
next = _skipTypeParameterList(next); |
if (next != null && _tokenMatches(next, TokenType.EQ)) { |
TypeAlias typeAlias = |
- parseClassTypeAlias(commentAndMetadata, null, keyword); |
- _reportErrorForToken( |
- ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); |
+ parseGenericTypeAlias(commentAndMetadata, keyword); |
return typeAlias; |
} |
} else if (_tokenMatches(next, TokenType.EQ)) { |
TypeAlias typeAlias = |
- parseClassTypeAlias(commentAndMetadata, null, keyword); |
- _reportErrorForToken( |
- ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); |
+ parseGenericTypeAlias(commentAndMetadata, keyword); |
return typeAlias; |
} |
} |
@@ -4902,6 +4985,25 @@ class Parser { |
} |
/** |
+ * Parse a type. |
+ * |
+ * type ::= |
+ * typeWithoutFunction |
+ * | functionType |
+ */ |
+ TypeAnnotation parseTypeAnnotation() { |
+ if (_matchesString('Function')) { |
+ // Generic function type with no return type. |
+ return parseGenericFunctionTypeAfterReturnType(null); |
+ } |
+ TypeAnnotation type = parseReturnType(); |
+ while (_matchesString('Function')) { |
+ type = parseGenericFunctionTypeAfterReturnType(type); |
+ } |
+ return type; |
+ } |
+ |
+ /** |
* Parse a list of type arguments. Return the type argument list that was |
* parsed. |
* |
@@ -6367,8 +6469,8 @@ class Parser { |
* Parse a list of formal parameters given that the list starts with the given |
* [leftParenthesis]. Return the formal parameters that were parsed. |
*/ |
- FormalParameterList _parseFormalParameterListAfterParen( |
- Token leftParenthesis) { |
+ FormalParameterList _parseFormalParameterListAfterParen(Token leftParenthesis, |
+ {bool inFunctionType = false}) { |
if (_matches(TokenType.CLOSE_PAREN)) { |
return astFactory.formalParameterList( |
leftParenthesis, null, null, null, getAndAdvance()); |
@@ -6441,7 +6543,8 @@ class Parser { |
// |
// Parse and record the parameter. |
// |
- FormalParameter parameter = parseFormalParameter(kind); |
+ FormalParameter parameter = |
+ parseFormalParameter(kind, inFunctionType: inFunctionType); |
parameters.add(parameter); |
if (kind == ParameterKind.REQUIRED && wasOptionalParameter) { |
_reportErrorForNode( |
@@ -6530,8 +6633,10 @@ class Parser { |
* |
* This method assumes that the current token matches `TokenType.OPEN_PAREN`. |
*/ |
- FormalParameterList _parseFormalParameterListUnchecked() { |
- return _parseFormalParameterListAfterParen(getAndAdvance()); |
+ FormalParameterList _parseFormalParameterListUnchecked( |
+ {bool inFunctionType = false}) { |
+ return _parseFormalParameterListAfterParen(getAndAdvance(), |
+ inFunctionType: inFunctionType); |
} |
/** |