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

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

Issue 1216873002: Add parsing support for generic methods (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: sort and format Created 5 years, 6 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 | « no previous file | 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 af4bd8dc24b17c85303aeab4a40b757838e208a4..8581fa44f54a998a00596f88dff2645a529de37c 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -2333,7 +2333,8 @@ class Parser {
_peek().matchesAny([
TokenType.OPEN_PAREN,
TokenType.OPEN_CURLY_BRACKET,
- TokenType.FUNCTION
+ TokenType.FUNCTION,
+ TokenType.LT
])) {
_validateModifiersForGetterOrSetterOrMethod(modifiers);
return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
@@ -2488,6 +2489,12 @@ class Parser {
// function type alias that was parsed.
_parseFunctionTypeAlias(commentAndMetadata, getAndAdvance());
return null;
+ } else if (parseGenericMethods) {
+ Token token = _skipTypeParameterList(_peek());
+ if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
+ return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
+ modifiers.externalKeyword, modifiers.staticKeyword, null);
+ }
}
TypeName type = parseTypeName();
if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
@@ -2552,6 +2559,9 @@ class Parser {
return _parseMethodDeclarationAfterParameters(commentAndMetadata,
modifiers.externalKeyword, modifiers.staticKeyword, type, methodName,
null, parameters);
+ } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) {
+ return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
+ modifiers.externalKeyword, modifiers.staticKeyword, type);
} else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) {
// We have found "TypeName identifier {", and are guessing that this is a
// getter without the keyword 'get'.
@@ -3041,14 +3051,18 @@ class Parser {
* parsed.
*
* functionExpression ::=
- * formalParameterList functionExpressionBody
+ * typeParameters? formalParameterList functionExpressionBody
*/
FunctionExpression parseFunctionExpression() {
+ TypeParameterList typeParameters = null;
+ if (parseGenericMethods && _matches(TokenType.LT)) {
+ typeParameters = parseTypeParameterList();
+ }
FormalParameterList parameters = parseFormalParameterList();
_validateFormalParameterList(parameters);
FunctionBody body =
_parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
- return new FunctionExpression(null, parameters, body);
+ return new FunctionExpression(typeParameters, parameters, body);
}
/**
@@ -3151,7 +3165,7 @@ class Parser {
* | simpleFormalParameter
*
* functionSignature:
- * metadata returnType? identifier formalParameterList
+ * metadata returnType? identifier typeParameters? formalParameterList
*
* fieldFormalParameter ::=
* metadata finalConstVarOrType? 'this' '.' identifier
@@ -3170,6 +3184,10 @@ class Parser {
period = _expect(TokenType.PERIOD);
}
SimpleIdentifier identifier = parseSimpleIdentifier();
+ TypeParameterList typeParameters = null;
+ if (parseGenericMethods && _matches(TokenType.LT)) {
+ typeParameters = parseTypeParameterList();
+ }
if (_matches(TokenType.OPEN_PAREN)) {
FormalParameterList parameters = parseFormalParameterList();
if (thisKeyword == null) {
@@ -3178,13 +3196,17 @@ class Parser {
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
}
return new FunctionTypedFormalParameter(commentAndMetadata.comment,
- commentAndMetadata.metadata, holder.type, identifier, null,
- parameters);
+ commentAndMetadata.metadata, holder.type, identifier,
+ typeParameters, parameters);
} else {
return new FieldFormalParameter(commentAndMetadata.comment,
commentAndMetadata.metadata, holder.keyword, holder.type,
- thisKeyword, period, identifier, null, parameters);
+ thisKeyword, period, identifier, typeParameters, parameters);
}
+ } else if (typeParameters != null) {
+ // TODO(brianwilkerson) Report an error. It looks like a function-typed
+ // parameter with no parameter list.
+ //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.endToken);
}
TypeName type = holder.type;
if (type != null) {
@@ -3197,6 +3219,9 @@ class Parser {
}
}
if (thisKeyword != null) {
+ // TODO(brianwilkerson) If there are type parameters but no parameters,
+ // should we create a synthetic empty parameter list here so we can
+ // capture the type parameters?
return new FieldFormalParameter(commentAndMetadata.comment,
commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword,
period, identifier, null, null);
@@ -3846,7 +3871,11 @@ class Parser {
if (_inInitializer) {
return false;
}
- Token afterParameters = _skipFormalParameterList(token);
+ Token afterTypeParameters = _skipTypeParameterList(token);
+ if (afterTypeParameters == null) {
+ afterTypeParameters = token;
+ }
+ Token afterParameters = _skipFormalParameterList(afterTypeParameters);
if (afterParameters == null) {
return false;
}
@@ -3923,6 +3952,17 @@ class Parser {
_tokenMatchesKeyword(token, Keyword.IN);
}
+ bool _isLikelyParameterList() {
+ if (_matches(TokenType.OPEN_PAREN)) {
+ return true;
+ }
+ if (!parseGenericMethods) {
+ return false;
+ }
+ Token token = _skipTypeArgumentList(_currentToken);
+ return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
+ }
+
/**
* Given that we have just found bracketed text within the given [comment],
* look to see whether that text is (a) followed by a parenthesized link
@@ -4011,7 +4051,8 @@ class Parser {
// 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) {
+ } else if (startToken.next != token &&
+ !_tokenMatches(token, TokenType.OPEN_PAREN)) {
// The type is more than a simple identifier, so it should be assumed to
// be a type name.
return true;
@@ -4184,22 +4225,27 @@ class Parser {
Expression expression = _parsePrimaryExpression();
bool isOptional = primaryAllowed || expression is SimpleIdentifier;
while (true) {
- while (_matches(TokenType.OPEN_PAREN)) {
+ while (_isLikelyParameterList()) {
+ TypeArgumentList typeArguments = null;
+ if (_matches(TokenType.LT)) {
+ typeArguments = parseTypeArgumentList();
+ }
ArgumentList argumentList = parseArgumentList();
if (expression is SimpleIdentifier) {
- expression = new MethodInvocation(
- null, null, expression as SimpleIdentifier, null, argumentList);
+ expression = new MethodInvocation(null, null,
+ expression as SimpleIdentifier, typeArguments, argumentList);
} else if (expression is PrefixedIdentifier) {
PrefixedIdentifier identifier = expression as PrefixedIdentifier;
expression = new MethodInvocation(identifier.prefix,
- identifier.period, identifier.identifier, null, argumentList);
+ identifier.period, identifier.identifier, typeArguments,
+ argumentList);
} else if (expression is PropertyAccess) {
PropertyAccess access = expression as PropertyAccess;
expression = new MethodInvocation(access.target, access.operator,
- access.propertyName, null, argumentList);
+ access.propertyName, typeArguments, argumentList);
} else {
- expression =
- new FunctionExpressionInvocation(expression, null, argumentList);
+ expression = new FunctionExpressionInvocation(
+ expression, typeArguments, argumentList);
}
if (!primaryAllowed) {
isOptional = false;
@@ -4351,7 +4397,8 @@ class Parser {
* method invocation.
*
* cascadeSection ::=
- * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* cascadeAssignment?
+ * '..' (cascadeSelector typeArguments? arguments*)
+ * (assignableSelector typeArguments? arguments*)* cascadeAssignment?
*
* cascadeSelector ::=
* '[' expression ']'
@@ -4386,20 +4433,24 @@ class Parser {
}
assert((expression == null && functionName != null) ||
(expression != null && functionName == null));
- if (_currentToken.type == TokenType.OPEN_PAREN) {
- while (_currentToken.type == TokenType.OPEN_PAREN) {
+ if (_isLikelyParameterList()) {
+ while (_isLikelyParameterList()) {
+ TypeArgumentList typeArguments = null;
+ if (_matches(TokenType.LT)) {
+ typeArguments = parseTypeArgumentList();
+ }
if (functionName != null) {
- expression = new MethodInvocation(
- expression, period, functionName, null, parseArgumentList());
+ expression = new MethodInvocation(expression, period, functionName,
+ typeArguments, parseArgumentList());
period = null;
functionName = null;
} else if (expression == null) {
// It should not be possible to get here.
expression = new MethodInvocation(expression, period,
- _createSyntheticIdentifier(), null, parseArgumentList());
+ _createSyntheticIdentifier(), typeArguments, parseArgumentList());
} else {
expression = new FunctionExpressionInvocation(
- expression, null, parseArgumentList());
+ expression, typeArguments, parseArgumentList());
}
}
} else if (functionName != null) {
@@ -4414,15 +4465,19 @@ class Parser {
if (!identical(selector, expression)) {
expression = selector;
progress = true;
- while (_currentToken.type == TokenType.OPEN_PAREN) {
+ while (_isLikelyParameterList()) {
+ TypeArgumentList typeArguments = null;
+ if (_matches(TokenType.LT)) {
+ typeArguments = parseTypeArgumentList();
+ }
if (expression is PropertyAccess) {
PropertyAccess propertyAccess = expression as PropertyAccess;
expression = new MethodInvocation(propertyAccess.target,
- propertyAccess.operator, propertyAccess.propertyName, null,
- parseArgumentList());
+ propertyAccess.operator, propertyAccess.propertyName,
+ typeArguments, parseArgumentList());
} else {
expression = new FunctionExpressionInvocation(
- expression, null, parseArgumentList());
+ expression, typeArguments, parseArgumentList());
}
}
}
@@ -5758,6 +5813,10 @@ class Parser {
keyword = getAndAdvance();
}
SimpleIdentifier name = parseSimpleIdentifier();
+ TypeParameterList typeParameters = null;
+ if (parseGenericMethods && _matches(TokenType.LT)) {
+ typeParameters = parseTypeParameterList();
+ }
FormalParameterList parameters = null;
if (!isGetter) {
if (_matches(TokenType.OPEN_PAREN)) {
@@ -5788,7 +5847,7 @@ class Parser {
// }
return new FunctionDeclaration(commentAndMetadata.comment,
commentAndMetadata.metadata, externalKeyword, returnType, keyword, name,
- new FunctionExpression(null, parameters, body));
+ new FunctionExpression(typeParameters, parameters, body));
}
/**
@@ -6270,6 +6329,10 @@ class Parser {
CommentAndMetadata commentAndMetadata, Token externalKeyword,
Token staticKeyword, TypeName returnType) {
SimpleIdentifier methodName = parseSimpleIdentifier();
+ TypeParameterList typeParameters = null;
+ if (parseGenericMethods && _matches(TokenType.LT)) {
+ typeParameters = parseTypeParameterList();
+ }
FormalParameterList parameters;
if (!_matches(TokenType.OPEN_PAREN) &&
(_matches(TokenType.OPEN_CURLY_BRACKET) ||
@@ -6284,7 +6347,7 @@ class Parser {
}
_validateFormalParameterList(parameters);
return _parseMethodDeclarationAfterParameters(commentAndMetadata,
- externalKeyword, staticKeyword, returnType, methodName, null,
+ externalKeyword, staticKeyword, returnType, methodName, typeParameters,
parameters);
}
@@ -6712,17 +6775,22 @@ class Parser {
if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
_matches(TokenType.PERIOD) ||
_matches(TokenType.QUESTION_PERIOD) ||
- _matches(TokenType.OPEN_PAREN)) {
+ _matches(TokenType.OPEN_PAREN) ||
+ (parseGenericMethods && _matches(TokenType.LT))) {
do {
- if (_matches(TokenType.OPEN_PAREN)) {
+ if (_isLikelyParameterList()) {
+ TypeArgumentList typeArguments = null;
+ if (_matches(TokenType.LT)) {
+ typeArguments = parseTypeArgumentList();
+ }
ArgumentList argumentList = parseArgumentList();
if (operand is PropertyAccess) {
PropertyAccess access = operand as PropertyAccess;
operand = new MethodInvocation(access.target, access.operator,
- access.propertyName, null, argumentList);
+ access.propertyName, typeArguments, argumentList);
} else {
- operand =
- new FunctionExpressionInvocation(operand, null, argumentList);
+ operand = new FunctionExpressionInvocation(
+ operand, typeArguments, argumentList);
}
} else {
operand = _parseAssignableSelector(operand, true);
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/parser_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698