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

Side by Side Diff: pkg/analyzer/lib/src/generated/parser.dart

Issue 1434863003: initial generic method comment parsing (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: re-sort members Created 5 years, 1 month 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 unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/scanner.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library engine.parser; 5 library engine.parser;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import "dart:math" as math; 8 import "dart:math" as math;
9 9
10 import 'ast.dart'; 10 import 'ast.dart';
(...skipping 2105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 * initializer, with no intervening parens, braces, or brackets. 2116 * initializer, with no intervening parens, braces, or brackets.
2117 */ 2117 */
2118 bool _inInitializer = false; 2118 bool _inInitializer = false;
2119 2119
2120 /** 2120 /**
2121 * A flag indicating whether the parser is to parse generic method syntax. 2121 * A flag indicating whether the parser is to parse generic method syntax.
2122 */ 2122 */
2123 bool parseGenericMethods = false; 2123 bool parseGenericMethods = false;
2124 2124
2125 /** 2125 /**
2126 * A flag indicating whether to parse generic method comments, of the form
2127 * `/*=T*/` and `/*<T>*/`.
2128 */
2129 bool parseGenericMethodComments = false;
2130
2131 /**
2126 * Initialize a newly created parser to parse the content of the given 2132 * Initialize a newly created parser to parse the content of the given
2127 * [_source] and to report any errors that are found to the given 2133 * [_source] and to report any errors that are found to the given
2128 * [_errorListener]. 2134 * [_errorListener].
2129 */ 2135 */
2130 Parser(this._source, this._errorListener); 2136 Parser(this._source, this._errorListener);
2131 2137
2132 void set currentToken(Token currentToken) { 2138 void set currentToken(Token currentToken) {
2133 this._currentToken = currentToken; 2139 this._currentToken = currentToken;
2134 } 2140 }
2135 2141
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
2507 return _parseConstructor( 2513 return _parseConstructor(
2508 commentAndMetadata, 2514 commentAndMetadata,
2509 modifiers.externalKeyword, 2515 modifiers.externalKeyword,
2510 _validateModifiersForConstructor(modifiers), 2516 _validateModifiersForConstructor(modifiers),
2511 modifiers.factoryKeyword, 2517 modifiers.factoryKeyword,
2512 parseSimpleIdentifier(), 2518 parseSimpleIdentifier(),
2513 getAndAdvance(), 2519 getAndAdvance(),
2514 parseSimpleIdentifier(), 2520 parseSimpleIdentifier(),
2515 parseFormalParameterList()); 2521 parseFormalParameterList());
2516 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 2522 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2523 TypeName returnType = _parseOptionalTypeNameComment();
2517 SimpleIdentifier methodName = parseSimpleIdentifier(); 2524 SimpleIdentifier methodName = parseSimpleIdentifier();
2525 TypeParameterList typeParameters = _parseGenericCommentTypeParameters();
2518 FormalParameterList parameters = parseFormalParameterList(); 2526 FormalParameterList parameters = parseFormalParameterList();
2519 if (_matches(TokenType.COLON) || 2527 if (_matches(TokenType.COLON) ||
2520 modifiers.factoryKeyword != null || 2528 modifiers.factoryKeyword != null ||
2521 methodName.name == className) { 2529 methodName.name == className) {
2522 return _parseConstructor( 2530 return _parseConstructor(
2523 commentAndMetadata, 2531 commentAndMetadata,
2524 modifiers.externalKeyword, 2532 modifiers.externalKeyword,
2525 _validateModifiersForConstructor(modifiers), 2533 _validateModifiersForConstructor(modifiers),
2526 modifiers.factoryKeyword, 2534 modifiers.factoryKeyword,
2527 methodName, 2535 methodName,
2528 null, 2536 null,
2529 null, 2537 null,
2530 parameters); 2538 parameters);
2531 } 2539 }
2532 _validateModifiersForGetterOrSetterOrMethod(modifiers); 2540 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2533 _validateFormalParameterList(parameters); 2541 _validateFormalParameterList(parameters);
2534 return _parseMethodDeclarationAfterParameters( 2542 return _parseMethodDeclarationAfterParameters(
2535 commentAndMetadata, 2543 commentAndMetadata,
2536 modifiers.externalKeyword, 2544 modifiers.externalKeyword,
2537 modifiers.staticKeyword, 2545 modifiers.staticKeyword,
2538 null, 2546 returnType,
2539 methodName, 2547 methodName,
2540 null, 2548 typeParameters,
2541 parameters); 2549 parameters);
2542 } else if (_peek() 2550 } else if (_peek()
2543 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) { 2551 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
2544 if (modifiers.constKeyword == null && 2552 if (modifiers.constKeyword == null &&
2545 modifiers.finalKeyword == null && 2553 modifiers.finalKeyword == null &&
2546 modifiers.varKeyword == null) { 2554 modifiers.varKeyword == null) {
2547 _reportErrorForCurrentToken( 2555 _reportErrorForCurrentToken(
2548 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); 2556 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
2549 } 2557 }
2550 return _parseInitializedIdentifierList(commentAndMetadata, 2558 return _parseInitializedIdentifierList(commentAndMetadata,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 return _parseInitializedIdentifierList( 2618 return _parseInitializedIdentifierList(
2611 commentAndMetadata, 2619 commentAndMetadata,
2612 modifiers.staticKeyword, 2620 modifiers.staticKeyword,
2613 _validateModifiersForField(modifiers), 2621 _validateModifiersForField(modifiers),
2614 type); 2622 type);
2615 } finally { 2623 } finally {
2616 _unlockErrorListener(); 2624 _unlockErrorListener();
2617 } 2625 }
2618 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 2626 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2619 SimpleIdentifier methodName = parseSimpleIdentifier(); 2627 SimpleIdentifier methodName = parseSimpleIdentifier();
2628 TypeParameterList typeParameters = _parseGenericCommentTypeParameters();
2620 FormalParameterList parameters = parseFormalParameterList(); 2629 FormalParameterList parameters = parseFormalParameterList();
2621 if (methodName.name == className) { 2630 if (methodName.name == className) {
2622 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type); 2631 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
2623 return _parseConstructor( 2632 return _parseConstructor(
2624 commentAndMetadata, 2633 commentAndMetadata,
2625 modifiers.externalKeyword, 2634 modifiers.externalKeyword,
2626 _validateModifiersForConstructor(modifiers), 2635 _validateModifiersForConstructor(modifiers),
2627 modifiers.factoryKeyword, 2636 modifiers.factoryKeyword,
2628 methodName, 2637 methodName,
2629 null, 2638 null,
2630 null, 2639 null,
2631 parameters); 2640 parameters);
2632 } 2641 }
2633 _validateModifiersForGetterOrSetterOrMethod(modifiers); 2642 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2634 _validateFormalParameterList(parameters); 2643 _validateFormalParameterList(parameters);
2635 return _parseMethodDeclarationAfterParameters( 2644 return _parseMethodDeclarationAfterParameters(
2636 commentAndMetadata, 2645 commentAndMetadata,
2637 modifiers.externalKeyword, 2646 modifiers.externalKeyword,
2638 modifiers.staticKeyword, 2647 modifiers.staticKeyword,
2639 type, 2648 type,
2640 methodName, 2649 methodName,
2641 null, 2650 typeParameters,
2642 parameters); 2651 parameters);
2643 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) { 2652 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) {
2644 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, 2653 return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
2645 modifiers.externalKeyword, modifiers.staticKeyword, type); 2654 modifiers.externalKeyword, modifiers.staticKeyword, type);
2646 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) { 2655 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) {
2647 // We have found "TypeName identifier {", and are guessing that this is a 2656 // We have found "TypeName identifier {", and are guessing that this is a
2648 // getter without the keyword 'get'. 2657 // getter without the keyword 'get'.
2649 _validateModifiersForGetterOrSetterOrMethod(modifiers); 2658 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2650 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET); 2659 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET);
2651 _currentToken = _injectToken( 2660 _currentToken = _injectToken(
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
3128 } 3137 }
3129 3138
3130 /** 3139 /**
3131 * Parse a function expression. Return the function expression that was 3140 * Parse a function expression. Return the function expression that was
3132 * parsed. 3141 * parsed.
3133 * 3142 *
3134 * functionExpression ::= 3143 * functionExpression ::=
3135 * typeParameters? formalParameterList functionExpressionBody 3144 * typeParameters? formalParameterList functionExpressionBody
3136 */ 3145 */
3137 FunctionExpression parseFunctionExpression() { 3146 FunctionExpression parseFunctionExpression() {
3138 TypeParameterList typeParameters = null; 3147 TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
3139 if (parseGenericMethods && _matches(TokenType.LT)) {
3140 typeParameters = parseTypeParameterList();
3141 }
3142 FormalParameterList parameters = parseFormalParameterList(); 3148 FormalParameterList parameters = parseFormalParameterList();
3143 _validateFormalParameterList(parameters); 3149 _validateFormalParameterList(parameters);
3144 FunctionBody body = 3150 FunctionBody body =
3145 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true); 3151 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
3146 return new FunctionExpression(typeParameters, parameters, body); 3152 return new FunctionExpression(typeParameters, parameters, body);
3147 } 3153 }
3148 3154
3149 /** 3155 /**
3150 * Parse an if-null expression. Return the if-null expression that was 3156 * Parse an if-null expression. Return the if-null expression that was
3151 * parsed. 3157 * parsed.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3258 NormalFormalParameter parseNormalFormalParameter() { 3264 NormalFormalParameter parseNormalFormalParameter() {
3259 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 3265 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
3260 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); 3266 FinalConstVarOrType holder = _parseFinalConstVarOrType(true);
3261 Token thisKeyword = null; 3267 Token thisKeyword = null;
3262 Token period = null; 3268 Token period = null;
3263 if (_matchesKeyword(Keyword.THIS)) { 3269 if (_matchesKeyword(Keyword.THIS)) {
3264 thisKeyword = getAndAdvance(); 3270 thisKeyword = getAndAdvance();
3265 period = _expect(TokenType.PERIOD); 3271 period = _expect(TokenType.PERIOD);
3266 } 3272 }
3267 SimpleIdentifier identifier = parseSimpleIdentifier(); 3273 SimpleIdentifier identifier = parseSimpleIdentifier();
3268 TypeParameterList typeParameters = null; 3274 TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
3269 if (parseGenericMethods && _matches(TokenType.LT)) {
3270 typeParameters = parseTypeParameterList();
3271 }
3272 if (_matches(TokenType.OPEN_PAREN)) { 3275 if (_matches(TokenType.OPEN_PAREN)) {
3273 FormalParameterList parameters = parseFormalParameterList(); 3276 FormalParameterList parameters = parseFormalParameterList();
3274 if (thisKeyword == null) { 3277 if (thisKeyword == null) {
3275 if (holder.keyword != null) { 3278 if (holder.keyword != null) {
3276 _reportErrorForToken( 3279 _reportErrorForToken(
3277 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); 3280 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
3278 } 3281 }
3279 return new FunctionTypedFormalParameter( 3282 return new FunctionTypedFormalParameter(
3280 commentAndMetadata.comment, 3283 commentAndMetadata.comment,
3281 commentAndMetadata.metadata, 3284 commentAndMetadata.metadata,
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
3469 return new TypeArgumentList(leftBracket, arguments, rightBracket); 3472 return new TypeArgumentList(leftBracket, arguments, rightBracket);
3470 } 3473 }
3471 3474
3472 /** 3475 /**
3473 * Parse a type name. Return the type name that was parsed. 3476 * Parse a type name. Return the type name that was parsed.
3474 * 3477 *
3475 * type ::= 3478 * type ::=
3476 * qualified typeArguments? 3479 * qualified typeArguments?
3477 */ 3480 */
3478 TypeName parseTypeName() { 3481 TypeName parseTypeName() {
3479 Identifier typeName; 3482 TypeName realType = _parseTypeName();
3480 if (_matchesKeyword(Keyword.VAR)) { 3483 // If this is followed by a generic method type comment, allow the comment
3481 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); 3484 // type to replace the real type name.
3482 typeName = new SimpleIdentifier(getAndAdvance()); 3485 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to
3483 } else if (_matchesIdentifier()) { 3486 // only work inside generic methods?
3484 typeName = parsePrefixedIdentifier(); 3487 TypeName typeComment = _parseOptionalTypeNameComment();
3485 } else { 3488 return typeComment ?? realType;
3486 typeName = _createSyntheticIdentifier();
3487 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
3488 }
3489 TypeArgumentList typeArguments = null;
3490 if (_matches(TokenType.LT)) {
3491 typeArguments = parseTypeArgumentList();
3492 }
3493 return new TypeName(typeName, typeArguments);
3494 } 3489 }
3495 3490
3496 /** 3491 /**
3497 * Parse a type parameter. Return the type parameter that was parsed. 3492 * Parse a type parameter. Return the type parameter that was parsed.
3498 * 3493 *
3499 * typeParameter ::= 3494 * typeParameter ::=
3500 * metadata name ('extends' bound)? 3495 * metadata name ('extends' bound)?
3501 */ 3496 */
3502 TypeParameter parseTypeParameter() { 3497 TypeParameter parseTypeParameter() {
3503 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 3498 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
3902 * either the given token is not a begin token or it does not have an end 3897 * either the given token is not a begin token or it does not have an end
3903 * token associated with it. 3898 * token associated with it.
3904 */ 3899 */
3905 Token _getEndToken(Token beginToken) { 3900 Token _getEndToken(Token beginToken) {
3906 if (beginToken is BeginToken) { 3901 if (beginToken is BeginToken) {
3907 return beginToken.endToken; 3902 return beginToken.endToken;
3908 } 3903 }
3909 return null; 3904 return null;
3910 } 3905 }
3911 3906
3907 bool _injectGenericComment(TokenType type, int prefixLen) {
3908 if (parseGenericMethodComments) {
3909 CommentToken t = _currentToken.precedingComments;
3910 for (; t != null; t = t.next) {
3911 if (t.type == type) {
3912 String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2);
3913 Token list = _scanGenericMethodComment(comment, t.offset + prefixLen);
3914 if (list != null) {
3915 // Insert the tokens into the stream.
3916 _injectTokenList(list);
3917 return true;
3918 }
3919 }
3920 }
3921 }
3922 return false;
3923 }
3924
3925 /**
3926 * Matches a generic comment type substitution and injects it into the token
3927 * stream. Returns true if a match was injected, otherwise false.
3928 *
3929 * These comments are of the form `/*=T*/`, in other words, a [TypeName]
3930 * inside a slash-star comment, preceded by equals sign.
3931 */
3932 bool _injectGenericCommentTypeAssign() {
3933 return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_ASSIGN, 3);
3934 }
3935
3936 /**
3937 * Matches a generic comment type parameters and injects them into the token
3938 * stream. Returns true if a match was injected, otherwise false.
3939 *
3940 * These comments are of the form `/*<K, V>*/`, in other words, a
3941 * [TypeParameterList] or [TypeArgumentList] inside a slash-star comment.
3942 */
3943 bool _injectGenericCommentTypeList() {
3944 return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_LIST, 2);
3945 }
3946
3912 /** 3947 /**
3913 * Inject the given [token] into the token stream immediately before the 3948 * Inject the given [token] into the token stream immediately before the
3914 * current token. 3949 * current token.
3915 */ 3950 */
3916 Token _injectToken(Token token) { 3951 Token _injectToken(Token token) {
3917 Token previous = _currentToken.previous; 3952 Token previous = _currentToken.previous;
3918 token.setNext(_currentToken); 3953 token.setNext(_currentToken);
3919 previous.setNext(token); 3954 previous.setNext(token);
3920 return token; 3955 return token;
3921 } 3956 }
3922 3957
3958 void _injectTokenList(Token firstToken) {
3959 // Scanner creates a cyclic EOF token.
3960 Token lastToken = firstToken;
3961 while (lastToken.next.type != TokenType.EOF) {
3962 lastToken = lastToken.next;
3963 }
3964 // Inject these new tokens into the stream.
3965 Token previous = _currentToken.previous;
3966 lastToken.setNext(_currentToken);
3967 previous.setNext(firstToken);
3968 _currentToken = firstToken;
3969 }
3970
3923 /** 3971 /**
3924 * Return `true` if the current token appears to be the beginning of a 3972 * Return `true` if the current token appears to be the beginning of a
3925 * function declaration. 3973 * function declaration.
3926 */ 3974 */
3927 bool _isFunctionDeclaration() { 3975 bool _isFunctionDeclaration() {
3928 if (_matchesKeyword(Keyword.VOID)) { 3976 if (_matchesKeyword(Keyword.VOID)) {
3929 return true; 3977 return true;
3930 } 3978 }
3931 Token afterReturnType = _skipTypeName(_currentToken); 3979 Token afterReturnType = _skipTypeName(_currentToken);
3932 if (afterReturnType == null) { 3980 if (afterReturnType == null) {
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
4354 } 4402 }
4355 // 4403 //
4356 // A primary expression can start with an identifier. We resolve the 4404 // A primary expression can start with an identifier. We resolve the
4357 // ambiguity by determining whether the primary consists of anything other 4405 // ambiguity by determining whether the primary consists of anything other
4358 // than an identifier and/or is followed by an assignableSelector. 4406 // than an identifier and/or is followed by an assignableSelector.
4359 // 4407 //
4360 Expression expression = _parsePrimaryExpression(); 4408 Expression expression = _parsePrimaryExpression();
4361 bool isOptional = primaryAllowed || expression is SimpleIdentifier; 4409 bool isOptional = primaryAllowed || expression is SimpleIdentifier;
4362 while (true) { 4410 while (true) {
4363 while (_isLikelyParameterList()) { 4411 while (_isLikelyParameterList()) {
4364 TypeArgumentList typeArguments = null; 4412 TypeArgumentList typeArguments = _parseOptionalTypeArguments();
4365 if (_matches(TokenType.LT)) {
4366 typeArguments = parseTypeArgumentList();
4367 }
4368 ArgumentList argumentList = parseArgumentList(); 4413 ArgumentList argumentList = parseArgumentList();
4369 if (expression is SimpleIdentifier) { 4414 if (expression is SimpleIdentifier) {
4370 expression = new MethodInvocation(null, null, 4415 expression = new MethodInvocation(null, null,
4371 expression as SimpleIdentifier, typeArguments, argumentList); 4416 expression as SimpleIdentifier, typeArguments, argumentList);
4372 } else if (expression is PrefixedIdentifier) { 4417 } else if (expression is PrefixedIdentifier) {
4373 PrefixedIdentifier identifier = expression as PrefixedIdentifier; 4418 PrefixedIdentifier identifier = expression as PrefixedIdentifier;
4374 expression = new MethodInvocation( 4419 expression = new MethodInvocation(
4375 identifier.prefix, 4420 identifier.prefix,
4376 identifier.period, 4421 identifier.period,
4377 identifier.identifier, 4422 identifier.identifier,
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
4566 } 4611 }
4567 } else { 4612 } else {
4568 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, 4613 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken,
4569 [_currentToken.lexeme]); 4614 [_currentToken.lexeme]);
4570 functionName = _createSyntheticIdentifier(); 4615 functionName = _createSyntheticIdentifier();
4571 } 4616 }
4572 assert((expression == null && functionName != null) || 4617 assert((expression == null && functionName != null) ||
4573 (expression != null && functionName == null)); 4618 (expression != null && functionName == null));
4574 if (_isLikelyParameterList()) { 4619 if (_isLikelyParameterList()) {
4575 while (_isLikelyParameterList()) { 4620 while (_isLikelyParameterList()) {
4576 TypeArgumentList typeArguments = null; 4621 TypeArgumentList typeArguments = _parseOptionalTypeArguments();
4577 if (_matches(TokenType.LT)) {
4578 typeArguments = parseTypeArgumentList();
4579 }
4580 if (functionName != null) { 4622 if (functionName != null) {
4581 expression = new MethodInvocation(expression, period, functionName, 4623 expression = new MethodInvocation(expression, period, functionName,
4582 typeArguments, parseArgumentList()); 4624 typeArguments, parseArgumentList());
4583 period = null; 4625 period = null;
4584 functionName = null; 4626 functionName = null;
4585 } else if (expression == null) { 4627 } else if (expression == null) {
4586 // It should not be possible to get here. 4628 // It should not be possible to get here.
4587 expression = new MethodInvocation(expression, period, 4629 expression = new MethodInvocation(expression, period,
4588 _createSyntheticIdentifier(), typeArguments, parseArgumentList()); 4630 _createSyntheticIdentifier(), typeArguments, parseArgumentList());
4589 } else { 4631 } else {
4590 expression = new FunctionExpressionInvocation( 4632 expression = new FunctionExpressionInvocation(
4591 expression, typeArguments, parseArgumentList()); 4633 expression, typeArguments, parseArgumentList());
4592 } 4634 }
4593 } 4635 }
4594 } else if (functionName != null) { 4636 } else if (functionName != null) {
4595 expression = new PropertyAccess(expression, period, functionName); 4637 expression = new PropertyAccess(expression, period, functionName);
4596 period = null; 4638 period = null;
4597 } 4639 }
4598 assert(expression != null); 4640 assert(expression != null);
4599 bool progress = true; 4641 bool progress = true;
4600 while (progress) { 4642 while (progress) {
4601 progress = false; 4643 progress = false;
4602 Expression selector = _parseAssignableSelector(expression, true); 4644 Expression selector = _parseAssignableSelector(expression, true);
4603 if (!identical(selector, expression)) { 4645 if (!identical(selector, expression)) {
4604 expression = selector; 4646 expression = selector;
4605 progress = true; 4647 progress = true;
4606 while (_isLikelyParameterList()) { 4648 while (_isLikelyParameterList()) {
4607 TypeArgumentList typeArguments = null; 4649 TypeArgumentList typeArguments = _parseOptionalTypeArguments();
4608 if (_matches(TokenType.LT)) {
4609 typeArguments = parseTypeArgumentList();
4610 }
4611 if (expression is PropertyAccess) { 4650 if (expression is PropertyAccess) {
4612 PropertyAccess propertyAccess = expression as PropertyAccess; 4651 PropertyAccess propertyAccess = expression as PropertyAccess;
4613 expression = new MethodInvocation( 4652 expression = new MethodInvocation(
4614 propertyAccess.target, 4653 propertyAccess.target,
4615 propertyAccess.operator, 4654 propertyAccess.operator,
4616 propertyAccess.propertyName, 4655 propertyAccess.propertyName,
4617 typeArguments, 4656 typeArguments,
4618 parseArgumentList()); 4657 parseArgumentList());
4619 } else { 4658 } else {
4620 expression = new FunctionExpressionInvocation( 4659 expression = new FunctionExpressionInvocation(
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
5684 * | 'var' 5723 * | 'var'
5685 * | type 5724 * | type
5686 */ 5725 */
5687 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { 5726 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) {
5688 Token keyword = null; 5727 Token keyword = null;
5689 TypeName type = null; 5728 TypeName type = null;
5690 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) { 5729 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) {
5691 keyword = getAndAdvance(); 5730 keyword = getAndAdvance();
5692 if (_isTypedIdentifier(_currentToken)) { 5731 if (_isTypedIdentifier(_currentToken)) {
5693 type = parseTypeName(); 5732 type = parseTypeName();
5733 } else {
5734 // Support `final/*=T*/ x;`
5735 type = _parseOptionalTypeNameComment();
5694 } 5736 }
5695 } else if (_matchesKeyword(Keyword.VAR)) { 5737 } else if (_matchesKeyword(Keyword.VAR)) {
5696 keyword = getAndAdvance(); 5738 keyword = getAndAdvance();
5739 // Support `var/*=T*/ x;`
5740 type = _parseOptionalTypeNameComment();
5741 if (type != null) {
5742 // Clear the keyword to prevent an error.
5743 keyword = null;
5744 }
5745 } else if (_isTypedIdentifier(_currentToken)) {
5746 type = parseReturnType();
5747 } else if (!optional) {
5748 _reportErrorForCurrentToken(
5749 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
5697 } else { 5750 } else {
5698 if (_isTypedIdentifier(_currentToken)) { 5751 // Support parameters such as `(/*=K*/ key, /*=V*/ value)`
5699 type = parseReturnType(); 5752 // This is not supported if the type is required.
5700 } else if (!optional) { 5753 type = _parseOptionalTypeNameComment();
5701 _reportErrorForCurrentToken(
5702 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
5703 }
5704 } 5754 }
5705 return new FinalConstVarOrType(keyword, type); 5755 return new FinalConstVarOrType(keyword, type);
5706 } 5756 }
5707 5757
5708 /** 5758 /**
5709 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be 5759 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
5710 * `true`. The [kind] is the kind of parameter being expected based on the 5760 * `true`. The [kind] is the kind of parameter being expected based on the
5711 * presence or absence of group delimiters. Return the formal parameter that 5761 * presence or absence of group delimiters. Return the formal parameter that
5712 * was parsed. 5762 * was parsed.
5713 * 5763 *
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
6018 bool isGetter = false; 6068 bool isGetter = false;
6019 if (_matchesKeyword(Keyword.GET) && 6069 if (_matchesKeyword(Keyword.GET) &&
6020 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 6070 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
6021 keyword = getAndAdvance(); 6071 keyword = getAndAdvance();
6022 isGetter = true; 6072 isGetter = true;
6023 } else if (_matchesKeyword(Keyword.SET) && 6073 } else if (_matchesKeyword(Keyword.SET) &&
6024 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 6074 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
6025 keyword = getAndAdvance(); 6075 keyword = getAndAdvance();
6026 } 6076 }
6027 SimpleIdentifier name = parseSimpleIdentifier(); 6077 SimpleIdentifier name = parseSimpleIdentifier();
6028 TypeParameterList typeParameters = null; 6078 TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
6029 if (parseGenericMethods && _matches(TokenType.LT)) {
6030 typeParameters = parseTypeParameterList();
6031 }
6032 FormalParameterList parameters = null; 6079 FormalParameterList parameters = null;
6033 if (!isGetter) { 6080 if (!isGetter) {
6034 if (_matches(TokenType.OPEN_PAREN)) { 6081 if (_matches(TokenType.OPEN_PAREN)) {
6035 parameters = parseFormalParameterList(); 6082 parameters = parseFormalParameterList();
6036 _validateFormalParameterList(parameters); 6083 _validateFormalParameterList(parameters);
6037 } else { 6084 } else {
6038 _reportErrorForCurrentToken( 6085 _reportErrorForCurrentToken(
6039 ParserErrorCode.MISSING_FUNCTION_PARAMETERS); 6086 ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
6040 parameters = new FormalParameterList( 6087 parameters = new FormalParameterList(
6041 _createSyntheticToken(TokenType.OPEN_PAREN), 6088 _createSyntheticToken(TokenType.OPEN_PAREN),
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
6175 commentAndMetadata.metadata, 6222 commentAndMetadata.metadata,
6176 keyword, 6223 keyword,
6177 returnType, 6224 returnType,
6178 name, 6225 name,
6179 typeParameters, 6226 typeParameters,
6180 parameters, 6227 parameters,
6181 semicolon); 6228 semicolon);
6182 } 6229 }
6183 6230
6184 /** 6231 /**
6232 * Parses generic type parameters from a comment.
6233 *
6234 * Normally this is handled by [_parseGenericMethodTypeParameters], but if the
6235 * code already handles the normal generic type parameters, the comment
6236 * matcher can be called directly. For example, we may have already tried
6237 * matching `<` (less than sign) in a method declaration, and be currently
6238 * on the `(` (open paren) because we didn't find it. In that case, this
6239 * function will parse the preceding comment such as `/*<T, R>*/`.
6240 */
6241 TypeParameterList _parseGenericCommentTypeParameters() {
6242 if (_injectGenericCommentTypeList()) {
6243 return parseTypeParameterList();
6244 }
6245 return null;
6246 }
6247
6248 /**
6249 * Parse the generic method or function's type parameters.
6250 *
6251 * For backwards compatibility this can optionally use comments.
6252 * See [parseGenericMethodComments].
6253 */
6254 TypeParameterList _parseGenericMethodTypeParameters() {
6255 if (parseGenericMethods && _matches(TokenType.LT) ||
6256 _injectGenericCommentTypeList()) {
6257 return parseTypeParameterList();
6258 }
6259 }
6260
6261 /**
6185 * Parse a getter. The [commentAndMetadata] is the documentation comment and 6262 * Parse a getter. The [commentAndMetadata] is the documentation comment and
6186 * metadata to be associated with the declaration. The externalKeyword] is the 6263 * metadata to be associated with the declaration. The externalKeyword] is the
6187 * 'external' token. The staticKeyword] is the static keyword, or `null` if 6264 * 'external' token. The staticKeyword] is the static keyword, or `null` if
6188 * the getter is not static. The [returnType] the return type that has already 6265 * the getter is not static. The [returnType] the return type that has already
6189 * been parsed, or `null` if there was no return type. Return the getter that 6266 * been parsed, or `null` if there was no return type. Return the getter that
6190 * was parsed. 6267 * was parsed.
6191 * 6268 *
6192 * getter ::= 6269 * getter ::=
6193 * getterSignature functionBody? 6270 * getterSignature functionBody?
6194 * 6271 *
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
6466 /** 6543 /**
6467 * Parse a list or map literal. The [modifier] is the 'const' modifier 6544 * Parse a list or map literal. The [modifier] is the 'const' modifier
6468 * appearing before the literal, or `null` if there is no modifier. Return the 6545 * appearing before the literal, or `null` if there is no modifier. Return the
6469 * list or map literal that was parsed. 6546 * list or map literal that was parsed.
6470 * 6547 *
6471 * listOrMapLiteral ::= 6548 * listOrMapLiteral ::=
6472 * listLiteral 6549 * listLiteral
6473 * | mapLiteral 6550 * | mapLiteral
6474 */ 6551 */
6475 TypedLiteral _parseListOrMapLiteral(Token modifier) { 6552 TypedLiteral _parseListOrMapLiteral(Token modifier) {
6476 TypeArgumentList typeArguments = null; 6553 TypeArgumentList typeArguments = _parseOptionalTypeArguments();
6477 if (_matches(TokenType.LT)) {
6478 typeArguments = parseTypeArgumentList();
6479 }
6480 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { 6554 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6481 return _parseMapLiteral(modifier, typeArguments); 6555 return _parseMapLiteral(modifier, typeArguments);
6482 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || 6556 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
6483 _matches(TokenType.INDEX)) { 6557 _matches(TokenType.INDEX)) {
6484 return _parseListLiteral(modifier, typeArguments); 6558 return _parseListLiteral(modifier, typeArguments);
6485 } 6559 }
6486 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL); 6560 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
6487 return new ListLiteral( 6561 return new ListLiteral(
6488 modifier, 6562 modifier,
6489 typeArguments, 6563 typeArguments,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
6603 * functionDeclaration ::= 6677 * functionDeclaration ::=
6604 * 'external'? 'static'? functionSignature functionBody 6678 * 'external'? 'static'? functionSignature functionBody
6605 * | 'external'? functionSignature ';' 6679 * | 'external'? functionSignature ';'
6606 */ 6680 */
6607 MethodDeclaration _parseMethodDeclarationAfterReturnType( 6681 MethodDeclaration _parseMethodDeclarationAfterReturnType(
6608 CommentAndMetadata commentAndMetadata, 6682 CommentAndMetadata commentAndMetadata,
6609 Token externalKeyword, 6683 Token externalKeyword,
6610 Token staticKeyword, 6684 Token staticKeyword,
6611 TypeName returnType) { 6685 TypeName returnType) {
6612 SimpleIdentifier methodName = parseSimpleIdentifier(); 6686 SimpleIdentifier methodName = parseSimpleIdentifier();
6613 TypeParameterList typeParameters = null; 6687 TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
6614 if (parseGenericMethods && _matches(TokenType.LT)) {
6615 typeParameters = parseTypeParameterList();
6616 }
6617 FormalParameterList parameters; 6688 FormalParameterList parameters;
6618 if (!_matches(TokenType.OPEN_PAREN) && 6689 if (!_matches(TokenType.OPEN_PAREN) &&
6619 (_matches(TokenType.OPEN_CURLY_BRACKET) || 6690 (_matches(TokenType.OPEN_CURLY_BRACKET) ||
6620 _matches(TokenType.FUNCTION))) { 6691 _matches(TokenType.FUNCTION))) {
6621 _reportErrorForToken( 6692 _reportErrorForToken(
6622 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous); 6693 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
6623 parameters = new FormalParameterList( 6694 parameters = new FormalParameterList(
6624 _createSyntheticToken(TokenType.OPEN_PAREN), 6695 _createSyntheticToken(TokenType.OPEN_PAREN),
6625 null, 6696 null,
6626 null, 6697 null,
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
7003 null, 7074 null,
7004 parameters, 7075 parameters,
7005 body); 7076 body);
7006 } 7077 }
7007 7078
7008 /** 7079 /**
7009 * Parse a return type if one is given, otherwise return `null` without 7080 * Parse a return type if one is given, otherwise return `null` without
7010 * advancing. Return the return type that was parsed. 7081 * advancing. Return the return type that was parsed.
7011 */ 7082 */
7012 TypeName _parseOptionalReturnType() { 7083 TypeName _parseOptionalReturnType() {
7013 if (_matchesKeyword(Keyword.VOID)) { 7084 TypeName typeComment = _parseOptionalTypeNameComment();
7085 if (typeComment != null) {
7086 return typeComment;
7087 } else if (_matchesKeyword(Keyword.VOID)) {
7014 return parseReturnType(); 7088 return parseReturnType();
7015 } else if (_matchesIdentifier() && 7089 } else if (_matchesIdentifier() &&
7016 !_matchesKeyword(Keyword.GET) && 7090 !_matchesKeyword(Keyword.GET) &&
7017 !_matchesKeyword(Keyword.SET) && 7091 !_matchesKeyword(Keyword.SET) &&
7018 !_matchesKeyword(Keyword.OPERATOR) && 7092 !_matchesKeyword(Keyword.OPERATOR) &&
7019 (_tokenMatchesIdentifier(_peek()) || 7093 (_tokenMatchesIdentifier(_peek()) ||
7020 _tokenMatches(_peek(), TokenType.LT))) { 7094 _tokenMatches(_peek(), TokenType.LT))) {
7021 return parseReturnType(); 7095 return parseReturnType();
7022 } else if (_matchesIdentifier() && 7096 } else if (_matchesIdentifier() &&
7023 _tokenMatches(_peek(), TokenType.PERIOD) && 7097 _tokenMatches(_peek(), TokenType.PERIOD) &&
7024 _tokenMatchesIdentifier(_peekAt(2)) && 7098 _tokenMatchesIdentifier(_peekAt(2)) &&
7025 (_tokenMatchesIdentifier(_peekAt(3)) || 7099 (_tokenMatchesIdentifier(_peekAt(3)) ||
7026 _tokenMatches(_peekAt(3), TokenType.LT))) { 7100 _tokenMatches(_peekAt(3), TokenType.LT))) {
7027 return parseReturnType(); 7101 return parseReturnType();
7028 } 7102 }
7029 return null; 7103 return null;
7030 } 7104 }
7031 7105
7032 /** 7106 /**
7107 * Parse a [TypeArgumentList] if present, otherwise return null.
7108 * This also supports the comment form, if enabled: `/*<T>*/`
7109 */
7110 TypeArgumentList _parseOptionalTypeArguments() {
7111 if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) {
7112 return parseTypeArgumentList();
7113 }
7114 return null;
7115 }
7116
7117 TypeName _parseOptionalTypeNameComment() {
7118 if (_injectGenericCommentTypeAssign()) {
7119 return _parseTypeName();
7120 }
7121 return null;
7122 }
7123
7124 /**
7033 * Parse a part or part-of directive. The [commentAndMetadata] is the metadata 7125 * Parse a part or part-of directive. The [commentAndMetadata] is the metadata
7034 * to be associated with the directive. Return the part or part-of directive 7126 * to be associated with the directive. Return the part or part-of directive
7035 * that was parsed. 7127 * that was parsed.
7036 * 7128 *
7037 * partDirective ::= 7129 * partDirective ::=
7038 * metadata 'part' stringLiteral ';' 7130 * metadata 'part' stringLiteral ';'
7039 * 7131 *
7040 * partOfDirective ::= 7132 * partOfDirective ::=
7041 * metadata 'part' 'of' identifier ';' 7133 * metadata 'part' 'of' identifier ';'
7042 */ 7134 */
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
7074 */ 7166 */
7075 Expression _parsePostfixExpression() { 7167 Expression _parsePostfixExpression() {
7076 Expression operand = _parseAssignableExpression(true); 7168 Expression operand = _parseAssignableExpression(true);
7077 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || 7169 if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
7078 _matches(TokenType.PERIOD) || 7170 _matches(TokenType.PERIOD) ||
7079 _matches(TokenType.QUESTION_PERIOD) || 7171 _matches(TokenType.QUESTION_PERIOD) ||
7080 _matches(TokenType.OPEN_PAREN) || 7172 _matches(TokenType.OPEN_PAREN) ||
7081 (parseGenericMethods && _matches(TokenType.LT))) { 7173 (parseGenericMethods && _matches(TokenType.LT))) {
7082 do { 7174 do {
7083 if (_isLikelyParameterList()) { 7175 if (_isLikelyParameterList()) {
7084 TypeArgumentList typeArguments = null; 7176 TypeArgumentList typeArguments = _parseOptionalTypeArguments();
7085 if (_matches(TokenType.LT)) {
7086 typeArguments = parseTypeArgumentList();
7087 }
7088 ArgumentList argumentList = parseArgumentList(); 7177 ArgumentList argumentList = parseArgumentList();
7089 if (operand is PropertyAccess) { 7178 if (operand is PropertyAccess) {
7090 PropertyAccess access = operand as PropertyAccess; 7179 PropertyAccess access = operand as PropertyAccess;
7091 operand = new MethodInvocation(access.target, access.operator, 7180 operand = new MethodInvocation(access.target, access.operator,
7092 access.propertyName, typeArguments, argumentList); 7181 access.propertyName, typeArguments, argumentList);
7093 } else { 7182 } else {
7094 operand = new FunctionExpressionInvocation( 7183 operand = new FunctionExpressionInvocation(
7095 operand, typeArguments, argumentList); 7184 operand, typeArguments, argumentList);
7096 } 7185 }
7097 } else { 7186 } else {
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
7734 TypeAlias typeAlias = 7823 TypeAlias typeAlias =
7735 _parseClassTypeAlias(commentAndMetadata, null, keyword); 7824 _parseClassTypeAlias(commentAndMetadata, null, keyword);
7736 _reportErrorForToken( 7825 _reportErrorForToken(
7737 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); 7826 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword);
7738 return typeAlias; 7827 return typeAlias;
7739 } 7828 }
7740 } 7829 }
7741 return _parseFunctionTypeAlias(commentAndMetadata, keyword); 7830 return _parseFunctionTypeAlias(commentAndMetadata, keyword);
7742 } 7831 }
7743 7832
7833 TypeName _parseTypeName() {
7834 Identifier typeName;
7835 if (_matchesKeyword(Keyword.VAR)) {
7836 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME);
7837 typeName = new SimpleIdentifier(getAndAdvance());
7838 } else if (_matchesIdentifier()) {
7839 typeName = parsePrefixedIdentifier();
7840 } else {
7841 typeName = _createSyntheticIdentifier();
7842 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
7843 }
7844 TypeArgumentList typeArguments = _parseOptionalTypeArguments();
7845 return new TypeName(typeName, typeArguments);
7846 }
7847
7744 /** 7848 /**
7745 * Parse a unary expression. Return the unary expression that was parsed. 7849 * Parse a unary expression. Return the unary expression that was parsed.
7746 * 7850 *
7747 * unaryExpression ::= 7851 * unaryExpression ::=
7748 * prefixOperator unaryExpression 7852 * prefixOperator unaryExpression
7749 * | awaitExpression 7853 * | awaitExpression
7750 * | postfixExpression 7854 * | postfixExpression
7751 * | unaryOperator 'super' 7855 * | unaryOperator 'super'
7752 * | '-' 'super' 7856 * | '-' 'super'
7753 * | incrementOperator assignableExpression 7857 * | incrementOperator assignableExpression
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
8077 void _reportErrorForToken(ErrorCode errorCode, Token token, 8181 void _reportErrorForToken(ErrorCode errorCode, Token token,
8078 [List<Object> arguments]) { 8182 [List<Object> arguments]) {
8079 if (token.type == TokenType.EOF) { 8183 if (token.type == TokenType.EOF) {
8080 token = token.previous; 8184 token = token.previous;
8081 } 8185 }
8082 _reportError(new AnalysisError(_source, token.offset, 8186 _reportError(new AnalysisError(_source, token.offset,
8083 math.max(token.length, 1), errorCode, arguments)); 8187 math.max(token.length, 1), errorCode, arguments));
8084 } 8188 }
8085 8189
8086 /** 8190 /**
8191 * Scans the generic method comment, and returns the tokens, otherwise
8192 * returns null.
8193 */
8194 Token _scanGenericMethodComment(String code, int offset) {
8195 BooleanErrorListener listener = new BooleanErrorListener();
8196 Scanner scanner =
8197 new Scanner(null, new SubSequenceReader(code, offset), listener);
8198 scanner.setSourceStart(1, 1);
8199 Token firstToken = scanner.tokenize();
8200 if (listener.errorReported) {
8201 return null;
8202 }
8203 return firstToken;
8204 }
8205
8206 /**
8087 * Skips a block with all containing blocks. 8207 * Skips a block with all containing blocks.
8088 */ 8208 */
8089 void _skipBlock() { 8209 void _skipBlock() {
8090 Token endToken = (_currentToken as BeginToken).endToken; 8210 Token endToken = (_currentToken as BeginToken).endToken;
8091 if (endToken == null) { 8211 if (endToken == null) {
8092 endToken = _currentToken.next; 8212 endToken = _currentToken.next;
8093 while (!identical(endToken, _currentToken)) { 8213 while (!identical(endToken, _currentToken)) {
8094 _currentToken = endToken; 8214 _currentToken = endToken;
8095 endToken = _currentToken.next; 8215 endToken = _currentToken.next;
8096 } 8216 }
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
8413 * This method must be kept in sync with [parseTypeArgumentList]. 8533 * This method must be kept in sync with [parseTypeArgumentList].
8414 * 8534 *
8415 * typeArguments ::= 8535 * typeArguments ::=
8416 * '<' typeList '>' 8536 * '<' typeList '>'
8417 * 8537 *
8418 * typeList ::= 8538 * typeList ::=
8419 * type (',' type)* 8539 * type (',' type)*
8420 */ 8540 */
8421 Token _skipTypeArgumentList(Token startToken) { 8541 Token _skipTypeArgumentList(Token startToken) {
8422 Token token = startToken; 8542 Token token = startToken;
8423 if (!_tokenMatches(token, TokenType.LT)) { 8543 if (!_tokenMatches(token, TokenType.LT) &&
8544 !_injectGenericCommentTypeList()) {
8424 return null; 8545 return null;
8425 } 8546 }
8426 token = _skipTypeName(token.next); 8547 token = _skipTypeName(token.next);
8427 if (token == null) { 8548 if (token == null) {
8428 // If the start token '<' is followed by '>' 8549 // If the start token '<' is followed by '>'
8429 // then assume this should be type argument list but is missing a type 8550 // then assume this should be type argument list but is missing a type
8430 token = startToken.next; 8551 token = startToken.next;
8431 if (_tokenMatches(token, TokenType.GT)) { 8552 if (_tokenMatches(token, TokenType.GT)) {
8432 return token.next; 8553 return token.next;
8433 } 8554 }
(...skipping 2619 matching lines...) Expand 10 before | Expand all | Expand 10 after
11053 } 11174 }
11054 11175
11055 /** 11176 /**
11056 * Copy resolution data from the [fromNode] to the [toNode]. 11177 * Copy resolution data from the [fromNode] to the [toNode].
11057 */ 11178 */
11058 static void copyResolutionData(AstNode fromNode, AstNode toNode) { 11179 static void copyResolutionData(AstNode fromNode, AstNode toNode) {
11059 ResolutionCopier copier = new ResolutionCopier(); 11180 ResolutionCopier copier = new ResolutionCopier();
11060 copier._isEqualNodes(fromNode, toNode); 11181 copier._isEqualNodes(fromNode, toNode);
11061 } 11182 }
11062 } 11183 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698