Chromium Code Reviews| Index: pkg/front_end/lib/src/fasta/parser/parser.dart |
| diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart |
| index f323b4519c356cb29e55355deacd0e461ec1286a..229b72eaf4c8bf1c97a1eea4ccc7931af8f9b5a5 100644 |
| --- a/pkg/front_end/lib/src/fasta/parser/parser.dart |
| +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart |
| @@ -726,6 +726,7 @@ class Parser { |
| // Function type without return type. |
| return parseType(token); |
| } |
| + token = _injectGenericCommentTypeAssign(token); |
|
ahe
2017/04/06 08:58:38
Methods in the parser needs to be public so they c
ahe
2017/04/06 10:04:42
See CL 2799043004 for a detailed explanation.
scheglov
2017/04/06 16:15:55
I moved these methods to Listener.
|
| Token peek = peekAfterIfType(token); |
| if (peek != null && (peek.isIdentifier() || optional('this', peek))) { |
| return parseType(token); |
| @@ -2405,6 +2406,12 @@ class Parser { |
| Token identifier = peekIdentifierAfterType(token); |
| if (identifier != null) { |
| assert(identifier.isIdentifier()); |
| + |
| + // If the identifier token has a type substitution comment /*=T*/, |
| + // then the set of tokens type tokens should be replaced with the |
| + // tokens parsed from the comment. |
| + token = _replaceTokenWithGenericCommentTypeAssign(token, identifier); |
| + |
| Token afterId = identifier.next; |
| int afterIdKind = afterId.kind; |
| if (identical(afterIdKind, EQ_TOKEN) || |
| @@ -2489,6 +2496,7 @@ class Parser { |
| if (isModifier(token.next)) { |
| return parseVariablesDeclaration(token); |
| } |
| + _injectGenericCommentTypeAssign(token.next); |
| Token identifier = peekIdentifierAfterOptionalType(token.next); |
| if (identifier != null) { |
| assert(identifier.isIdentifier()); |
| @@ -3310,6 +3318,13 @@ class Parser { |
| Token token, bool endWithSemicolon) { |
| int count = 1; |
| token = parseMetadataStar(token); |
| + |
| + // If the next token has a type substitution comment /*=T*/, then |
| + // the current 'var' token should be repealed and replaced. |
| + if (token.keyword == Keyword.VAR) { |
|
ahe
2017/04/06 08:58:38
Use this method to match keywords:
optional('var'
ahe
2017/04/06 10:04:42
See lines 178-184.
scheglov
2017/04/06 16:15:55
Done.
|
| + token = _replaceTokenWithGenericCommentTypeAssign(token, token.next); |
| + } |
| + |
| token = parseModifiers(token); |
| token = parseTypeOpt(token); |
| listener.beginVariablesDeclaration(token); |
| @@ -3803,6 +3818,12 @@ class Parser { |
| token, () => code.format(uri, token.charOffset, string)); |
| } |
| + /// Matches a generic comment type substitution and injects it into the token |
| + /// stream before the given [token]. |
| + Token _injectGenericCommentTypeAssign(Token token) { |
| + return _injectGenericComment(token, GENERIC_METHOD_TYPE_ASSIGN, 3); |
| + } |
| + |
| /// Matches a generic comment type parameters or type arguments and injects |
| /// them into the token stream before the given [token]. |
| Token _injectGenericCommentTypeList(Token token) { |
| @@ -3855,6 +3876,23 @@ class Parser { |
| previous.setNext(firstToken); |
| beforeToken = firstToken; |
| } |
| + |
| + /// If the [tokenWithComment] has a type substitution comment /*=T*/, then |
| + /// the comment should be scanned into new tokens, and these tokens inserted |
| + /// instead of tokens from the [tokenToStartReplacing] to the |
| + /// [tokenWithComment]. Returns the first newly inserted token, or the |
| + /// original [tokenWithComment]. |
| + Token _replaceTokenWithGenericCommentTypeAssign( |
| + Token tokenToStartReplacing, Token tokenWithComment) { |
| + Token injected = _injectGenericCommentTypeAssign(tokenWithComment); |
| + if (!identical(injected, tokenWithComment)) { |
| + Token prev = tokenToStartReplacing.previous; |
| + prev.setNextWithoutSettingPrevious(injected); |
| + tokenToStartReplacing = injected; |
| + tokenToStartReplacing.previous = prev; |
| + } |
| + return tokenToStartReplacing; |
| + } |
| } |
| typedef FastaMessage NoArgument(Uri uri, int charOffset); |