Add parsing support for generic methods

R=scheglov@google.com

Review URL: https://codereview.chromium.org//1216873002.
This commit is contained in:
Brian Wilkerson
2015-06-29 08:39:15 -07:00
parent 76f1fec4f9
commit 09fd112781
2 changed files with 521 additions and 37 deletions
+102 -34
View File
@@ -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);
+419 -3
View File
@@ -173,6 +173,7 @@ class ComplexParserTest extends ParserTestCase {
(obj) => obj is MethodInvocation, MethodInvocation,
propertyAccess1.target);
expect(invocation2.methodName.name, "d");
expect(invocation2.typeArguments, isNull);
ArgumentList argumentList2 = invocation2.argumentList;
expect(argumentList2, isNotNull);
expect(argumentList2.arguments, hasLength(1));
@@ -182,6 +183,7 @@ class ComplexParserTest extends ParserTestCase {
FunctionExpressionInvocation invocation3 = EngineTestCase.assertInstanceOf(
(obj) => obj is FunctionExpressionInvocation,
FunctionExpressionInvocation, invocation2.target);
expect(invocation3.typeArguments, isNull);
ArgumentList argumentList3 = invocation3.argumentList;
expect(argumentList3, isNotNull);
expect(argumentList3.arguments, hasLength(1));
@@ -192,6 +194,45 @@ class ComplexParserTest extends ParserTestCase {
(obj) => obj is MethodInvocation, MethodInvocation,
invocation3.function);
expect(invocation4.methodName.name, "a");
expect(invocation4.typeArguments, isNull);
ArgumentList argumentList4 = invocation4.argumentList;
expect(argumentList4, isNotNull);
expect(argumentList4.arguments, hasLength(1));
}
void test_assignableExpression_arguments_normal_chain_typeArguments() {
enableGenericMethods = true;
PropertyAccess propertyAccess1 = parseExpression("a<E>(b)<F>(c).d<G>(e).f");
expect(propertyAccess1.propertyName.name, "f");
//
// a<E>(b)<F>(c).d>G?(e)
//
MethodInvocation invocation2 = EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation,
propertyAccess1.target);
expect(invocation2.methodName.name, "d");
expect(invocation2.typeArguments, isNotNull);
ArgumentList argumentList2 = invocation2.argumentList;
expect(argumentList2, isNotNull);
expect(argumentList2.arguments, hasLength(1));
//
// a<E>(b)<F>(c)
//
FunctionExpressionInvocation invocation3 = EngineTestCase.assertInstanceOf(
(obj) => obj is FunctionExpressionInvocation,
FunctionExpressionInvocation, invocation2.target);
expect(invocation3.typeArguments, isNotNull);
ArgumentList argumentList3 = invocation3.argumentList;
expect(argumentList3, isNotNull);
expect(argumentList3.arguments, hasLength(1));
//
// a(b)
//
MethodInvocation invocation4 = EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation,
invocation3.function);
expect(invocation4.methodName.name, "a");
expect(invocation4.typeArguments, isNotNull);
ArgumentList argumentList4 = invocation4.argumentList;
expect(argumentList4, isNotNull);
expect(argumentList4.arguments, hasLength(1));
@@ -1750,6 +1791,17 @@ class Foo {
"parseCascadeSection", "..()", [ParserErrorCode.MISSING_IDENTIFIER]);
expect(methodInvocation.target, isNull);
expect(methodInvocation.methodName.name, "");
expect(methodInvocation.typeArguments, isNull);
expect(methodInvocation.argumentList.arguments, hasLength(0));
}
void test_parseCascadeSection_missingIdentifier_typeArguments() {
enableGenericMethods = true;
MethodInvocation methodInvocation = parse4(
"parseCascadeSection", "..<E>()", [ParserErrorCode.MISSING_IDENTIFIER]);
expect(methodInvocation.target, isNull);
expect(methodInvocation.methodName.name, "");
expect(methodInvocation.typeArguments, isNotNull);
expect(methodInvocation.argumentList.arguments, hasLength(0));
}
@@ -2527,6 +2579,12 @@ class ParserTestCase extends EngineTestCase {
*/
static bool parseFunctionBodies = true;
/**
* A flag indicating whether generic method support should be enabled for a
* specific test.
*/
bool enableGenericMethods = false;
/**
* If non-null, this value is used to override the default value of
* [Scanner.enableNullAwareOperators] before scanning.
@@ -2585,6 +2643,7 @@ class ParserTestCase extends EngineTestCase {
// Parse the source.
//
Parser parser = createParser(listener);
parser.parseGenericMethods = enableGenericMethods;
parser.parseFunctionBodies = parseFunctionBodies;
Object result =
invokeParserMethodImpl(parser, methodName, objects, tokenStream);
@@ -2718,6 +2777,7 @@ class ParserTestCase extends EngineTestCase {
listener.setLineInfo(new TestSource(), scanner.lineStarts);
Token token = scanner.tokenize();
Parser parser = createParser(listener);
parser.parseGenericMethods = enableGenericMethods;
Expression expression = parser.parseExpression(token);
expect(expression, isNotNull);
listener.assertErrorsWithCodes(errorCodes);
@@ -4654,6 +4714,16 @@ class SimpleParserTest extends ParserTestCase {
expect(_isFunctionDeclaration("f() => e"), isTrue);
}
void test_isFunctionDeclaration_nameButNoReturn_typeParameters_block() {
enableGenericMethods = true;
expect(_isFunctionDeclaration("f<E>() {}"), isTrue);
}
void test_isFunctionDeclaration_nameButNoReturn_typeParameters_expression() {
enableGenericMethods = true;
expect(_isFunctionDeclaration("f<E>() => e"), isTrue);
}
void test_isFunctionDeclaration_normalReturn_block() {
expect(_isFunctionDeclaration("C f() {}"), isTrue);
}
@@ -4662,6 +4732,16 @@ class SimpleParserTest extends ParserTestCase {
expect(_isFunctionDeclaration("C f() => e"), isTrue);
}
void test_isFunctionDeclaration_normalReturn_typeParameters_block() {
enableGenericMethods = true;
expect(_isFunctionDeclaration("C f<E>() {}"), isTrue);
}
void test_isFunctionDeclaration_normalReturn_typeParameters_expression() {
enableGenericMethods = true;
expect(_isFunctionDeclaration("C f<E>() => e"), isTrue);
}
void test_isFunctionDeclaration_voidReturn_block() {
expect(_isFunctionDeclaration("void f() {}"), isTrue);
}
@@ -4670,6 +4750,16 @@ class SimpleParserTest extends ParserTestCase {
expect(_isFunctionDeclaration("void f() => e"), isTrue);
}
void test_isFunctionDeclaration_voidReturn_typeParameters_block() {
enableGenericMethods = true;
expect(_isFunctionDeclaration("void f<E>() {}"), isTrue);
}
void test_isFunctionDeclaration_voidReturn_typeParameters_expression() {
enableGenericMethods = true;
expect(_isFunctionDeclaration("void f<E>() => e"), isTrue);
}
void test_isFunctionExpression_false_noBody() {
expect(_isFunctionExpression("f();"), isFalse);
}
@@ -4678,14 +4768,24 @@ class SimpleParserTest extends ParserTestCase {
expect(_isFunctionExpression("(a + b) {"), isFalse);
}
void test_isFunctionExpression_noName_block() {
void test_isFunctionExpression_noParameters_block() {
expect(_isFunctionExpression("() {}"), isTrue);
}
void test_isFunctionExpression_noName_expression() {
void test_isFunctionExpression_noParameters_expression() {
expect(_isFunctionExpression("() => e"), isTrue);
}
void test_isFunctionExpression_noParameters_typeParameters_block() {
enableGenericMethods = true;
expect(_isFunctionExpression("<E>() {}"), isTrue);
}
void test_isFunctionExpression_noParameters_typeParameters_expression() {
enableGenericMethods = true;
expect(_isFunctionExpression("<E>() => e"), isTrue);
}
void test_isFunctionExpression_parameter_final() {
expect(_isFunctionExpression("(final a) {}"), isTrue);
expect(_isFunctionExpression("(final a, b) {}"), isTrue);
@@ -4935,6 +5035,22 @@ class SimpleParserTest extends ParserTestCase {
FunctionExpressionInvocation invocation =
propertyAccess.target as FunctionExpressionInvocation;
expect(invocation.function, isNotNull);
expect(invocation.typeArguments, isNull);
ArgumentList argumentList = invocation.argumentList;
expect(argumentList, isNotNull);
expect(argumentList.arguments, hasLength(1));
expect(propertyAccess.operator, isNotNull);
expect(propertyAccess.propertyName, isNotNull);
}
void test_parseAssignableExpression_expression_args_dot_typeParameters() {
enableGenericMethods = true;
PropertyAccess propertyAccess =
parse("parseAssignableExpression", <Object>[false], "(x)<F>(y).z");
FunctionExpressionInvocation invocation =
propertyAccess.target as FunctionExpressionInvocation;
expect(invocation.function, isNotNull);
expect(invocation.typeArguments, isNotNull);
ArgumentList argumentList = invocation.argumentList;
expect(argumentList, isNotNull);
expect(argumentList.arguments, hasLength(1));
@@ -4979,6 +5095,21 @@ class SimpleParserTest extends ParserTestCase {
parse("parseAssignableExpression", <Object>[false], "x(y).z");
MethodInvocation invocation = propertyAccess.target as MethodInvocation;
expect(invocation.methodName.name, "x");
expect(invocation.typeArguments, isNull);
ArgumentList argumentList = invocation.argumentList;
expect(argumentList, isNotNull);
expect(argumentList.arguments, hasLength(1));
expect(propertyAccess.operator, isNotNull);
expect(propertyAccess.propertyName, isNotNull);
}
void test_parseAssignableExpression_identifier_args_dot_typeParameters() {
enableGenericMethods = true;
PropertyAccess propertyAccess =
parse("parseAssignableExpression", <Object>[false], "x<E>(y).z");
MethodInvocation invocation = propertyAccess.target as MethodInvocation;
expect(invocation.methodName.name, "x");
expect(invocation.typeArguments, isNotNull);
ArgumentList argumentList = invocation.argumentList;
expect(argumentList, isNotNull);
expect(argumentList.arguments, hasLength(1));
@@ -5193,6 +5324,17 @@ class SimpleParserTest extends ParserTestCase {
parse4("parseCascadeSection", "..[i](b)");
EngineTestCase.assertInstanceOf(
(obj) => obj is IndexExpression, IndexExpression, section.function);
expect(section.typeArguments, isNull);
expect(section.argumentList, isNotNull);
}
void test_parseCascadeSection_ia_typeArguments() {
enableGenericMethods = true;
FunctionExpressionInvocation section =
parse4("parseCascadeSection", "..[i]<E>(b)");
EngineTestCase.assertInstanceOf(
(obj) => obj is IndexExpression, IndexExpression, section.function);
expect(section.typeArguments, isNotNull);
expect(section.argumentList, isNotNull);
}
@@ -5202,6 +5344,20 @@ class SimpleParserTest extends ParserTestCase {
(obj) => obj is MethodInvocation, MethodInvocation, section.target);
expect(section.operator, isNotNull);
expect(section.methodName, isNotNull);
expect(section.typeArguments, isNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
void test_parseCascadeSection_ii_typeArguments() {
enableGenericMethods = true;
MethodInvocation section =
parse4("parseCascadeSection", "..a<E>(b).c<F>(d)");
EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation, section.target);
expect(section.operator, isNotNull);
expect(section.methodName, isNotNull);
expect(section.typeArguments, isNotNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
@@ -5231,6 +5387,17 @@ class SimpleParserTest extends ParserTestCase {
(obj) => obj is IntegerLiteral, IntegerLiteral, rhs);
}
void test_parseCascadeSection_p_assign_withCascade_typeArguments() {
enableGenericMethods = true;
AssignmentExpression section =
parse4("parseCascadeSection", "..a = 3..m<E>()");
expect(section.leftHandSide, isNotNull);
expect(section.operator, isNotNull);
Expression rhs = section.rightHandSide;
EngineTestCase.assertInstanceOf(
(obj) => obj is IntegerLiteral, IntegerLiteral, rhs);
}
void test_parseCascadeSection_p_builtIn() {
PropertyAccess section = parse4("parseCascadeSection", "..as");
expect(section.target, isNull);
@@ -5243,6 +5410,18 @@ class SimpleParserTest extends ParserTestCase {
expect(section.target, isNull);
expect(section.operator, isNotNull);
expect(section.methodName, isNotNull);
expect(section.typeArguments, isNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
void test_parseCascadeSection_pa_typeArguments() {
enableGenericMethods = true;
MethodInvocation section = parse4("parseCascadeSection", "..a<E>(b)");
expect(section.target, isNull);
expect(section.operator, isNotNull);
expect(section.methodName, isNotNull);
expect(section.typeArguments, isNotNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
@@ -5252,6 +5431,18 @@ class SimpleParserTest extends ParserTestCase {
parse4("parseCascadeSection", "..a(b)(c)");
EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation, section.function);
expect(section.typeArguments, isNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
void test_parseCascadeSection_paa_typeArguments() {
enableGenericMethods = true;
FunctionExpressionInvocation section =
parse4("parseCascadeSection", "..a<E>(b)<F>(c)");
EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation, section.function);
expect(section.typeArguments, isNotNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
@@ -5261,6 +5452,18 @@ class SimpleParserTest extends ParserTestCase {
parse4("parseCascadeSection", "..a(b)(c).d(e)(f)");
EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation, section.function);
expect(section.typeArguments, isNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
void test_parseCascadeSection_paapaa_typeArguments() {
enableGenericMethods = true;
FunctionExpressionInvocation section =
parse4("parseCascadeSection", "..a<E>(b)<F>(c).d<G>(e)<H>(f)");
EngineTestCase.assertInstanceOf(
(obj) => obj is MethodInvocation, MethodInvocation, section.function);
expect(section.typeArguments, isNotNull);
expect(section.argumentList, isNotNull);
expect(section.argumentList.arguments, hasLength(1));
}
@@ -5272,6 +5475,14 @@ class SimpleParserTest extends ParserTestCase {
expect(section.propertyName, isNotNull);
}
void test_parseCascadeSection_pap_typeArguments() {
enableGenericMethods = true;
PropertyAccess section = parse4("parseCascadeSection", "..a<E>(b).c");
expect(section.target, isNotNull);
expect(section.operator, isNotNull);
expect(section.propertyName, isNotNull);
}
void test_parseClassDeclaration_abstract() {
ClassDeclaration declaration = parse("parseClassDeclaration", <Object>[
emptyCommentAndMetadata(),
@@ -5581,6 +5792,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.modifierKeyword, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.propertyKeyword, isNull);
expect(method.returnType, isNull);
@@ -5595,11 +5807,60 @@ class SimpleParserTest extends ParserTestCase {
expect(method.modifierKeyword, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.propertyKeyword, isNull);
expect(method.returnType, isNotNull);
}
void test_parseClassMember_method_generic_noReturnType() {
enableGenericMethods = true;
MethodDeclaration method =
parse("parseClassMember", <Object>["C"], "m<T>() {}");
expect(method.documentationComment, isNull);
expect(method.externalKeyword, isNull);
expect(method.modifierKeyword, isNull);
expect(method.propertyKeyword, isNull);
expect(method.returnType, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNotNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
void test_parseClassMember_method_generic_returnType() {
enableGenericMethods = true;
MethodDeclaration method =
parse("parseClassMember", <Object>["C"], "T m<T>() {}");
expect(method.documentationComment, isNull);
expect(method.externalKeyword, isNull);
expect(method.modifierKeyword, isNull);
expect(method.propertyKeyword, isNull);
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNotNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
void test_parseClassMember_method_generic_void() {
enableGenericMethods = true;
MethodDeclaration method =
parse("parseClassMember", <Object>["C"], "void m<T>() {}");
expect(method.documentationComment, isNull);
expect(method.externalKeyword, isNull);
expect(method.modifierKeyword, isNull);
expect(method.propertyKeyword, isNull);
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNotNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
void test_parseClassMember_method_get_noType() {
MethodDeclaration method =
parse("parseClassMember", <Object>["C"], "get() {}");
@@ -5610,6 +5871,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5624,6 +5886,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5638,6 +5901,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5652,6 +5916,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5666,6 +5931,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5680,6 +5946,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5694,6 +5961,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5708,6 +5976,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5722,6 +5991,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5736,6 +6006,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5750,6 +6021,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNotNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -5764,6 +6036,7 @@ class SimpleParserTest extends ParserTestCase {
expect(method.returnType, isNotNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNotNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.body, isNotNull);
}
@@ -6978,6 +7251,7 @@ void''');
FunctionExpression expression = invocation.function as FunctionExpression;
expect(expression.parameters, isNotNull);
expect(expression.body, isNotNull);
expect(invocation.typeArguments, isNull);
ArgumentList list = invocation.argumentList;
expect(list, isNotNull);
expect(list.arguments, hasLength(1));
@@ -6986,12 +7260,24 @@ void''');
void test_parseExpression_nonAwait() {
MethodInvocation expression = parseExpression("await()");
expect(expression.methodName.name, 'await');
expect(expression.typeArguments, isNull);
expect(expression.argumentList, isNotNull);
}
void test_parseExpression_superMethodInvocation() {
MethodInvocation invocation = parse4("parseExpression", "super.m()");
expect(invocation.target, isNotNull);
expect(invocation.methodName, isNotNull);
expect(invocation.typeArguments, isNull);
expect(invocation.argumentList, isNotNull);
}
void test_parseExpression_superMethodInvocation_typeArguments() {
enableGenericMethods = true;
MethodInvocation invocation = parse4("parseExpression", "super.m<E>()");
expect(invocation.target, isNotNull);
expect(invocation.methodName, isNotNull);
expect(invocation.typeArguments, isNotNull);
expect(invocation.argumentList, isNotNull);
}
@@ -7029,6 +7315,17 @@ void''');
parse4("parseExpressionWithoutCascade", "super.m()");
expect(invocation.target, isNotNull);
expect(invocation.methodName, isNotNull);
expect(invocation.typeArguments, isNull);
expect(invocation.argumentList, isNotNull);
}
void test_parseExpressionWithoutCascade_superMethodInvocation_typeArguments() {
enableGenericMethods = true;
MethodInvocation invocation =
parse4("parseExpressionWithoutCascade", "super.m<E>()");
expect(invocation.target, isNotNull);
expect(invocation.methodName, isNotNull);
expect(invocation.typeArguments, isNotNull);
expect(invocation.argumentList, isNotNull);
}
@@ -7765,6 +8062,24 @@ void''');
FunctionExpression expression = declaration.functionExpression;
expect(expression, isNotNull);
expect(expression.body, isNotNull);
expect(expression.typeParameters, isNull);
expect(expression.parameters, isNotNull);
expect(declaration.propertyKeyword, isNull);
}
void test_parseFunctionDeclaration_functionWithTypeParameters() {
enableGenericMethods = true;
Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName(new SimpleIdentifier(null), null);
FunctionDeclaration declaration = parse("parseFunctionDeclaration",
<Object>[commentAndMetadata(comment), null, returnType], "f<E>() {}");
expect(declaration.documentationComment, comment);
expect(declaration.returnType, returnType);
expect(declaration.name, isNotNull);
FunctionExpression expression = declaration.functionExpression;
expect(expression, isNotNull);
expect(expression.body, isNotNull);
expect(expression.typeParameters, isNotNull);
expect(expression.parameters, isNotNull);
expect(declaration.propertyKeyword, isNull);
}
@@ -7780,6 +8095,7 @@ void''');
FunctionExpression expression = declaration.functionExpression;
expect(expression, isNotNull);
expect(expression.body, isNotNull);
expect(expression.typeParameters, isNull);
expect(expression.parameters, isNull);
expect(declaration.propertyKeyword, isNotNull);
}
@@ -7795,6 +8111,7 @@ void''');
FunctionExpression expression = declaration.functionExpression;
expect(expression, isNotNull);
expect(expression.body, isNotNull);
expect(expression.typeParameters, isNull);
expect(expression.parameters, isNotNull);
expect(declaration.propertyKeyword, isNotNull);
}
@@ -7805,10 +8122,28 @@ void''');
expect(statement.functionDeclaration, isNotNull);
}
void test_parseFunctionDeclarationStatement_typeParameters() {
enableGenericMethods = true;
FunctionDeclarationStatement statement =
parse4("parseFunctionDeclarationStatement", "E f<E>(E p) => p * 2;");
expect(statement.functionDeclaration, isNotNull);
}
void test_parseFunctionExpression_body_inExpression() {
FunctionExpression expression =
parse4("parseFunctionExpression", "(int i) => i++");
expect(expression.body, isNotNull);
expect(expression.typeParameters, isNull);
expect(expression.parameters, isNotNull);
expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
}
void test_parseFunctionExpression_typeParameters() {
enableGenericMethods = true;
FunctionExpression expression =
parse4("parseFunctionExpression", "<E>(E i) => i++");
expect(expression.body, isNotNull);
expect(expression.typeParameters, isNotNull);
expect(expression.parameters, isNotNull);
expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
}
@@ -7849,6 +8184,7 @@ void''');
expect(method.modifierKeyword, staticKeyword);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNull);
expect(method.propertyKeyword, isNotNull);
expect(method.returnType, returnType);
@@ -8433,6 +8769,7 @@ void''');
FunctionExpression expression = invocation.function as FunctionExpression;
expect(expression.parameters, isNotNull);
expect(expression.body, isNotNull);
expect(invocation.typeArguments, isNull);
ArgumentList list = invocation.argumentList;
expect(list, isNotNull);
expect(list.arguments, hasLength(1));
@@ -8550,6 +8887,17 @@ void''');
parse4("parseNormalFormalParameter", "a())");
expect(parameter.returnType, isNull);
expect(parameter.identifier, isNotNull);
expect(parameter.typeParameters, isNull);
expect(parameter.parameters, isNotNull);
}
void test_parseNormalFormalParameter_function_noType_typeParameters() {
enableGenericMethods = true;
FunctionTypedFormalParameter parameter =
parse4("parseNormalFormalParameter", "a<E>())");
expect(parameter.returnType, isNull);
expect(parameter.identifier, isNotNull);
expect(parameter.typeParameters, isNotNull);
expect(parameter.parameters, isNotNull);
}
@@ -8558,6 +8906,17 @@ void''');
parse4("parseNormalFormalParameter", "A a())");
expect(parameter.returnType, isNotNull);
expect(parameter.identifier, isNotNull);
expect(parameter.typeParameters, isNull);
expect(parameter.parameters, isNotNull);
}
void test_parseNormalFormalParameter_function_type_typeParameters() {
enableGenericMethods = true;
FunctionTypedFormalParameter parameter =
parse4("parseNormalFormalParameter", "A a<E>())");
expect(parameter.returnType, isNotNull);
expect(parameter.identifier, isNotNull);
expect(parameter.typeParameters, isNotNull);
expect(parameter.parameters, isNotNull);
}
@@ -8566,6 +8925,17 @@ void''');
parse4("parseNormalFormalParameter", "void a())");
expect(parameter.returnType, isNotNull);
expect(parameter.identifier, isNotNull);
expect(parameter.typeParameters, isNull);
expect(parameter.parameters, isNotNull);
}
void test_parseNormalFormalParameter_function_void_typeParameters() {
enableGenericMethods = true;
FunctionTypedFormalParameter parameter =
parse4("parseNormalFormalParameter", "void a<E>())");
expect(parameter.returnType, isNotNull);
expect(parameter.identifier, isNotNull);
expect(parameter.typeParameters, isNotNull);
expect(parameter.parameters, isNotNull);
}
@@ -8631,6 +9001,7 @@ void''');
expect(method.modifierKeyword, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNotNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.propertyKeyword, isNull);
expect(method.returnType, returnType);
@@ -8682,6 +9053,7 @@ void''');
expect(expression.target, isNotNull);
expect(expression.operator.type, TokenType.PERIOD);
expect(expression.methodName, isNotNull);
expect(expression.typeArguments, isNull);
expect(expression.argumentList, isNotNull);
}
@@ -8691,6 +9063,28 @@ void''');
expect(expression.target, isNotNull);
expect(expression.operator.type, TokenType.QUESTION_PERIOD);
expect(expression.methodName, isNotNull);
expect(expression.typeArguments, isNull);
expect(expression.argumentList, isNotNull);
}
void test_parsePostfixExpression_none_methodInvocation_question_dot_typeArguments() {
enableGenericMethods = true;
_enableNullAwareOperators = true;
MethodInvocation expression = parse4('parsePostfixExpression', 'a?.m<E>()');
expect(expression.target, isNotNull);
expect(expression.operator.type, TokenType.QUESTION_PERIOD);
expect(expression.methodName, isNotNull);
expect(expression.typeArguments, isNotNull);
expect(expression.argumentList, isNotNull);
}
void test_parsePostfixExpression_none_methodInvocation_typeArguments() {
enableGenericMethods = true;
MethodInvocation expression = parse4("parsePostfixExpression", "a.m<E>()");
expect(expression.target, isNotNull);
expect(expression.operator.type, TokenType.PERIOD);
expect(expression.methodName, isNotNull);
expect(expression.typeArguments, isNotNull);
expect(expression.argumentList, isNotNull);
}
@@ -8961,6 +9355,7 @@ void''');
expect(method.modifierKeyword, isNull);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.propertyKeyword, isNotNull);
expect(method.returnType, returnType);
@@ -8982,6 +9377,7 @@ void''');
expect(method.modifierKeyword, staticKeyword);
expect(method.name, isNotNull);
expect(method.operatorKeyword, isNull);
expect(method.typeParameters, isNull);
expect(method.parameters, isNotNull);
expect(method.propertyKeyword, isNotNull);
expect(method.returnType, returnType);
@@ -9033,13 +9429,33 @@ void''');
expect(argumentList.rightBracket, isNotNull);
}
void test_parseStatement_functionDeclaration() {
void test_parseStatement_functionDeclaration_noReturnType() {
FunctionDeclarationStatement statement =
parse4("parseStatement", "f(a, b) {};");
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_functionDeclaration_noReturnType_typeParameters() {
enableGenericMethods = true;
FunctionDeclarationStatement statement =
parse4("parseStatement", "f(a, b) {};");
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_functionDeclaration_returnType() {
// TODO(brianwilkerson) Implement more tests for this method.
FunctionDeclarationStatement statement =
parse4("parseStatement", "int f(a, b) {};");
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_functionDeclaration_returnType_typeParameters() {
enableGenericMethods = true;
FunctionDeclarationStatement statement =
parse4("parseStatement", "int f<E>(a, b) {};");
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_mulipleLabels() {
LabeledStatement statement = parse4("parseStatement", "l: m: return x;");
expect(statement.labels, hasLength(2));