| OLD | NEW |
| 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 analyzer.parser; | 5 library analyzer.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 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 5174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5185 } else { | 5185 } else { |
| 5186 type = parseTypeWithoutFunction(inExpression); | 5186 type = parseTypeWithoutFunction(inExpression); |
| 5187 } | 5187 } |
| 5188 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | 5188 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
| 5189 type = parseGenericFunctionTypeAfterReturnType(type); | 5189 type = parseGenericFunctionTypeAfterReturnType(type); |
| 5190 } | 5190 } |
| 5191 return type; | 5191 return type; |
| 5192 } | 5192 } |
| 5193 | 5193 |
| 5194 /** | 5194 /** |
| 5195 * Parse a type which is not `void`. | |
| 5196 * | |
| 5197 * typeNotVoid ::= | |
| 5198 * functionType | |
| 5199 * | typeNotVoidWithoutFunction | |
| 5200 */ | |
| 5201 TypeAnnotation parseTypeNotVoid(bool inExpression) { | |
| 5202 TypeAnnotation type = null; | |
| 5203 if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | |
| 5204 // Generic function type with no return type. | |
| 5205 type = parseGenericFunctionTypeAfterReturnType(null); | |
| 5206 } else if (_currentToken.keyword == Keyword.VOID && | |
| 5207 _atGenericFunctionTypeAfterReturnType(_currentToken.next)) { | |
| 5208 type = astFactory.typeName( | |
| 5209 astFactory.simpleIdentifier(getAndAdvance()), null); | |
| 5210 } else { | |
| 5211 type = parseTypeName(inExpression); | |
| 5212 } | |
| 5213 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | |
| 5214 type = parseGenericFunctionTypeAfterReturnType(type); | |
| 5215 } | |
| 5216 return type; | |
| 5217 } | |
| 5218 | |
| 5219 /** | |
| 5220 * Parse a type which is not a function type. | |
| 5221 * | |
| 5222 * typeWithoutFunction ::= | |
| 5223 * `void` | |
| 5224 * | typeNotVoidWithoutFunction | |
| 5225 */ | |
| 5226 TypeAnnotation parseTypeWithoutFunction(bool inExpression) { | |
| 5227 if (_currentToken.keyword == Keyword.VOID) { | |
| 5228 return astFactory.typeName( | |
| 5229 astFactory.simpleIdentifier(getAndAdvance()), null); | |
| 5230 } else { | |
| 5231 return parseTypeName(inExpression); | |
| 5232 } | |
| 5233 } | |
| 5234 | |
| 5235 /** | |
| 5236 * Parse a list of type arguments. Return the type argument list that was | 5195 * Parse a list of type arguments. Return the type argument list that was |
| 5237 * parsed. | 5196 * parsed. |
| 5238 * | 5197 * |
| 5239 * This method assumes that the current token matches `TokenType.LT`. | 5198 * This method assumes that the current token matches `TokenType.LT`. |
| 5240 * | 5199 * |
| 5241 * typeArguments ::= | 5200 * typeArguments ::= |
| 5242 * '<' typeList '>' | 5201 * '<' typeList '>' |
| 5243 * | 5202 * |
| 5244 * typeList ::= | 5203 * typeList ::= |
| 5245 * type (',' type)* | 5204 * type (',' type)* |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5269 TypeName realType = _parseTypeName(inExpression); | 5228 TypeName realType = _parseTypeName(inExpression); |
| 5270 // If this is followed by a generic method type comment, allow the comment | 5229 // If this is followed by a generic method type comment, allow the comment |
| 5271 // type to replace the real type name. | 5230 // type to replace the real type name. |
| 5272 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to | 5231 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to |
| 5273 // only work inside generic methods? | 5232 // only work inside generic methods? |
| 5274 TypeName typeFromComment = _parseOptionalTypeNameComment(); | 5233 TypeName typeFromComment = _parseOptionalTypeNameComment(); |
| 5275 return typeFromComment ?? realType; | 5234 return typeFromComment ?? realType; |
| 5276 } | 5235 } |
| 5277 | 5236 |
| 5278 /** | 5237 /** |
| 5238 * Parse a type which is not `void`. |
| 5239 * |
| 5240 * typeNotVoid ::= |
| 5241 * functionType |
| 5242 * | typeNotVoidWithoutFunction |
| 5243 */ |
| 5244 TypeAnnotation parseTypeNotVoid(bool inExpression) { |
| 5245 TypeAnnotation type = null; |
| 5246 if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
| 5247 // Generic function type with no return type. |
| 5248 type = parseGenericFunctionTypeAfterReturnType(null); |
| 5249 } else if (_currentToken.keyword == Keyword.VOID && |
| 5250 _atGenericFunctionTypeAfterReturnType(_currentToken.next)) { |
| 5251 type = astFactory.typeName( |
| 5252 astFactory.simpleIdentifier(getAndAdvance()), null); |
| 5253 } else { |
| 5254 type = parseTypeName(inExpression); |
| 5255 } |
| 5256 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
| 5257 type = parseGenericFunctionTypeAfterReturnType(type); |
| 5258 } |
| 5259 return type; |
| 5260 } |
| 5261 |
| 5262 /** |
| 5279 * Parse a type parameter. Return the type parameter that was parsed. | 5263 * Parse a type parameter. Return the type parameter that was parsed. |
| 5280 * | 5264 * |
| 5281 * typeParameter ::= | 5265 * typeParameter ::= |
| 5282 * metadata name ('extends' bound)? | 5266 * metadata name ('extends' bound)? |
| 5283 */ | 5267 */ |
| 5284 TypeParameter parseTypeParameter() { | 5268 TypeParameter parseTypeParameter() { |
| 5285 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); | 5269 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); |
| 5286 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); | 5270 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); |
| 5287 if (_matches(TokenType.QUESTION)) { | 5271 if (_matches(TokenType.QUESTION)) { |
| 5288 _reportErrorForCurrentToken(ParserErrorCode.NULLABLE_TYPE_PARAMETER); | 5272 _reportErrorForCurrentToken(ParserErrorCode.NULLABLE_TYPE_PARAMETER); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5312 List<TypeParameter> typeParameters = <TypeParameter>[parseTypeParameter()]; | 5296 List<TypeParameter> typeParameters = <TypeParameter>[parseTypeParameter()]; |
| 5313 while (_optional(TokenType.COMMA)) { | 5297 while (_optional(TokenType.COMMA)) { |
| 5314 typeParameters.add(parseTypeParameter()); | 5298 typeParameters.add(parseTypeParameter()); |
| 5315 } | 5299 } |
| 5316 Token rightBracket = _expectGt(); | 5300 Token rightBracket = _expectGt(); |
| 5317 return astFactory.typeParameterList( | 5301 return astFactory.typeParameterList( |
| 5318 leftBracket, typeParameters, rightBracket); | 5302 leftBracket, typeParameters, rightBracket); |
| 5319 } | 5303 } |
| 5320 | 5304 |
| 5321 /** | 5305 /** |
| 5306 * Parse a type which is not a function type. |
| 5307 * |
| 5308 * typeWithoutFunction ::= |
| 5309 * `void` |
| 5310 * | typeNotVoidWithoutFunction |
| 5311 */ |
| 5312 TypeAnnotation parseTypeWithoutFunction(bool inExpression) { |
| 5313 if (_currentToken.keyword == Keyword.VOID) { |
| 5314 return astFactory.typeName( |
| 5315 astFactory.simpleIdentifier(getAndAdvance()), null); |
| 5316 } else { |
| 5317 return parseTypeName(inExpression); |
| 5318 } |
| 5319 } |
| 5320 |
| 5321 /** |
| 5322 * Parse a unary expression. Return the unary expression that was parsed. | 5322 * Parse a unary expression. Return the unary expression that was parsed. |
| 5323 * | 5323 * |
| 5324 * unaryExpression ::= | 5324 * unaryExpression ::= |
| 5325 * prefixOperator unaryExpression | 5325 * prefixOperator unaryExpression |
| 5326 * | awaitExpression | 5326 * | awaitExpression |
| 5327 * | postfixExpression | 5327 * | postfixExpression |
| 5328 * | unaryOperator 'super' | 5328 * | unaryOperator 'super' |
| 5329 * | '-' 'super' | 5329 * | '-' 'super' |
| 5330 * | incrementOperator assignableExpression | 5330 * | incrementOperator assignableExpression |
| 5331 */ | 5331 */ |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5683 } else { | 5683 } else { |
| 5684 next = skipTypeWithoutFunction(startToken); | 5684 next = skipTypeWithoutFunction(startToken); |
| 5685 } | 5685 } |
| 5686 while (next != null && _atGenericFunctionTypeAfterReturnType(next)) { | 5686 while (next != null && _atGenericFunctionTypeAfterReturnType(next)) { |
| 5687 next = skipGenericFunctionTypeAfterReturnType(next); | 5687 next = skipGenericFunctionTypeAfterReturnType(next); |
| 5688 } | 5688 } |
| 5689 return next; | 5689 return next; |
| 5690 } | 5690 } |
| 5691 | 5691 |
| 5692 /** | 5692 /** |
| 5693 * Parse a typeWithoutFunction, starting at the [startToken], without actually | |
| 5694 * creating a TypeAnnotation or changing the current token. Return the token | |
| 5695 * following the typeWithoutFunction that was parsed, or `null` if the given | |
| 5696 * token is not the first token in a valid typeWithoutFunction. | |
| 5697 * | |
| 5698 * This method must be kept in sync with [parseTypeWithoutFunction]. | |
| 5699 */ | |
| 5700 Token skipTypeWithoutFunction(Token startToken) { | |
| 5701 if (startToken.keyword == Keyword.VOID) { | |
| 5702 return startToken.next; | |
| 5703 } else { | |
| 5704 return skipTypeName(startToken); | |
| 5705 } | |
| 5706 } | |
| 5707 | |
| 5708 /** | |
| 5709 * Parse a list of type arguments, starting at the [startToken], without | 5693 * Parse a list of type arguments, starting at the [startToken], without |
| 5710 * actually creating a type argument list or changing the current token. | 5694 * actually creating a type argument list or changing the current token. |
| 5711 * Return the token following the type argument list that was parsed, or | 5695 * Return the token following the type argument list that was parsed, or |
| 5712 * `null` if the given token is not the first token in a valid type argument | 5696 * `null` if the given token is not the first token in a valid type argument |
| 5713 * list. | 5697 * list. |
| 5714 * | 5698 * |
| 5715 * This method must be kept in sync with [parseTypeArgumentList]. | 5699 * This method must be kept in sync with [parseTypeArgumentList]. |
| 5716 * | 5700 * |
| 5717 * typeArguments ::= | 5701 * typeArguments ::= |
| 5718 * '<' typeList '>' | 5702 * '<' typeList '>' |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5798 return next.next; | 5782 return next.next; |
| 5799 } | 5783 } |
| 5800 } | 5784 } |
| 5801 previous = next; | 5785 previous = next; |
| 5802 next = next.next; | 5786 next = next.next; |
| 5803 } | 5787 } |
| 5804 return null; | 5788 return null; |
| 5805 } | 5789 } |
| 5806 | 5790 |
| 5807 /** | 5791 /** |
| 5792 * Parse a typeWithoutFunction, starting at the [startToken], without actually |
| 5793 * creating a TypeAnnotation or changing the current token. Return the token |
| 5794 * following the typeWithoutFunction that was parsed, or `null` if the given |
| 5795 * token is not the first token in a valid typeWithoutFunction. |
| 5796 * |
| 5797 * This method must be kept in sync with [parseTypeWithoutFunction]. |
| 5798 */ |
| 5799 Token skipTypeWithoutFunction(Token startToken) { |
| 5800 if (startToken.keyword == Keyword.VOID) { |
| 5801 return startToken.next; |
| 5802 } else { |
| 5803 return skipTypeName(startToken); |
| 5804 } |
| 5805 } |
| 5806 |
| 5807 /** |
| 5808 * Advance to the next token in the token stream. | 5808 * Advance to the next token in the token stream. |
| 5809 */ | 5809 */ |
| 5810 void _advance() { | 5810 void _advance() { |
| 5811 _currentToken = _currentToken.next; | 5811 _currentToken = _currentToken.next; |
| 5812 } | 5812 } |
| 5813 | 5813 |
| 5814 /** | 5814 /** |
| 5815 * Append the character equivalent of the given [codePoint] to the given | 5815 * Append the character equivalent of the given [codePoint] to the given |
| 5816 * [builder]. Use the [startIndex] and [endIndex] to report an error, and | 5816 * [builder]. Use the [startIndex] and [endIndex] to report an error, and |
| 5817 * don't append anything to the builder, if the code point is invalid. The | 5817 * don't append anything to the builder, if the code point is invalid. The |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6149 } | 6149 } |
| 6150 | 6150 |
| 6151 bool _injectGenericComment(TokenType type, int prefixLen) { | 6151 bool _injectGenericComment(TokenType type, int prefixLen) { |
| 6152 if (parseGenericMethodComments) { | 6152 if (parseGenericMethodComments) { |
| 6153 CommentToken t = _currentToken.precedingComments; | 6153 CommentToken t = _currentToken.precedingComments; |
| 6154 for (; t != null; t = t.next) { | 6154 for (; t != null; t = t.next) { |
| 6155 if (t.type == type) { | 6155 if (t.type == type) { |
| 6156 String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2); | 6156 String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2); |
| 6157 Token list = _scanGenericMethodComment(comment, t.offset + prefixLen); | 6157 Token list = _scanGenericMethodComment(comment, t.offset + prefixLen); |
| 6158 if (list != null) { | 6158 if (list != null) { |
| 6159 _reportErrorForToken(HintCode.GENERIC_METHOD_COMMENT, t); |
| 6159 // Remove the token from the comment stream. | 6160 // Remove the token from the comment stream. |
| 6160 t.remove(); | 6161 t.remove(); |
| 6161 // Insert the tokens into the stream. | 6162 // Insert the tokens into the stream. |
| 6162 _injectTokenList(list); | 6163 _injectTokenList(list); |
| 6163 return true; | 6164 return true; |
| 6164 } | 6165 } |
| 6165 } | 6166 } |
| 6166 } | 6167 } |
| 6167 } | 6168 } |
| 6168 return false; | 6169 return false; |
| (...skipping 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8648 } | 8649 } |
| 8649 } | 8650 } |
| 8650 } | 8651 } |
| 8651 | 8652 |
| 8652 /** | 8653 /** |
| 8653 * Instances of this class are thrown when the parser detects that AST has | 8654 * Instances of this class are thrown when the parser detects that AST has |
| 8654 * too many nested expressions to be parsed safely and avoid possibility of | 8655 * too many nested expressions to be parsed safely and avoid possibility of |
| 8655 * [StackOverflowError] in the parser or during later analysis. | 8656 * [StackOverflowError] in the parser or during later analysis. |
| 8656 */ | 8657 */ |
| 8657 class _TooDeepTreeError {} | 8658 class _TooDeepTreeError {} |
| OLD | NEW |