Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: pkg/analyzer/lib/src/generated/parser.dart

Issue 2628973003: Add preliminary parser support for generic function types (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/dart/error/syntactic_errors.dart ('k') | pkg/analyzer/test/generated/parser_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
/**
« no previous file with comments | « pkg/analyzer/lib/src/dart/error/syntactic_errors.dart ('k') | pkg/analyzer/test/generated/parser_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698