Chromium Code Reviews| 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 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 Loading... | |
| 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; | |
|
Jennifer Messerly
2015/11/11 18:28:06
aside, we don't actually need this flag in the par
Paul Berry
2015/11/11 19:26:53
My two cents: I'd actually lean slightly toward le
Jennifer Messerly
2015/11/11 19:30:25
good point.
Brian Wilkerson
2015/11/11 21:53:42
I agree, I'd leave the flag in. You'll probably ev
| |
| 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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)) { |
| 2517 SimpleIdentifier methodName = parseSimpleIdentifier(); | 2523 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 2524 TypeParameterList typeParameters = _parseGenericCommentTypeParameters(); | |
| 2518 FormalParameterList parameters = parseFormalParameterList(); | 2525 FormalParameterList parameters = parseFormalParameterList(); |
| 2519 if (_matches(TokenType.COLON) || | 2526 if (_matches(TokenType.COLON) || |
| 2520 modifiers.factoryKeyword != null || | 2527 modifiers.factoryKeyword != null || |
| 2521 methodName.name == className) { | 2528 methodName.name == className) { |
| 2522 return _parseConstructor( | 2529 return _parseConstructor( |
| 2523 commentAndMetadata, | 2530 commentAndMetadata, |
| 2524 modifiers.externalKeyword, | 2531 modifiers.externalKeyword, |
| 2525 _validateModifiersForConstructor(modifiers), | 2532 _validateModifiersForConstructor(modifiers), |
| 2526 modifiers.factoryKeyword, | 2533 modifiers.factoryKeyword, |
| 2527 methodName, | 2534 methodName, |
| 2528 null, | 2535 null, |
| 2529 null, | 2536 null, |
| 2530 parameters); | 2537 parameters); |
| 2531 } | 2538 } |
| 2532 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 2539 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2533 _validateFormalParameterList(parameters); | 2540 _validateFormalParameterList(parameters); |
| 2534 return _parseMethodDeclarationAfterParameters( | 2541 return _parseMethodDeclarationAfterParameters( |
| 2535 commentAndMetadata, | 2542 commentAndMetadata, |
| 2536 modifiers.externalKeyword, | 2543 modifiers.externalKeyword, |
| 2537 modifiers.staticKeyword, | 2544 modifiers.staticKeyword, |
| 2538 null, | 2545 null, |
| 2539 methodName, | 2546 methodName, |
| 2540 null, | 2547 typeParameters, |
| 2541 parameters); | 2548 parameters); |
| 2542 } else if (_peek() | 2549 } else if (_peek() |
| 2543 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) { | 2550 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) { |
| 2544 if (modifiers.constKeyword == null && | 2551 if (modifiers.constKeyword == null && |
| 2545 modifiers.finalKeyword == null && | 2552 modifiers.finalKeyword == null && |
| 2546 modifiers.varKeyword == null) { | 2553 modifiers.varKeyword == null) { |
| 2547 _reportErrorForCurrentToken( | 2554 _reportErrorForCurrentToken( |
| 2548 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); | 2555 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); |
| 2549 } | 2556 } |
| 2550 return _parseInitializedIdentifierList(commentAndMetadata, | 2557 return _parseInitializedIdentifierList(commentAndMetadata, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2610 return _parseInitializedIdentifierList( | 2617 return _parseInitializedIdentifierList( |
| 2611 commentAndMetadata, | 2618 commentAndMetadata, |
| 2612 modifiers.staticKeyword, | 2619 modifiers.staticKeyword, |
| 2613 _validateModifiersForField(modifiers), | 2620 _validateModifiersForField(modifiers), |
| 2614 type); | 2621 type); |
| 2615 } finally { | 2622 } finally { |
| 2616 _unlockErrorListener(); | 2623 _unlockErrorListener(); |
| 2617 } | 2624 } |
| 2618 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 2625 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 2619 SimpleIdentifier methodName = parseSimpleIdentifier(); | 2626 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 2627 TypeParameterList typeParameters = _parseGenericCommentTypeParameters(); | |
| 2620 FormalParameterList parameters = parseFormalParameterList(); | 2628 FormalParameterList parameters = parseFormalParameterList(); |
| 2621 if (methodName.name == className) { | 2629 if (methodName.name == className) { |
| 2622 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type); | 2630 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type); |
| 2623 return _parseConstructor( | 2631 return _parseConstructor( |
| 2624 commentAndMetadata, | 2632 commentAndMetadata, |
| 2625 modifiers.externalKeyword, | 2633 modifiers.externalKeyword, |
| 2626 _validateModifiersForConstructor(modifiers), | 2634 _validateModifiersForConstructor(modifiers), |
| 2627 modifiers.factoryKeyword, | 2635 modifiers.factoryKeyword, |
| 2628 methodName, | 2636 methodName, |
| 2629 null, | 2637 null, |
| 2630 null, | 2638 null, |
| 2631 parameters); | 2639 parameters); |
| 2632 } | 2640 } |
| 2633 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 2641 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2634 _validateFormalParameterList(parameters); | 2642 _validateFormalParameterList(parameters); |
| 2635 return _parseMethodDeclarationAfterParameters( | 2643 return _parseMethodDeclarationAfterParameters( |
| 2636 commentAndMetadata, | 2644 commentAndMetadata, |
| 2637 modifiers.externalKeyword, | 2645 modifiers.externalKeyword, |
| 2638 modifiers.staticKeyword, | 2646 modifiers.staticKeyword, |
| 2639 type, | 2647 type, |
| 2640 methodName, | 2648 methodName, |
| 2641 null, | 2649 typeParameters, |
| 2642 parameters); | 2650 parameters); |
| 2643 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) { | 2651 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) { |
| 2644 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, | 2652 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, |
| 2645 modifiers.externalKeyword, modifiers.staticKeyword, type); | 2653 modifiers.externalKeyword, modifiers.staticKeyword, type); |
| 2646 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) { | 2654 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) { |
| 2647 // We have found "TypeName identifier {", and are guessing that this is a | 2655 // We have found "TypeName identifier {", and are guessing that this is a |
| 2648 // getter without the keyword 'get'. | 2656 // getter without the keyword 'get'. |
| 2649 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 2657 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2650 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET); | 2658 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET); |
| 2651 _currentToken = _injectToken( | 2659 _currentToken = _injectToken( |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3128 } | 3136 } |
| 3129 | 3137 |
| 3130 /** | 3138 /** |
| 3131 * Parse a function expression. Return the function expression that was | 3139 * Parse a function expression. Return the function expression that was |
| 3132 * parsed. | 3140 * parsed. |
| 3133 * | 3141 * |
| 3134 * functionExpression ::= | 3142 * functionExpression ::= |
| 3135 * typeParameters? formalParameterList functionExpressionBody | 3143 * typeParameters? formalParameterList functionExpressionBody |
| 3136 */ | 3144 */ |
| 3137 FunctionExpression parseFunctionExpression() { | 3145 FunctionExpression parseFunctionExpression() { |
| 3138 TypeParameterList typeParameters = null; | 3146 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 3139 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 3140 typeParameters = parseTypeParameterList(); | |
| 3141 } | |
| 3142 FormalParameterList parameters = parseFormalParameterList(); | 3147 FormalParameterList parameters = parseFormalParameterList(); |
| 3143 _validateFormalParameterList(parameters); | 3148 _validateFormalParameterList(parameters); |
| 3144 FunctionBody body = | 3149 FunctionBody body = |
| 3145 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true); | 3150 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true); |
| 3146 return new FunctionExpression(typeParameters, parameters, body); | 3151 return new FunctionExpression(typeParameters, parameters, body); |
| 3147 } | 3152 } |
| 3148 | 3153 |
| 3149 /** | 3154 /** |
| 3150 * Parse an if-null expression. Return the if-null expression that was | 3155 * Parse an if-null expression. Return the if-null expression that was |
| 3151 * parsed. | 3156 * parsed. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3258 NormalFormalParameter parseNormalFormalParameter() { | 3263 NormalFormalParameter parseNormalFormalParameter() { |
| 3259 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); | 3264 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 3260 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); | 3265 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); |
| 3261 Token thisKeyword = null; | 3266 Token thisKeyword = null; |
| 3262 Token period = null; | 3267 Token period = null; |
| 3263 if (_matchesKeyword(Keyword.THIS)) { | 3268 if (_matchesKeyword(Keyword.THIS)) { |
| 3264 thisKeyword = getAndAdvance(); | 3269 thisKeyword = getAndAdvance(); |
| 3265 period = _expect(TokenType.PERIOD); | 3270 period = _expect(TokenType.PERIOD); |
| 3266 } | 3271 } |
| 3267 SimpleIdentifier identifier = parseSimpleIdentifier(); | 3272 SimpleIdentifier identifier = parseSimpleIdentifier(); |
| 3268 TypeParameterList typeParameters = null; | 3273 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 3269 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 3270 typeParameters = parseTypeParameterList(); | |
| 3271 } | |
| 3272 if (_matches(TokenType.OPEN_PAREN)) { | 3274 if (_matches(TokenType.OPEN_PAREN)) { |
| 3273 FormalParameterList parameters = parseFormalParameterList(); | 3275 FormalParameterList parameters = parseFormalParameterList(); |
| 3274 if (thisKeyword == null) { | 3276 if (thisKeyword == null) { |
| 3275 if (holder.keyword != null) { | 3277 if (holder.keyword != null) { |
| 3276 _reportErrorForToken( | 3278 _reportErrorForToken( |
| 3277 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); | 3279 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); |
| 3278 } | 3280 } |
| 3279 return new FunctionTypedFormalParameter( | 3281 return new FunctionTypedFormalParameter( |
| 3280 commentAndMetadata.comment, | 3282 commentAndMetadata.comment, |
| 3281 commentAndMetadata.metadata, | 3283 commentAndMetadata.metadata, |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3469 return new TypeArgumentList(leftBracket, arguments, rightBracket); | 3471 return new TypeArgumentList(leftBracket, arguments, rightBracket); |
| 3470 } | 3472 } |
| 3471 | 3473 |
| 3472 /** | 3474 /** |
| 3473 * Parse a type name. Return the type name that was parsed. | 3475 * Parse a type name. Return the type name that was parsed. |
| 3474 * | 3476 * |
| 3475 * type ::= | 3477 * type ::= |
| 3476 * qualified typeArguments? | 3478 * qualified typeArguments? |
| 3477 */ | 3479 */ |
| 3478 TypeName parseTypeName() { | 3480 TypeName parseTypeName() { |
| 3481 TypeName result = _parseTypeName(); | |
| 3482 // If this is followed by a generic method type comment, allow the comment | |
| 3483 // type to replace the real type name. | |
| 3484 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to | |
| 3485 // only work inside generic methods? | |
|
Jennifer Messerly
2015/11/11 18:28:06
This feature weirds me out. I kind of wonder if it
Brian Wilkerson
2015/11/11 21:53:42
Given that this only applies to return types and p
Paul Berry
2015/11/11 22:01:58
I would think it could potentially apply to other
Jennifer Messerly
2015/11/11 22:04:12
EDIT: Paul beat me to it. But here was my comment.
| |
| 3486 if (_injectGenericCommentTypeAssign()) { | |
| 3487 return _parseTypeName(); | |
| 3488 } | |
| 3489 return result; | |
| 3490 } | |
| 3491 | |
| 3492 TypeName _parseTypeName() { | |
| 3479 Identifier typeName; | 3493 Identifier typeName; |
| 3480 if (_matchesKeyword(Keyword.VAR)) { | 3494 if (_matchesKeyword(Keyword.VAR)) { |
| 3481 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); | 3495 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); |
| 3482 typeName = new SimpleIdentifier(getAndAdvance()); | 3496 typeName = new SimpleIdentifier(getAndAdvance()); |
| 3483 } else if (_matchesIdentifier()) { | 3497 } else if (_matchesIdentifier()) { |
| 3484 typeName = parsePrefixedIdentifier(); | 3498 typeName = parsePrefixedIdentifier(); |
| 3485 } else { | 3499 } else { |
| 3486 typeName = _createSyntheticIdentifier(); | 3500 typeName = _createSyntheticIdentifier(); |
| 3487 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); | 3501 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); |
| 3488 } | 3502 } |
| 3489 TypeArgumentList typeArguments = null; | 3503 TypeArgumentList typeArguments = _maybeParseTypeArguments(); |
| 3490 if (_matches(TokenType.LT)) { | |
| 3491 typeArguments = parseTypeArgumentList(); | |
| 3492 } | |
| 3493 return new TypeName(typeName, typeArguments); | 3504 return new TypeName(typeName, typeArguments); |
| 3494 } | 3505 } |
| 3495 | 3506 |
| 3496 /** | 3507 /** |
| 3497 * Parse a type parameter. Return the type parameter that was parsed. | 3508 * Parse a type parameter. Return the type parameter that was parsed. |
| 3498 * | 3509 * |
| 3499 * typeParameter ::= | 3510 * typeParameter ::= |
| 3500 * metadata name ('extends' bound)? | 3511 * metadata name ('extends' bound)? |
| 3501 */ | 3512 */ |
| 3502 TypeParameter parseTypeParameter() { | 3513 TypeParameter parseTypeParameter() { |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3902 * either the given token is not a begin token or it does not have an end | 3913 * either the given token is not a begin token or it does not have an end |
| 3903 * token associated with it. | 3914 * token associated with it. |
| 3904 */ | 3915 */ |
| 3905 Token _getEndToken(Token beginToken) { | 3916 Token _getEndToken(Token beginToken) { |
| 3906 if (beginToken is BeginToken) { | 3917 if (beginToken is BeginToken) { |
| 3907 return beginToken.endToken; | 3918 return beginToken.endToken; |
| 3908 } | 3919 } |
| 3909 return null; | 3920 return null; |
| 3910 } | 3921 } |
| 3911 | 3922 |
| 3923 bool _injectGenericComment(TokenType type, int prefixLen) { | |
| 3924 if (parseGenericMethodComments) { | |
|
Jennifer Messerly
2015/11/11 18:28:06
as noted above, this guard shouldn't really be nec
| |
| 3925 CommentToken t = _currentToken.precedingComments; | |
| 3926 for (; t != null; t = t.next) { | |
| 3927 if (t.type == TokenType.GENERIC_METHOD_TYPE_LIST) { | |
|
Jennifer Messerly
2015/11/11 20:52:27
Bug here. the /*=T*/ comments weren't working beca
| |
| 3928 String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2); | |
| 3929 Token list = _scanGenericMethodComment(comment, t.offset + prefixLen); | |
|
Paul Berry
2015/11/11 19:26:53
What will happen if the comment is matched by Scan
Jennifer Messerly
2015/11/11 19:30:25
Should be exactly as if you wrote that without the
| |
| 3930 if (list != null) { | |
| 3931 // TODO(jmesserly): detach the old comment token? | |
|
Brian Wilkerson
2015/11/11 21:53:42
It shouldn't actually hurt anything if you leave i
Jennifer Messerly
2015/11/12 00:20:00
Sounds good. Removed the TODO.
| |
| 3932 // Insert the tokens into the stream. | |
| 3933 _injectTokenList(list); | |
| 3934 return true; | |
| 3935 } | |
| 3936 } | |
| 3937 } | |
| 3938 } | |
| 3939 return false; | |
| 3940 } | |
| 3941 | |
| 3942 /** | |
| 3943 * Matches a generic comment type substitution and injects it into the token | |
|
Jennifer Messerly
2015/11/11 18:28:06
oops, fixed this locally. Not sure how it happened
| |
| 3944 * stream. Returns true if a match was injected, otherwise false. | |
| 3945 * | |
| 3946 * These comments are of the form `/*=T*/`, in other words, a [TypeName] | |
| 3947 * inside a slash-star comment, preceded by equals sign. | |
| 3948 */ | |
| 3949 bool _injectGenericCommentTypeAssign() { | |
| 3950 return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_ASSIGN, 3); | |
| 3951 } | |
| 3952 | |
| 3953 /** | |
| 3954 * Matches a generic comment type parameters and injects them into the token | |
| 3955 * stream. Returns true if a match was injected, otherwise false. | |
| 3956 * | |
| 3957 * These comments are of the form `/*<K, V>*/`, in other words, a | |
| 3958 * [TypeParameterList] or [TypeArgumentList] inside a slash-star comment. | |
| 3959 */ | |
| 3960 bool _injectGenericCommentTypeList() { | |
| 3961 return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_LIST, 2); | |
| 3962 } | |
| 3963 | |
| 3912 /** | 3964 /** |
| 3913 * Inject the given [token] into the token stream immediately before the | 3965 * Inject the given [token] into the token stream immediately before the |
| 3914 * current token. | 3966 * current token. |
| 3915 */ | 3967 */ |
| 3916 Token _injectToken(Token token) { | 3968 Token _injectToken(Token token) { |
| 3917 Token previous = _currentToken.previous; | 3969 Token previous = _currentToken.previous; |
| 3918 token.setNext(_currentToken); | 3970 token.setNext(_currentToken); |
| 3919 previous.setNext(token); | 3971 previous.setNext(token); |
| 3920 return token; | 3972 return token; |
| 3921 } | 3973 } |
| 3922 | 3974 |
| 3975 void _injectTokenList(Token firstToken) { | |
|
Jennifer Messerly
2015/11/11 18:28:06
I used the same pattern as the existing _injectTok
| |
| 3976 // Scanner creates a cyclic EOF token. | |
| 3977 Token lastToken = firstToken; | |
| 3978 while (lastToken.next.type != TokenType.EOF) { | |
| 3979 lastToken = lastToken.next; | |
| 3980 } | |
| 3981 // Inject these new tokens into the stream. | |
| 3982 Token previous = _currentToken.previous; | |
| 3983 lastToken.setNext(_currentToken); | |
| 3984 previous.setNext(firstToken); | |
| 3985 _currentToken = firstToken; | |
| 3986 } | |
| 3987 | |
| 3923 /** | 3988 /** |
| 3924 * Return `true` if the current token appears to be the beginning of a | 3989 * Return `true` if the current token appears to be the beginning of a |
| 3925 * function declaration. | 3990 * function declaration. |
| 3926 */ | 3991 */ |
| 3927 bool _isFunctionDeclaration() { | 3992 bool _isFunctionDeclaration() { |
| 3928 if (_matchesKeyword(Keyword.VOID)) { | 3993 if (_matchesKeyword(Keyword.VOID)) { |
| 3929 return true; | 3994 return true; |
| 3930 } | 3995 } |
| 3931 Token afterReturnType = _skipTypeName(_currentToken); | 3996 Token afterReturnType = _skipTypeName(_currentToken); |
| 3932 if (afterReturnType == null) { | 3997 if (afterReturnType == null) { |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4264 _tokenMatchesKeyword(_currentToken, keyword); | 4329 _tokenMatchesKeyword(_currentToken, keyword); |
| 4265 | 4330 |
| 4266 /** | 4331 /** |
| 4267 * Return `true` if the current token matches the given [identifier]. | 4332 * Return `true` if the current token matches the given [identifier]. |
| 4268 */ | 4333 */ |
| 4269 bool _matchesString(String identifier) => | 4334 bool _matchesString(String identifier) => |
| 4270 _currentToken.type == TokenType.IDENTIFIER && | 4335 _currentToken.type == TokenType.IDENTIFIER && |
| 4271 _currentToken.lexeme == identifier; | 4336 _currentToken.lexeme == identifier; |
| 4272 | 4337 |
| 4273 /** | 4338 /** |
| 4339 * Parse a [TypeArgumentList] if present, otherwise return null. | |
| 4340 * This also supports the comment form, if enabled: `/*<T>*/` | |
| 4341 */ | |
| 4342 TypeArgumentList _maybeParseTypeArguments() { | |
|
Brian Wilkerson
2015/11/11 21:53:42
For consistency with "_parseOptionalReturnType", p
Jennifer Messerly
2015/11/12 00:20:00
Done.
| |
| 4343 if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) { | |
| 4344 return parseTypeArgumentList(); | |
| 4345 } | |
| 4346 return null; | |
| 4347 } | |
| 4348 | |
| 4349 /** | |
| 4274 * If the current token has the given [type], then advance to the next token | 4350 * If the current token has the given [type], then advance to the next token |
| 4275 * and return `true`. Otherwise, return `false` without advancing. This method | 4351 * and return `true`. Otherwise, return `false` without advancing. This method |
| 4276 * should not be invoked with an argument value of [TokenType.GT]. | 4352 * should not be invoked with an argument value of [TokenType.GT]. |
| 4277 */ | 4353 */ |
| 4278 bool _optional(TokenType type) { | 4354 bool _optional(TokenType type) { |
| 4279 if (_matches(type)) { | 4355 if (_matches(type)) { |
| 4280 _advance(); | 4356 _advance(); |
| 4281 return true; | 4357 return true; |
| 4282 } | 4358 } |
| 4283 return false; | 4359 return false; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4354 } | 4430 } |
| 4355 // | 4431 // |
| 4356 // A primary expression can start with an identifier. We resolve the | 4432 // A primary expression can start with an identifier. We resolve the |
| 4357 // ambiguity by determining whether the primary consists of anything other | 4433 // ambiguity by determining whether the primary consists of anything other |
| 4358 // than an identifier and/or is followed by an assignableSelector. | 4434 // than an identifier and/or is followed by an assignableSelector. |
| 4359 // | 4435 // |
| 4360 Expression expression = _parsePrimaryExpression(); | 4436 Expression expression = _parsePrimaryExpression(); |
| 4361 bool isOptional = primaryAllowed || expression is SimpleIdentifier; | 4437 bool isOptional = primaryAllowed || expression is SimpleIdentifier; |
| 4362 while (true) { | 4438 while (true) { |
| 4363 while (_isLikelyParameterList()) { | 4439 while (_isLikelyParameterList()) { |
| 4364 TypeArgumentList typeArguments = null; | 4440 TypeArgumentList typeArguments = _maybeParseTypeArguments(); |
| 4365 if (_matches(TokenType.LT)) { | |
| 4366 typeArguments = parseTypeArgumentList(); | |
| 4367 } | |
| 4368 ArgumentList argumentList = parseArgumentList(); | 4441 ArgumentList argumentList = parseArgumentList(); |
| 4369 if (expression is SimpleIdentifier) { | 4442 if (expression is SimpleIdentifier) { |
| 4370 expression = new MethodInvocation(null, null, | 4443 expression = new MethodInvocation(null, null, |
| 4371 expression as SimpleIdentifier, typeArguments, argumentList); | 4444 expression as SimpleIdentifier, typeArguments, argumentList); |
| 4372 } else if (expression is PrefixedIdentifier) { | 4445 } else if (expression is PrefixedIdentifier) { |
| 4373 PrefixedIdentifier identifier = expression as PrefixedIdentifier; | 4446 PrefixedIdentifier identifier = expression as PrefixedIdentifier; |
| 4374 expression = new MethodInvocation( | 4447 expression = new MethodInvocation( |
| 4375 identifier.prefix, | 4448 identifier.prefix, |
| 4376 identifier.period, | 4449 identifier.period, |
| 4377 identifier.identifier, | 4450 identifier.identifier, |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4566 } | 4639 } |
| 4567 } else { | 4640 } else { |
| 4568 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, | 4641 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, |
| 4569 [_currentToken.lexeme]); | 4642 [_currentToken.lexeme]); |
| 4570 functionName = _createSyntheticIdentifier(); | 4643 functionName = _createSyntheticIdentifier(); |
| 4571 } | 4644 } |
| 4572 assert((expression == null && functionName != null) || | 4645 assert((expression == null && functionName != null) || |
| 4573 (expression != null && functionName == null)); | 4646 (expression != null && functionName == null)); |
| 4574 if (_isLikelyParameterList()) { | 4647 if (_isLikelyParameterList()) { |
| 4575 while (_isLikelyParameterList()) { | 4648 while (_isLikelyParameterList()) { |
| 4576 TypeArgumentList typeArguments = null; | 4649 TypeArgumentList typeArguments = _maybeParseTypeArguments(); |
| 4577 if (_matches(TokenType.LT)) { | |
| 4578 typeArguments = parseTypeArgumentList(); | |
| 4579 } | |
| 4580 if (functionName != null) { | 4650 if (functionName != null) { |
| 4581 expression = new MethodInvocation(expression, period, functionName, | 4651 expression = new MethodInvocation(expression, period, functionName, |
| 4582 typeArguments, parseArgumentList()); | 4652 typeArguments, parseArgumentList()); |
| 4583 period = null; | 4653 period = null; |
| 4584 functionName = null; | 4654 functionName = null; |
| 4585 } else if (expression == null) { | 4655 } else if (expression == null) { |
| 4586 // It should not be possible to get here. | 4656 // It should not be possible to get here. |
| 4587 expression = new MethodInvocation(expression, period, | 4657 expression = new MethodInvocation(expression, period, |
| 4588 _createSyntheticIdentifier(), typeArguments, parseArgumentList()); | 4658 _createSyntheticIdentifier(), typeArguments, parseArgumentList()); |
| 4589 } else { | 4659 } else { |
| 4590 expression = new FunctionExpressionInvocation( | 4660 expression = new FunctionExpressionInvocation( |
| 4591 expression, typeArguments, parseArgumentList()); | 4661 expression, typeArguments, parseArgumentList()); |
| 4592 } | 4662 } |
| 4593 } | 4663 } |
| 4594 } else if (functionName != null) { | 4664 } else if (functionName != null) { |
| 4595 expression = new PropertyAccess(expression, period, functionName); | 4665 expression = new PropertyAccess(expression, period, functionName); |
| 4596 period = null; | 4666 period = null; |
| 4597 } | 4667 } |
| 4598 assert(expression != null); | 4668 assert(expression != null); |
| 4599 bool progress = true; | 4669 bool progress = true; |
| 4600 while (progress) { | 4670 while (progress) { |
| 4601 progress = false; | 4671 progress = false; |
| 4602 Expression selector = _parseAssignableSelector(expression, true); | 4672 Expression selector = _parseAssignableSelector(expression, true); |
| 4603 if (!identical(selector, expression)) { | 4673 if (!identical(selector, expression)) { |
| 4604 expression = selector; | 4674 expression = selector; |
| 4605 progress = true; | 4675 progress = true; |
| 4606 while (_isLikelyParameterList()) { | 4676 while (_isLikelyParameterList()) { |
| 4607 TypeArgumentList typeArguments = null; | 4677 TypeArgumentList typeArguments = _maybeParseTypeArguments(); |
| 4608 if (_matches(TokenType.LT)) { | |
| 4609 typeArguments = parseTypeArgumentList(); | |
| 4610 } | |
| 4611 if (expression is PropertyAccess) { | 4678 if (expression is PropertyAccess) { |
| 4612 PropertyAccess propertyAccess = expression as PropertyAccess; | 4679 PropertyAccess propertyAccess = expression as PropertyAccess; |
| 4613 expression = new MethodInvocation( | 4680 expression = new MethodInvocation( |
| 4614 propertyAccess.target, | 4681 propertyAccess.target, |
| 4615 propertyAccess.operator, | 4682 propertyAccess.operator, |
| 4616 propertyAccess.propertyName, | 4683 propertyAccess.propertyName, |
| 4617 typeArguments, | 4684 typeArguments, |
| 4618 parseArgumentList()); | 4685 parseArgumentList()); |
| 4619 } else { | 4686 } else { |
| 4620 expression = new FunctionExpressionInvocation( | 4687 expression = new FunctionExpressionInvocation( |
| (...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6018 bool isGetter = false; | 6085 bool isGetter = false; |
| 6019 if (_matchesKeyword(Keyword.GET) && | 6086 if (_matchesKeyword(Keyword.GET) && |
| 6020 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 6087 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 6021 keyword = getAndAdvance(); | 6088 keyword = getAndAdvance(); |
| 6022 isGetter = true; | 6089 isGetter = true; |
| 6023 } else if (_matchesKeyword(Keyword.SET) && | 6090 } else if (_matchesKeyword(Keyword.SET) && |
| 6024 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 6091 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 6025 keyword = getAndAdvance(); | 6092 keyword = getAndAdvance(); |
| 6026 } | 6093 } |
| 6027 SimpleIdentifier name = parseSimpleIdentifier(); | 6094 SimpleIdentifier name = parseSimpleIdentifier(); |
| 6028 TypeParameterList typeParameters = null; | 6095 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 6029 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 6030 typeParameters = parseTypeParameterList(); | |
| 6031 } | |
| 6032 FormalParameterList parameters = null; | 6096 FormalParameterList parameters = null; |
| 6033 if (!isGetter) { | 6097 if (!isGetter) { |
| 6034 if (_matches(TokenType.OPEN_PAREN)) { | 6098 if (_matches(TokenType.OPEN_PAREN)) { |
| 6035 parameters = parseFormalParameterList(); | 6099 parameters = parseFormalParameterList(); |
| 6036 _validateFormalParameterList(parameters); | 6100 _validateFormalParameterList(parameters); |
| 6037 } else { | 6101 } else { |
| 6038 _reportErrorForCurrentToken( | 6102 _reportErrorForCurrentToken( |
| 6039 ParserErrorCode.MISSING_FUNCTION_PARAMETERS); | 6103 ParserErrorCode.MISSING_FUNCTION_PARAMETERS); |
| 6040 parameters = new FormalParameterList( | 6104 parameters = new FormalParameterList( |
| 6041 _createSyntheticToken(TokenType.OPEN_PAREN), | 6105 _createSyntheticToken(TokenType.OPEN_PAREN), |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6175 commentAndMetadata.metadata, | 6239 commentAndMetadata.metadata, |
| 6176 keyword, | 6240 keyword, |
| 6177 returnType, | 6241 returnType, |
| 6178 name, | 6242 name, |
| 6179 typeParameters, | 6243 typeParameters, |
| 6180 parameters, | 6244 parameters, |
| 6181 semicolon); | 6245 semicolon); |
| 6182 } | 6246 } |
| 6183 | 6247 |
| 6184 /** | 6248 /** |
| 6249 * Parses generic type parameters from a comment. | |
| 6250 * | |
| 6251 * Normally this is handled by [_parseGenericMethodTypeParameters], but if t he | |
|
Jennifer Messerly
2015/11/11 18:28:06
fixed this locally, will be in next upload
| |
| 6252 * code already handles the normal generic type parameters, the comment | |
| 6253 * matcher can be called directly. For example, we may have already tried | |
| 6254 * matching `<` (less than sign) in a method declaration, and be currently | |
| 6255 * on the `(` (open paren) because we didn't find it. In that case, this | |
| 6256 * function will parse the preceding comment such as `/*<T, R>*/`. | |
| 6257 */ | |
| 6258 TypeParameterList _parseGenericCommentTypeParameters() { | |
| 6259 if (_injectGenericCommentTypeList()) { | |
| 6260 return parseTypeParameterList(); | |
| 6261 } | |
| 6262 return null; | |
| 6263 } | |
| 6264 | |
| 6265 /** | |
| 6266 * Parse the generic method or function's type parameters. | |
| 6267 * | |
| 6268 * For backwards compatibility this can optionally use comments. | |
| 6269 * See [parseGenericMethodComments]. | |
| 6270 */ | |
| 6271 TypeParameterList _parseGenericMethodTypeParameters() { | |
| 6272 if (parseGenericMethods && _matches(TokenType.LT) || | |
| 6273 _injectGenericCommentTypeList()) { | |
| 6274 return parseTypeParameterList(); | |
| 6275 } | |
| 6276 } | |
| 6277 | |
| 6278 /** | |
| 6185 * Parse a getter. The [commentAndMetadata] is the documentation comment and | 6279 * Parse a getter. The [commentAndMetadata] is the documentation comment and |
| 6186 * metadata to be associated with the declaration. The externalKeyword] is the | 6280 * metadata to be associated with the declaration. The externalKeyword] is the |
| 6187 * 'external' token. The staticKeyword] is the static keyword, or `null` if | 6281 * '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 | 6282 * 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 | 6283 * been parsed, or `null` if there was no return type. Return the getter that |
| 6190 * was parsed. | 6284 * was parsed. |
| 6191 * | 6285 * |
| 6192 * getter ::= | 6286 * getter ::= |
| 6193 * getterSignature functionBody? | 6287 * getterSignature functionBody? |
| 6194 * | 6288 * |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6466 /** | 6560 /** |
| 6467 * Parse a list or map literal. The [modifier] is the 'const' modifier | 6561 * 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 | 6562 * appearing before the literal, or `null` if there is no modifier. Return the |
| 6469 * list or map literal that was parsed. | 6563 * list or map literal that was parsed. |
| 6470 * | 6564 * |
| 6471 * listOrMapLiteral ::= | 6565 * listOrMapLiteral ::= |
| 6472 * listLiteral | 6566 * listLiteral |
| 6473 * | mapLiteral | 6567 * | mapLiteral |
| 6474 */ | 6568 */ |
| 6475 TypedLiteral _parseListOrMapLiteral(Token modifier) { | 6569 TypedLiteral _parseListOrMapLiteral(Token modifier) { |
| 6476 TypeArgumentList typeArguments = null; | 6570 TypeArgumentList typeArguments = _maybeParseTypeArguments(); |
| 6477 if (_matches(TokenType.LT)) { | |
| 6478 typeArguments = parseTypeArgumentList(); | |
| 6479 } | |
| 6480 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { | 6571 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 6481 return _parseMapLiteral(modifier, typeArguments); | 6572 return _parseMapLiteral(modifier, typeArguments); |
| 6482 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || | 6573 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || |
| 6483 _matches(TokenType.INDEX)) { | 6574 _matches(TokenType.INDEX)) { |
| 6484 return _parseListLiteral(modifier, typeArguments); | 6575 return _parseListLiteral(modifier, typeArguments); |
| 6485 } | 6576 } |
| 6486 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL); | 6577 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL); |
| 6487 return new ListLiteral( | 6578 return new ListLiteral( |
| 6488 modifier, | 6579 modifier, |
| 6489 typeArguments, | 6580 typeArguments, |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6603 * functionDeclaration ::= | 6694 * functionDeclaration ::= |
| 6604 * 'external'? 'static'? functionSignature functionBody | 6695 * 'external'? 'static'? functionSignature functionBody |
| 6605 * | 'external'? functionSignature ';' | 6696 * | 'external'? functionSignature ';' |
| 6606 */ | 6697 */ |
| 6607 MethodDeclaration _parseMethodDeclarationAfterReturnType( | 6698 MethodDeclaration _parseMethodDeclarationAfterReturnType( |
| 6608 CommentAndMetadata commentAndMetadata, | 6699 CommentAndMetadata commentAndMetadata, |
| 6609 Token externalKeyword, | 6700 Token externalKeyword, |
| 6610 Token staticKeyword, | 6701 Token staticKeyword, |
| 6611 TypeName returnType) { | 6702 TypeName returnType) { |
| 6612 SimpleIdentifier methodName = parseSimpleIdentifier(); | 6703 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 6613 TypeParameterList typeParameters = null; | 6704 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 6614 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 6615 typeParameters = parseTypeParameterList(); | |
| 6616 } | |
| 6617 FormalParameterList parameters; | 6705 FormalParameterList parameters; |
| 6618 if (!_matches(TokenType.OPEN_PAREN) && | 6706 if (!_matches(TokenType.OPEN_PAREN) && |
| 6619 (_matches(TokenType.OPEN_CURLY_BRACKET) || | 6707 (_matches(TokenType.OPEN_CURLY_BRACKET) || |
| 6620 _matches(TokenType.FUNCTION))) { | 6708 _matches(TokenType.FUNCTION))) { |
| 6621 _reportErrorForToken( | 6709 _reportErrorForToken( |
| 6622 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous); | 6710 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous); |
| 6623 parameters = new FormalParameterList( | 6711 parameters = new FormalParameterList( |
| 6624 _createSyntheticToken(TokenType.OPEN_PAREN), | 6712 _createSyntheticToken(TokenType.OPEN_PAREN), |
| 6625 null, | 6713 null, |
| 6626 null, | 6714 null, |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7074 */ | 7162 */ |
| 7075 Expression _parsePostfixExpression() { | 7163 Expression _parsePostfixExpression() { |
| 7076 Expression operand = _parseAssignableExpression(true); | 7164 Expression operand = _parseAssignableExpression(true); |
| 7077 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || | 7165 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || |
| 7078 _matches(TokenType.PERIOD) || | 7166 _matches(TokenType.PERIOD) || |
| 7079 _matches(TokenType.QUESTION_PERIOD) || | 7167 _matches(TokenType.QUESTION_PERIOD) || |
| 7080 _matches(TokenType.OPEN_PAREN) || | 7168 _matches(TokenType.OPEN_PAREN) || |
| 7081 (parseGenericMethods && _matches(TokenType.LT))) { | 7169 (parseGenericMethods && _matches(TokenType.LT))) { |
| 7082 do { | 7170 do { |
| 7083 if (_isLikelyParameterList()) { | 7171 if (_isLikelyParameterList()) { |
| 7084 TypeArgumentList typeArguments = null; | 7172 TypeArgumentList typeArguments = _maybeParseTypeArguments(); |
| 7085 if (_matches(TokenType.LT)) { | |
| 7086 typeArguments = parseTypeArgumentList(); | |
| 7087 } | |
| 7088 ArgumentList argumentList = parseArgumentList(); | 7173 ArgumentList argumentList = parseArgumentList(); |
| 7089 if (operand is PropertyAccess) { | 7174 if (operand is PropertyAccess) { |
| 7090 PropertyAccess access = operand as PropertyAccess; | 7175 PropertyAccess access = operand as PropertyAccess; |
| 7091 operand = new MethodInvocation(access.target, access.operator, | 7176 operand = new MethodInvocation(access.target, access.operator, |
| 7092 access.propertyName, typeArguments, argumentList); | 7177 access.propertyName, typeArguments, argumentList); |
| 7093 } else { | 7178 } else { |
| 7094 operand = new FunctionExpressionInvocation( | 7179 operand = new FunctionExpressionInvocation( |
| 7095 operand, typeArguments, argumentList); | 7180 operand, typeArguments, argumentList); |
| 7096 } | 7181 } |
| 7097 } else { | 7182 } else { |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8077 void _reportErrorForToken(ErrorCode errorCode, Token token, | 8162 void _reportErrorForToken(ErrorCode errorCode, Token token, |
| 8078 [List<Object> arguments]) { | 8163 [List<Object> arguments]) { |
| 8079 if (token.type == TokenType.EOF) { | 8164 if (token.type == TokenType.EOF) { |
| 8080 token = token.previous; | 8165 token = token.previous; |
| 8081 } | 8166 } |
| 8082 _reportError(new AnalysisError(_source, token.offset, | 8167 _reportError(new AnalysisError(_source, token.offset, |
| 8083 math.max(token.length, 1), errorCode, arguments)); | 8168 math.max(token.length, 1), errorCode, arguments)); |
| 8084 } | 8169 } |
| 8085 | 8170 |
| 8086 /** | 8171 /** |
| 8172 * Scans the generic method comment, and returns the tokens, otherwise | |
| 8173 * returns null. | |
| 8174 */ | |
| 8175 Token _scanGenericMethodComment(String code, int offset) { | |
| 8176 BooleanErrorListener listener = new BooleanErrorListener(); | |
| 8177 Scanner scanner = | |
| 8178 new Scanner(null, new SubSequenceReader(code, offset), listener); | |
| 8179 scanner.setSourceStart(1, 1); | |
| 8180 Token firstToken = scanner.tokenize(); | |
| 8181 if (listener.errorReported) { | |
| 8182 // TODO(jmesserly): should we report these messages? | |
|
Brian Wilkerson
2015/11/11 21:53:42
It would help you find bugs while using this featu
Jennifer Messerly
2015/11/12 00:20:00
Good point. Removed the TODO.
| |
| 8183 return null; | |
| 8184 } | |
| 8185 return firstToken; | |
| 8186 } | |
| 8187 | |
| 8188 /** | |
| 8087 * Skips a block with all containing blocks. | 8189 * Skips a block with all containing blocks. |
| 8088 */ | 8190 */ |
| 8089 void _skipBlock() { | 8191 void _skipBlock() { |
| 8090 Token endToken = (_currentToken as BeginToken).endToken; | 8192 Token endToken = (_currentToken as BeginToken).endToken; |
| 8091 if (endToken == null) { | 8193 if (endToken == null) { |
| 8092 endToken = _currentToken.next; | 8194 endToken = _currentToken.next; |
| 8093 while (!identical(endToken, _currentToken)) { | 8195 while (!identical(endToken, _currentToken)) { |
| 8094 _currentToken = endToken; | 8196 _currentToken = endToken; |
| 8095 endToken = _currentToken.next; | 8197 endToken = _currentToken.next; |
| 8096 } | 8198 } |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8413 * This method must be kept in sync with [parseTypeArgumentList]. | 8515 * This method must be kept in sync with [parseTypeArgumentList]. |
| 8414 * | 8516 * |
| 8415 * typeArguments ::= | 8517 * typeArguments ::= |
| 8416 * '<' typeList '>' | 8518 * '<' typeList '>' |
| 8417 * | 8519 * |
| 8418 * typeList ::= | 8520 * typeList ::= |
| 8419 * type (',' type)* | 8521 * type (',' type)* |
| 8420 */ | 8522 */ |
| 8421 Token _skipTypeArgumentList(Token startToken) { | 8523 Token _skipTypeArgumentList(Token startToken) { |
| 8422 Token token = startToken; | 8524 Token token = startToken; |
| 8423 if (!_tokenMatches(token, TokenType.LT)) { | 8525 if (!_tokenMatches(token, TokenType.LT) && |
| 8526 !_injectGenericCommentTypeList()) { | |
| 8424 return null; | 8527 return null; |
| 8425 } | 8528 } |
| 8426 token = _skipTypeName(token.next); | 8529 token = _skipTypeName(token.next); |
| 8427 if (token == null) { | 8530 if (token == null) { |
| 8428 // If the start token '<' is followed by '>' | 8531 // If the start token '<' is followed by '>' |
| 8429 // then assume this should be type argument list but is missing a type | 8532 // then assume this should be type argument list but is missing a type |
| 8430 token = startToken.next; | 8533 token = startToken.next; |
| 8431 if (_tokenMatches(token, TokenType.GT)) { | 8534 if (_tokenMatches(token, TokenType.GT)) { |
| 8432 return token.next; | 8535 return token.next; |
| 8433 } | 8536 } |
| (...skipping 2619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11053 } | 11156 } |
| 11054 | 11157 |
| 11055 /** | 11158 /** |
| 11056 * Copy resolution data from the [fromNode] to the [toNode]. | 11159 * Copy resolution data from the [fromNode] to the [toNode]. |
| 11057 */ | 11160 */ |
| 11058 static void copyResolutionData(AstNode fromNode, AstNode toNode) { | 11161 static void copyResolutionData(AstNode fromNode, AstNode toNode) { |
| 11059 ResolutionCopier copier = new ResolutionCopier(); | 11162 ResolutionCopier copier = new ResolutionCopier(); |
| 11060 copier._isEqualNodes(fromNode, toNode); | 11163 copier._isEqualNodes(fromNode, toNode); |
| 11061 } | 11164 } |
| 11062 } | 11165 } |
| OLD | NEW |